forked from premiere/premiere-libtorrent
modernize and improve type-safety of the DHT put implementation and test (#929)
modernize and improve type-safety of the DHT put implementation and tests. use unique_ptr instead of malloc for dht put items.
This commit is contained in:
parent
ddb274751f
commit
9c2325ff6b
2
Jamfile
2
Jamfile
|
@ -297,6 +297,8 @@ rule warnings ( properties * )
|
||||||
result += <cflags>/wd4251 ;
|
result += <cflags>/wd4251 ;
|
||||||
# disable warning C4275: non DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier'
|
# disable warning C4275: non DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier'
|
||||||
result += <cflags>/wd4275 ;
|
result += <cflags>/wd4275 ;
|
||||||
|
# disable warning C4373: virtual function overrides, previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
|
||||||
|
result += <cflags>/wd4373 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $(result) ;
|
return $(result) ;
|
||||||
|
|
|
@ -457,9 +457,9 @@ namespace
|
||||||
ses.dht_get_item(public_key, salt);
|
ses.dht_get_item(public_key, salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_string(entry& e, std::array<char, 64>& sig, std::uint64_t& seq,
|
void put_string(entry& e, std::array<char, 64>& sig, std::uint64_t& seq
|
||||||
std::string const& salt, std::string public_key, std::string private_key,
|
, std::string const& salt, std::string pk, std::string sk
|
||||||
std::string data)
|
, std::string data)
|
||||||
{
|
{
|
||||||
using libtorrent::dht::sign_mutable_item;
|
using libtorrent::dht::sign_mutable_item;
|
||||||
|
|
||||||
|
@ -467,9 +467,13 @@ namespace
|
||||||
std::vector<char> buf;
|
std::vector<char> buf;
|
||||||
bencode(std::back_inserter(buf), e);
|
bencode(std::back_inserter(buf), e);
|
||||||
++seq;
|
++seq;
|
||||||
sign_mutable_item(std::pair<char const*, int>(&buf[0], int(buf.size()))
|
dht::signature sign;
|
||||||
, std::pair<char const*, int>(&salt[0], int(salt.size()))
|
sign_mutable_item(buf, salt
|
||||||
, seq, public_key.c_str(), private_key.c_str(), sig.data());
|
, dht::sequence_number(seq)
|
||||||
|
, dht::public_key(pk.data())
|
||||||
|
, dht::secret_key(sk.data())
|
||||||
|
, sign);
|
||||||
|
sig = sign.bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dht_put_mutable_item(lt::session& ses, std::string private_key, std::string public_key,
|
void dht_put_mutable_item(lt::session& ses, std::string private_key, std::string public_key,
|
||||||
|
|
|
@ -194,6 +194,7 @@ nobase_include_HEADERS = \
|
||||||
kademlia/routing_table.hpp \
|
kademlia/routing_table.hpp \
|
||||||
kademlia/rpc_manager.hpp \
|
kademlia/rpc_manager.hpp \
|
||||||
kademlia/traversal_algorithm.hpp \
|
kademlia/traversal_algorithm.hpp \
|
||||||
|
kademlia/types.hpp \
|
||||||
kademlia/item.hpp \
|
kademlia/item.hpp \
|
||||||
kademlia/get_item.hpp \
|
kademlia/get_item.hpp \
|
||||||
kademlia/get_peers.hpp
|
kademlia/get_peers.hpp
|
||||||
|
|
|
@ -42,6 +42,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||||
|
|
||||||
#include "libtorrent/assert.hpp"
|
#include "libtorrent/assert.hpp"
|
||||||
|
#include "libtorrent/span.hpp"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
@ -238,6 +239,8 @@ struct bdecode_token
|
||||||
// There are 5 different types of nodes, see type_t.
|
// There are 5 different types of nodes, see type_t.
|
||||||
struct TORRENT_EXPORT bdecode_node
|
struct TORRENT_EXPORT bdecode_node
|
||||||
{
|
{
|
||||||
|
// TODO: 3 make this take span<char const> for buffer, and make it return a
|
||||||
|
// bdecode_node
|
||||||
TORRENT_EXPORT friend int bdecode(char const* start, char const* end, bdecode_node& ret
|
TORRENT_EXPORT friend int bdecode(char const* start, char const* end, bdecode_node& ret
|
||||||
, error_code& ec, int* error_pos, int depth_limit
|
, error_code& ec, int* error_pos, int depth_limit
|
||||||
, int token_limit);
|
, int token_limit);
|
||||||
|
@ -280,7 +283,7 @@ struct TORRENT_EXPORT bdecode_node
|
||||||
// buffer where this node is defined. For a dictionary for instance, this
|
// buffer where this node is defined. For a dictionary for instance, this
|
||||||
// starts with ``d`` and ends with ``e``, and has all the content of the
|
// starts with ``d`` and ends with ``e``, and has all the content of the
|
||||||
// dictionary in between.
|
// dictionary in between.
|
||||||
std::pair<char const*, int> data_section() const;
|
span<char const> data_section() const;
|
||||||
|
|
||||||
// functions with the ``list_`` prefix operate on lists. These functions are
|
// functions with the ``list_`` prefix operate on lists. These functions are
|
||||||
// only valid if ``type()`` == ``list_t``. ``list_at()`` returns the item
|
// only valid if ``type()`` == ``list_t``. ``list_at()`` returns the item
|
||||||
|
|
|
@ -20,6 +20,8 @@ extern "C" {
|
||||||
void TORRENT_EXPORT ed25519_create_seed(unsigned char *seed);
|
void TORRENT_EXPORT ed25519_create_seed(unsigned char *seed);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// TODO: 3 wrap these into C++ calls with proper types (dht::signature,
|
||||||
|
// public_key and secret_key)
|
||||||
void TORRENT_EXPORT ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
|
void TORRENT_EXPORT ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
|
||||||
void TORRENT_EXPORT ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
|
void TORRENT_EXPORT ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
|
||||||
int TORRENT_EXPORT ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *private_key);
|
int TORRENT_EXPORT ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *private_key);
|
||||||
|
|
|
@ -49,6 +49,7 @@ namespace libtorrent
|
||||||
namespace aux {
|
namespace aux {
|
||||||
|
|
||||||
TORRENT_EXTRA_EXPORT int hex_to_int(char in);
|
TORRENT_EXTRA_EXPORT int hex_to_int(char in);
|
||||||
|
// TODO: 3 take an span here instead
|
||||||
TORRENT_EXTRA_EXPORT bool is_hex(char const *in, int len);
|
TORRENT_EXTRA_EXPORT bool is_hex(char const *in, int len);
|
||||||
|
|
||||||
// The overload taking a ``std::string`` converts (binary) the string ``s``
|
// The overload taking a ``std::string`` converts (binary) the string ``s``
|
||||||
|
@ -58,6 +59,7 @@ namespace libtorrent
|
||||||
// ``out``. The caller is responsible for making sure the buffer pointed to
|
// ``out``. The caller is responsible for making sure the buffer pointed to
|
||||||
// by ``out`` is large enough, i.e. has at least len * 2 bytes of space.
|
// by ``out`` is large enough, i.e. has at least len * 2 bytes of space.
|
||||||
TORRENT_DEPRECATED_EXPORT std::string to_hex(std::string const& s);
|
TORRENT_DEPRECATED_EXPORT std::string to_hex(std::string const& s);
|
||||||
|
// TODO: 3 take an span here instead
|
||||||
TORRENT_DEPRECATED_EXPORT void to_hex(char const *in, int len, char* out);
|
TORRENT_DEPRECATED_EXPORT void to_hex(char const *in, int len, char* out);
|
||||||
|
|
||||||
// converts the buffer [``in``, ``in`` + len) from hexadecimal to
|
// converts the buffer [``in``, ``in`` + len) from hexadecimal to
|
||||||
|
@ -65,6 +67,7 @@ namespace libtorrent
|
||||||
// by ``out``. The caller is responsible for making sure the buffer
|
// by ``out``. The caller is responsible for making sure the buffer
|
||||||
// at ``out`` has enough space for the result to be written to, i.e.
|
// at ``out`` has enough space for the result to be written to, i.e.
|
||||||
// (len + 1) / 2 bytes.
|
// (len + 1) / 2 bytes.
|
||||||
|
// TODO: 3 take an span here instead
|
||||||
TORRENT_DEPRECATED_EXPORT bool from_hex(char const *in, int len, char* out);
|
TORRENT_DEPRECATED_EXPORT bool from_hex(char const *in, int len, char* out);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,10 +40,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||||
|
|
||||||
#include <libtorrent/kademlia/node_id.hpp>
|
#include <libtorrent/kademlia/node_id.hpp>
|
||||||
|
#include <libtorrent/kademlia/types.hpp>
|
||||||
|
|
||||||
#include <libtorrent/socket.hpp>
|
#include <libtorrent/socket.hpp>
|
||||||
#include <libtorrent/sha1_hash.hpp>
|
#include <libtorrent/sha1_hash.hpp>
|
||||||
#include <libtorrent/address.hpp>
|
#include <libtorrent/address.hpp>
|
||||||
|
#include <libtorrent/span.hpp>
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
@ -164,7 +166,7 @@ namespace dht
|
||||||
// dht_settings::max_dht_items.
|
// dht_settings::max_dht_items.
|
||||||
//
|
//
|
||||||
virtual void put_immutable_item(sha1_hash const& target
|
virtual void put_immutable_item(sha1_hash const& target
|
||||||
, char const* buf, int size
|
, span<char const> buf
|
||||||
, address const& addr) = 0;
|
, address const& addr) = 0;
|
||||||
|
|
||||||
// This function retrieves the sequence number of a mutable item.
|
// This function retrieves the sequence number of a mutable item.
|
||||||
|
@ -173,7 +175,7 @@ namespace dht
|
||||||
// inside the out parameter seq.
|
// inside the out parameter seq.
|
||||||
//
|
//
|
||||||
virtual bool get_mutable_item_seq(sha1_hash const& target
|
virtual bool get_mutable_item_seq(sha1_hash const& target
|
||||||
, std::int64_t& seq) const = 0;
|
, sequence_number& seq) const = 0;
|
||||||
|
|
||||||
// This function retrieves the mutable stored in the DHT.
|
// This function retrieves the mutable stored in the DHT.
|
||||||
//
|
//
|
||||||
|
@ -189,7 +191,7 @@ namespace dht
|
||||||
// inside the (entry) out parameter item.
|
// inside the (entry) out parameter item.
|
||||||
//
|
//
|
||||||
virtual bool get_mutable_item(sha1_hash const& target
|
virtual bool get_mutable_item(sha1_hash const& target
|
||||||
, std::int64_t seq, bool force_fill
|
, sequence_number seq, bool force_fill
|
||||||
, entry& item) const = 0;
|
, entry& item) const = 0;
|
||||||
|
|
||||||
// Store the item's data. This layer is only for storage.
|
// Store the item's data. This layer is only for storage.
|
||||||
|
@ -201,11 +203,11 @@ namespace dht
|
||||||
// dht_settings::max_dht_items.
|
// dht_settings::max_dht_items.
|
||||||
//
|
//
|
||||||
virtual void put_mutable_item(sha1_hash const& target
|
virtual void put_mutable_item(sha1_hash const& target
|
||||||
, char const* buf, int size
|
, span<char const> buf
|
||||||
, char const* sig
|
, signature const& sig
|
||||||
, std::int64_t seq
|
, sequence_number seq
|
||||||
, char const* pk
|
, public_key const& pk
|
||||||
, char const* salt, int salt_size
|
, span<char const> salt
|
||||||
, address const& addr) = 0;
|
, address const& addr) = 0;
|
||||||
|
|
||||||
// This function is called periodically (non-constant frequency).
|
// This function is called periodically (non-constant frequency).
|
||||||
|
|
|
@ -106,7 +106,7 @@ namespace libtorrent { namespace dht
|
||||||
|
|
||||||
// key is a 32-byte binary string, the public key to look up.
|
// key is a 32-byte binary string, the public key to look up.
|
||||||
// the salt is optional
|
// the salt is optional
|
||||||
void get_item(char const* key
|
void get_item(public_key const& key
|
||||||
, boost::function<void(item const&, bool)> cb
|
, boost::function<void(item const&, bool)> cb
|
||||||
, std::string salt = std::string());
|
, std::string salt = std::string());
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ namespace libtorrent { namespace dht
|
||||||
// for mutable_item.
|
// for mutable_item.
|
||||||
// the data_cb will be called when we get authoritative mutable_item,
|
// the data_cb will be called when we get authoritative mutable_item,
|
||||||
// the cb is same as put immutable_item.
|
// the cb is same as put immutable_item.
|
||||||
void put_item(char const* key
|
void put_item(public_key const& key
|
||||||
, boost::function<void(item const&, int)> cb
|
, boost::function<void(item const&, int)> cb
|
||||||
, boost::function<void(item&)> data_cb, std::string salt = std::string());
|
, boost::function<void(item&)> data_cb, std::string salt = std::string());
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ struct find_data : traversal_algorithm
|
||||||
{
|
{
|
||||||
typedef boost::function<void(std::vector<std::pair<node_entry, std::string> > const&)> nodes_callback;
|
typedef boost::function<void(std::vector<std::pair<node_entry, std::string> > const&)> nodes_callback;
|
||||||
|
|
||||||
find_data(node & node, node_id target
|
find_data(node& node, node_id target
|
||||||
, nodes_callback const& ncallback);
|
, nodes_callback const& ncallback);
|
||||||
|
|
||||||
void got_write_token(node_id const& n, std::string const& write_token);
|
void got_write_token(node_id const& n, std::string const& write_token);
|
||||||
|
|
|
@ -46,9 +46,9 @@ public:
|
||||||
typedef boost::function<void(item const&, bool)> data_callback;
|
typedef boost::function<void(item const&, bool)> data_callback;
|
||||||
|
|
||||||
void got_data(bdecode_node const& v,
|
void got_data(bdecode_node const& v,
|
||||||
char const* pk,
|
public_key const& pk,
|
||||||
std::uint64_t seq,
|
sequence_number seq,
|
||||||
char const* sig);
|
signature const& sig);
|
||||||
|
|
||||||
// for immutable itms
|
// for immutable itms
|
||||||
get_item(node& dht_node
|
get_item(node& dht_node
|
||||||
|
@ -58,8 +58,8 @@ public:
|
||||||
|
|
||||||
// for mutable items
|
// for mutable items
|
||||||
get_item(node& dht_node
|
get_item(node& dht_node
|
||||||
, char const* pk
|
, public_key const& pk
|
||||||
, std::string const& salt
|
, span<char const> salt
|
||||||
, data_callback const& dcallback
|
, data_callback const& dcallback
|
||||||
, nodes_callback const& ncallback);
|
, nodes_callback const& ncallback);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (c) 2013, Steven Siloti
|
Copyright (c) 2013, Steven Siloti, Arvid Norberg
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -36,6 +36,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <libtorrent/sha1_hash.hpp>
|
#include <libtorrent/sha1_hash.hpp>
|
||||||
#include <libtorrent/bdecode.hpp>
|
#include <libtorrent/bdecode.hpp>
|
||||||
#include <libtorrent/entry.hpp>
|
#include <libtorrent/entry.hpp>
|
||||||
|
#include <libtorrent/span.hpp>
|
||||||
|
#include <libtorrent/kademlia/types.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
@ -44,19 +47,18 @@ namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
|
|
||||||
// calculate the target hash for an immutable item.
|
// calculate the target hash for an immutable item.
|
||||||
sha1_hash TORRENT_EXTRA_EXPORT item_target_id(
|
sha1_hash TORRENT_EXTRA_EXPORT item_target_id(span<char const> v);
|
||||||
std::pair<char const*, int> v);
|
|
||||||
|
|
||||||
// calculate the target hash for a mutable item.
|
// calculate the target hash for a mutable item.
|
||||||
sha1_hash TORRENT_EXTRA_EXPORT item_target_id(std::pair<char const*, int> salt
|
sha1_hash TORRENT_EXTRA_EXPORT item_target_id(span<char const> salt
|
||||||
, char const* pk);
|
, public_key const& pk);
|
||||||
|
|
||||||
bool TORRENT_EXTRA_EXPORT verify_mutable_item(
|
bool TORRENT_EXTRA_EXPORT verify_mutable_item(
|
||||||
std::pair<char const*, int> v
|
span<char const> v
|
||||||
, std::pair<char const*, int> salt
|
, span<char const> salt
|
||||||
, std::uint64_t seq
|
, sequence_number seq
|
||||||
, char const* pk
|
, public_key const& pk
|
||||||
, char const* sig);
|
, signature const& sig);
|
||||||
|
|
||||||
// TODO: since this is a public function, it should probably be moved
|
// TODO: since this is a public function, it should probably be moved
|
||||||
// out of this header and into one with other public functions.
|
// out of this header and into one with other public functions.
|
||||||
|
@ -68,47 +70,40 @@ bool TORRENT_EXTRA_EXPORT verify_mutable_item(
|
||||||
// is responsible for allocating the destination buffer that's passed in
|
// is responsible for allocating the destination buffer that's passed in
|
||||||
// as the ``sig`` argument. Typically it would be allocated on the stack.
|
// as the ``sig`` argument. Typically it would be allocated on the stack.
|
||||||
void TORRENT_EXPORT sign_mutable_item(
|
void TORRENT_EXPORT sign_mutable_item(
|
||||||
std::pair<char const*, int> v
|
span<char const> v
|
||||||
, std::pair<char const*, int> salt
|
, span<char const> salt
|
||||||
, std::uint64_t seq
|
, sequence_number seq
|
||||||
, char const* pk
|
, public_key const& pk
|
||||||
, char const* sk
|
, secret_key const& sk
|
||||||
, char* sig);
|
, signature& sig);
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
item_pk_len = 32,
|
|
||||||
item_sk_len = 64,
|
|
||||||
item_sig_len = 64
|
|
||||||
};
|
|
||||||
|
|
||||||
class TORRENT_EXTRA_EXPORT item
|
class TORRENT_EXTRA_EXPORT item
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
item() : m_seq(0), m_mutable(false) {}
|
item() : m_seq(0), m_mutable(false) {}
|
||||||
item(char const* pk, std::string const& salt);
|
item(public_key const& pk, span<char const> salt);
|
||||||
item(entry const& v) { assign(v); }
|
item(entry v);
|
||||||
item(entry const& v
|
item(entry v
|
||||||
, std::pair<char const*, int> salt
|
, span<char const> salt
|
||||||
, std::uint64_t seq, char const* pk, char const* sk);
|
, sequence_number seq
|
||||||
item(bdecode_node const& v) { assign(v); }
|
, public_key const& pk
|
||||||
|
, secret_key const& sk);
|
||||||
|
item(bdecode_node const& v);
|
||||||
|
|
||||||
void assign(entry const& v)
|
void assign(entry v);
|
||||||
{
|
void assign(entry v, span<char const> salt
|
||||||
assign(v, std::pair<char const*, int>(static_cast<char const*>(nullptr)
|
, sequence_number seq
|
||||||
, 0), 0, nullptr, nullptr);
|
, public_key const& pk
|
||||||
}
|
, secret_key const& sk);
|
||||||
void assign(entry const& v, std::pair<char const*, int> salt
|
void assign(bdecode_node const& v);
|
||||||
, std::uint64_t seq, char const* pk, char const* sk);
|
bool assign(bdecode_node const& v, span<char const> salt
|
||||||
void assign(bdecode_node const& v)
|
, sequence_number seq
|
||||||
{
|
, public_key const& pk
|
||||||
assign(v, std::pair<char const*, int>(static_cast<char const*>(nullptr)
|
, signature const& sig);
|
||||||
, 0), 0, nullptr, nullptr);
|
void assign(entry v, span<char const> salt
|
||||||
}
|
, sequence_number seq
|
||||||
bool assign(bdecode_node const& v, std::pair<char const*, int> salt
|
, public_key const& pk
|
||||||
, std::uint64_t seq, char const* pk, char const* sig);
|
, signature const& sig);
|
||||||
void assign(entry const& v, std::string salt, std::uint64_t seq
|
|
||||||
, char const* pk, char const* sig);
|
|
||||||
|
|
||||||
void clear() { m_value = entry(); }
|
void clear() { m_value = entry(); }
|
||||||
bool empty() const { return m_value.type() == entry::undefined_t; }
|
bool empty() const { return m_value.type() == entry::undefined_t; }
|
||||||
|
@ -116,19 +111,19 @@ public:
|
||||||
bool is_mutable() const { return m_mutable; }
|
bool is_mutable() const { return m_mutable; }
|
||||||
|
|
||||||
entry const& value() const { return m_value; }
|
entry const& value() const { return m_value; }
|
||||||
std::array<char, item_pk_len> const& pk() const
|
public_key const& pk() const
|
||||||
{ return m_pk; }
|
{ return m_pk; }
|
||||||
std::array<char, item_sig_len> const& sig() const
|
signature const& sig() const
|
||||||
{ return m_sig; }
|
{ return m_sig; }
|
||||||
std::uint64_t seq() const { return m_seq; }
|
sequence_number seq() const { return m_seq; }
|
||||||
std::string const& salt() const { return m_salt; }
|
std::string const& salt() const { return m_salt; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
entry m_value;
|
entry m_value;
|
||||||
std::string m_salt;
|
std::string m_salt;
|
||||||
std::array<char, item_pk_len> m_pk;
|
public_key m_pk;
|
||||||
std::array<char, item_sig_len> m_sig;
|
signature m_sig;
|
||||||
std::uint64_t m_seq;
|
sequence_number m_seq;
|
||||||
bool m_mutable;
|
bool m_mutable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,7 @@ void incoming_error(entry& e, char const* msg, int error_code = 203);
|
||||||
// given a redundant name to avoid clashing with libtorrent::detail
|
// given a redundant name to avoid clashing with libtorrent::detail
|
||||||
namespace dht_detail {
|
namespace dht_detail {
|
||||||
|
|
||||||
|
//#error move this to its own .hpp/.cpp pair and make it take an span instead of being a template
|
||||||
TORRENT_EXPORT bool verify_message(bdecode_node const& msg, key_desc_t const desc[]
|
TORRENT_EXPORT bool verify_message(bdecode_node const& msg, key_desc_t const desc[]
|
||||||
, bdecode_node ret[], int size, char* error, int error_size);
|
, bdecode_node ret[], int size, char* error, int error_size);
|
||||||
|
|
||||||
|
|
|
@ -150,17 +150,17 @@ public:
|
||||||
, boost::function<void(msg const&)> f);
|
, boost::function<void(msg const&)> f);
|
||||||
|
|
||||||
void get_item(sha1_hash const& target, boost::function<void(item const&)> f);
|
void get_item(sha1_hash const& target, boost::function<void(item const&)> f);
|
||||||
void get_item(char const* pk, std::string const& salt, boost::function<void(item const&, bool)> f);
|
void get_item(public_key const& pk, std::string const& salt, boost::function<void(item const&, bool)> f);
|
||||||
|
|
||||||
void put_item(sha1_hash const& target, entry const& data, boost::function<void(int)> f);
|
void put_item(sha1_hash const& target, entry const& data, boost::function<void(int)> f);
|
||||||
void put_item(char const* pk, std::string const& salt
|
void put_item(public_key const& pk, std::string const& salt
|
||||||
, boost::function<void(item const&, int)> f
|
, boost::function<void(item const&, int)> f
|
||||||
, boost::function<void(item&)> data_cb);
|
, boost::function<void(item&)> data_cb);
|
||||||
|
|
||||||
bool verify_token(std::string const& token, char const* info_hash
|
bool verify_token(std::string const& token, sha1_hash const& info_hash
|
||||||
, udp::endpoint const& addr) const;
|
, udp::endpoint const& addr) const;
|
||||||
|
|
||||||
std::string generate_token(udp::endpoint const& addr, char const* info_hash);
|
std::string generate_token(udp::endpoint const& addr, sha1_hash const& info_hash);
|
||||||
|
|
||||||
// the returned time is the delay until connection_timeout()
|
// the returned time is the delay until connection_timeout()
|
||||||
// should be called again the next time
|
// should be called again the next time
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBTORRENT_TYPES_HPP
|
||||||
|
#define LIBTORRENT_TYPES_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace libtorrent { namespace dht
|
||||||
|
{
|
||||||
|
struct public_key
|
||||||
|
{
|
||||||
|
public_key() = default;
|
||||||
|
explicit public_key(char const* b)
|
||||||
|
{ std::copy(b, b + len, bytes.begin()); }
|
||||||
|
bool operator==(public_key const& rhs) const
|
||||||
|
{ return bytes == rhs.bytes; }
|
||||||
|
constexpr static int len = 32;
|
||||||
|
std::array<char, len> bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct secret_key
|
||||||
|
{
|
||||||
|
secret_key() = default;
|
||||||
|
explicit secret_key(char const* b)
|
||||||
|
{ std::copy(b, b + len, bytes.begin()); }
|
||||||
|
bool operator==(secret_key const& rhs) const
|
||||||
|
{ return bytes == rhs.bytes; }
|
||||||
|
constexpr static int len = 64;
|
||||||
|
std::array<char, len> bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct signature
|
||||||
|
{
|
||||||
|
signature() = default;
|
||||||
|
explicit signature(char const* b)
|
||||||
|
{ std::copy(b, b + len, bytes.begin()); }
|
||||||
|
bool operator==(signature const& rhs) const
|
||||||
|
{ return bytes == rhs.bytes; }
|
||||||
|
constexpr static int len = 64;
|
||||||
|
std::array<char, len> bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sequence_number
|
||||||
|
{
|
||||||
|
sequence_number() : value(0) {}
|
||||||
|
explicit sequence_number(std::uint64_t v) : value(v) {}
|
||||||
|
sequence_number(sequence_number const& sqn) = default;
|
||||||
|
bool operator<(sequence_number rhs) const
|
||||||
|
{ return value < rhs.value; }
|
||||||
|
bool operator>(sequence_number rhs) const
|
||||||
|
{ return value > rhs.value; }
|
||||||
|
sequence_number& operator=(sequence_number rhs)
|
||||||
|
{ value = rhs.value; return *this; }
|
||||||
|
bool operator<=(sequence_number rhs) const
|
||||||
|
{ return value <= rhs.value; }
|
||||||
|
bool operator==(sequence_number const& rhs) const
|
||||||
|
{ return value == rhs.value; }
|
||||||
|
sequence_number& operator++()
|
||||||
|
{ ++value; return *this; }
|
||||||
|
std::uint64_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif // LIBTORRENT_TYPES_HPP
|
||||||
|
|
|
@ -84,6 +84,7 @@ namespace libtorrent { namespace aux
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 3 use span<> here
|
||||||
int copy_buffer(char const* buf, int const size)
|
int copy_buffer(char const* buf, int const size)
|
||||||
{
|
{
|
||||||
int const ret = int(m_storage.size());
|
int const ret = int(m_storage.size());
|
||||||
|
|
|
@ -284,8 +284,8 @@ TORRENT_TEST(dht_dual_stack_mutable_item)
|
||||||
dht_network dht(sim, 100);
|
dht_network dht(sim, 100);
|
||||||
dht_network dht6(sim, 100, dht_network::bind_ipv6);
|
dht_network dht6(sim, 100, dht_network::bind_ipv6);
|
||||||
|
|
||||||
std::array<char, ed25519_private_key_size> sk;
|
lt::dht::secret_key sk;
|
||||||
std::array<char, ed25519_public_key_size> pk;
|
lt::dht::public_key pk;
|
||||||
int put_count = 0;
|
int put_count = 0;
|
||||||
bool got_item = false;
|
bool got_item = false;
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ TORRENT_TEST(dht_dual_stack_mutable_item)
|
||||||
{
|
{
|
||||||
TEST_CHECK(!got_item);
|
TEST_CHECK(!got_item);
|
||||||
if (p->authoritative)
|
if (p->authoritative)
|
||||||
got_item = p->key == pk && p->item.string() == "mutable item";
|
got_item = p->key == pk.bytes && p->item.string() == "mutable item";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// terminate?
|
// terminate?
|
||||||
|
@ -315,28 +315,28 @@ TORRENT_TEST(dht_dual_stack_mutable_item)
|
||||||
if (ticks == 2)
|
if (ticks == 2)
|
||||||
{
|
{
|
||||||
std::array<unsigned char, ed25519_seed_size> seed;
|
std::array<unsigned char, ed25519_seed_size> seed;
|
||||||
ed25519_create_keypair((unsigned char*)pk.data()
|
ed25519_create_keypair((unsigned char*)pk.bytes.data()
|
||||||
, (unsigned char*)sk.data(), seed.data());
|
, (unsigned char*)sk.bytes.data(), seed.data());
|
||||||
|
|
||||||
ses.dht_put_item(pk, [&](lt::entry& item, std::array<char, 64>& sig
|
ses.dht_put_item(pk.bytes, [&](lt::entry& item, std::array<char, 64>& sig
|
||||||
, std::uint64_t& seq, std::string const& salt)
|
, std::uint64_t& seq, std::string const& salt)
|
||||||
{
|
{
|
||||||
item = "mutable item";
|
item = "mutable item";
|
||||||
seq = 1;
|
seq = 1;
|
||||||
std::vector<char> v;
|
std::vector<char> v;
|
||||||
|
lt::dht::signature sign;
|
||||||
lt::bencode(std::back_inserter(v), item);
|
lt::bencode(std::back_inserter(v), item);
|
||||||
lt::dht::sign_mutable_item(
|
lt::dht::sign_mutable_item(v, salt
|
||||||
std::make_pair(v.data(), int(v.size()))
|
, lt::dht::sequence_number(seq), pk, sk, sign);
|
||||||
, std::make_pair(salt.data(), int(salt.size()))
|
|
||||||
, seq, pk.data(), sk.data(), sig.data());
|
|
||||||
put_count++;
|
put_count++;
|
||||||
|
sig = sign.bytes;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (ticks == 4)
|
if (ticks == 4)
|
||||||
{
|
{
|
||||||
// should be one for each stack, ipv4 and ipv6
|
// should be one for each stack, ipv4 and ipv6
|
||||||
TEST_EQUAL(put_count, 2);
|
TEST_EQUAL(put_count, 2);
|
||||||
ses.dht_get_item(pk);
|
ses.dht_get_item(pk.bytes);
|
||||||
}
|
}
|
||||||
if (ticks == 6)
|
if (ticks == 6)
|
||||||
{
|
{
|
||||||
|
|
|
@ -107,7 +107,7 @@ void test_expiration(high_resolution_clock::duration const& expiry_time
|
||||||
{
|
{
|
||||||
default_config cfg;
|
default_config cfg;
|
||||||
simulation sim(cfg);
|
simulation sim(cfg);
|
||||||
sim::asio::io_service ios(sim, asio::ip::address_v4::from_string("10.0.0.1"));
|
sim::asio::io_service ios(sim, addr("10.0.0.1"));
|
||||||
|
|
||||||
sim::asio::high_resolution_timer timer(ios);
|
sim::asio::high_resolution_timer timer(ios);
|
||||||
timer.expires_from_now(expiry_time);
|
timer.expires_from_now(expiry_time);
|
||||||
|
@ -139,16 +139,15 @@ TORRENT_TEST(dht_storage_counters)
|
||||||
s->announce_peer(n2, p3, "torrent_name1", false);
|
s->announce_peer(n2, p3, "torrent_name1", false);
|
||||||
s->announce_peer(n3, p4, "torrent_name2", false);
|
s->announce_peer(n3, p4, "torrent_name2", false);
|
||||||
|
|
||||||
s->put_immutable_item(n4, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(n4, {"123", 3}, addr("124.31.75.21"));
|
||||||
|
s->put_immutable_item(n1, {"123", 3}, addr("124.31.75.21"));
|
||||||
|
s->put_immutable_item(n2, {"123", 3}, addr("124.31.75.21"));
|
||||||
|
s->put_immutable_item(n3, {"123", 3}, addr("124.31.75.21"));
|
||||||
|
|
||||||
s->put_immutable_item(n1, "123", 3, address::from_string("124.31.75.21"));
|
dht::public_key pk;
|
||||||
s->put_immutable_item(n2, "123", 3, address::from_string("124.31.75.21"));
|
dht::signature sig;
|
||||||
s->put_immutable_item(n3, "123", 3, address::from_string("124.31.75.21"));
|
s->put_mutable_item(n4, {"123", 3}, sig, sequence_number(1), pk, {"salt", 4}
|
||||||
|
, addr("124.31.75.21"));
|
||||||
char public_key[item_pk_len];
|
|
||||||
char signature[item_sig_len];
|
|
||||||
s->put_mutable_item(n4, "123", 3, signature, 1, public_key, "salt", 4
|
|
||||||
, address::from_string("124.31.75.21"));
|
|
||||||
|
|
||||||
dht_storage_counters c;
|
dht_storage_counters c;
|
||||||
// note that we are using the aux global timer
|
// note that we are using the aux global timer
|
||||||
|
|
|
@ -1886,6 +1886,7 @@ namespace libtorrent {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 3 use span<> here
|
||||||
dht_pkt_alert::dht_pkt_alert(aux::stack_allocator& alloc
|
dht_pkt_alert::dht_pkt_alert(aux::stack_allocator& alloc
|
||||||
, char const* buf, int size, dht_pkt_alert::direction_t d, udp::endpoint ep)
|
, char const* buf, int size, dht_pkt_alert::direction_t d, udp::endpoint ep)
|
||||||
: dir(d)
|
: dir(d)
|
||||||
|
@ -1987,8 +1988,9 @@ namespace libtorrent {
|
||||||
aux::stack_allocator& alloc, void* userdata_
|
aux::stack_allocator& alloc, void* userdata_
|
||||||
, udp::endpoint const& addr_, bdecode_node const& response)
|
, udp::endpoint const& addr_, bdecode_node const& response)
|
||||||
: userdata(userdata_), addr(addr_), m_alloc(alloc)
|
: userdata(userdata_), addr(addr_), m_alloc(alloc)
|
||||||
, m_response_idx(alloc.copy_buffer(response.data_section().first, response.data_section().second))
|
, m_response_idx(alloc.copy_buffer(response.data_section().data()
|
||||||
, m_response_size(response.data_section().second)
|
, int(response.data_section().size())))
|
||||||
|
, m_response_size(int(response.data_section().size()))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
dht_direct_response_alert::dht_direct_response_alert(
|
dht_direct_response_alert::dht_direct_response_alert(
|
||||||
|
|
|
@ -303,14 +303,14 @@ namespace libtorrent
|
||||||
bdecode_node::operator bool() const
|
bdecode_node::operator bool() const
|
||||||
{ return m_token_idx != -1; }
|
{ return m_token_idx != -1; }
|
||||||
|
|
||||||
std::pair<char const*, int> bdecode_node::data_section() const
|
span<char const> bdecode_node::data_section() const
|
||||||
{
|
{
|
||||||
if (m_token_idx == -1) return std::make_pair(m_buffer, 0);
|
if (m_token_idx == -1) return span<char const>();
|
||||||
|
|
||||||
TORRENT_ASSERT(m_token_idx != -1);
|
TORRENT_ASSERT(m_token_idx != -1);
|
||||||
bdecode_token const& t = m_root_tokens[m_token_idx];
|
bdecode_token const& t = m_root_tokens[m_token_idx];
|
||||||
bdecode_token const& next = m_root_tokens[m_token_idx + t.next_item];
|
bdecode_token const& next = m_root_tokens[m_token_idx + t.next_item];
|
||||||
return std::make_pair(m_buffer + t.offset, next.offset - t.offset);
|
return { m_buffer + t.offset, size_t(next.offset - t.offset) };
|
||||||
}
|
}
|
||||||
|
|
||||||
bdecode_node bdecode_node::list_at(int i) const
|
bdecode_node bdecode_node::list_at(int i) const
|
||||||
|
|
|
@ -95,8 +95,8 @@ namespace libtorrent
|
||||||
, sha1_hash const& stream_key, bool const outgoing)
|
, sha1_hash const& stream_key, bool const outgoing)
|
||||||
{
|
{
|
||||||
hasher h;
|
hasher h;
|
||||||
static const char keyA[] = "keyA";
|
static const char keyA[] = {'k', 'e', 'y', 'A'};
|
||||||
static const char keyB[] = "keyB";
|
static const char keyB[] = {'k', 'e', 'y', 'B'};
|
||||||
|
|
||||||
// encryption rc4 longkeys
|
// encryption rc4 longkeys
|
||||||
// outgoing connection : hash ('keyA',S,SKEY)
|
// outgoing connection : hash ('keyA',S,SKEY)
|
||||||
|
@ -105,10 +105,10 @@ namespace libtorrent
|
||||||
std::array<char, 96> secret_buf;
|
std::array<char, 96> secret_buf;
|
||||||
mp::export_bits(secret, reinterpret_cast<std::uint8_t*>(secret_buf.data()), 8);
|
mp::export_bits(secret, reinterpret_cast<std::uint8_t*>(secret_buf.data()), 8);
|
||||||
|
|
||||||
if (outgoing) h.update(keyA, 4); else h.update(keyB, 4);
|
if (outgoing) h.update(keyA); else h.update(keyB);
|
||||||
h.update(secret_buf);
|
h.update(secret_buf);
|
||||||
h.update(stream_key);
|
h.update(stream_key);
|
||||||
const sha1_hash local_key = h.final();
|
sha1_hash const local_key = h.final();
|
||||||
|
|
||||||
h.reset();
|
h.reset();
|
||||||
|
|
||||||
|
@ -116,10 +116,10 @@ namespace libtorrent
|
||||||
// outgoing connection : hash ('keyB',S,SKEY)
|
// outgoing connection : hash ('keyB',S,SKEY)
|
||||||
// incoming connection : hash ('keyA',S,SKEY)
|
// incoming connection : hash ('keyA',S,SKEY)
|
||||||
|
|
||||||
if (outgoing) h.update(keyB, 4); else h.update(keyA, 4);
|
if (outgoing) h.update(keyB); else h.update(keyA);
|
||||||
h.update(secret_buf);
|
h.update(secret_buf);
|
||||||
h.update(stream_key);
|
h.update(stream_key);
|
||||||
const sha1_hash remote_key = h.final();
|
sha1_hash const remote_key = h.final();
|
||||||
|
|
||||||
boost::shared_ptr<rc4_handler> ret = boost::make_shared<rc4_handler>();
|
boost::shared_ptr<rc4_handler> ret = boost::make_shared<rc4_handler>();
|
||||||
|
|
||||||
|
@ -557,27 +557,30 @@ namespace libtorrent
|
||||||
char msg[20 + 20 + 8 + 4 + 2 + 512 + 2];
|
char msg[20 + 20 + 8 + 4 + 2 + 512 + 2];
|
||||||
char* ptr = msg;
|
char* ptr = msg;
|
||||||
|
|
||||||
|
static char const req1[4] = {'r', 'e', 'q', '1'};
|
||||||
// sync hash (hash('req1',S))
|
// sync hash (hash('req1',S))
|
||||||
h.reset();
|
h.reset();
|
||||||
h.update("req1",4);
|
h.update(req1);
|
||||||
h.update(secret);
|
h.update(secret);
|
||||||
sha1_hash const sync_hash = h.final();
|
sha1_hash const sync_hash = h.final();
|
||||||
|
|
||||||
memcpy(ptr, sync_hash.data(), 20);
|
std::memcpy(ptr, sync_hash.data(), 20);
|
||||||
ptr += 20;
|
ptr += 20;
|
||||||
|
|
||||||
|
static char const req2[4] = {'r', 'e', 'q', '2'};
|
||||||
// stream key obfuscated hash [ hash('req2',SKEY) xor hash('req3',S) ]
|
// stream key obfuscated hash [ hash('req2',SKEY) xor hash('req3',S) ]
|
||||||
h.reset();
|
h.reset();
|
||||||
h.update("req2",4);
|
h.update(req2);
|
||||||
h.update(info_hash);
|
h.update(info_hash);
|
||||||
sha1_hash const streamkey_hash = h.final();
|
sha1_hash const streamkey_hash = h.final();
|
||||||
|
|
||||||
|
static char const req3[4] = {'r', 'e', 'q', '3'};
|
||||||
h.reset();
|
h.reset();
|
||||||
h.update("req3",4);
|
h.update(req3);
|
||||||
h.update(secret);
|
h.update(secret);
|
||||||
sha1_hash const obfsc_hash = h.final() ^ streamkey_hash;
|
sha1_hash const obfsc_hash = h.final() ^ streamkey_hash;
|
||||||
|
|
||||||
memcpy(ptr, obfsc_hash.data(), 20);
|
std::memcpy(ptr, obfsc_hash.data(), 20);
|
||||||
ptr += 20;
|
ptr += 20;
|
||||||
|
|
||||||
// Discard DH key exchange data, setup RC4 keys
|
// Discard DH key exchange data, setup RC4 keys
|
||||||
|
@ -726,7 +729,7 @@ namespace libtorrent
|
||||||
// if we're encrypting this buffer, we need to make a copy
|
// if we're encrypting this buffer, we need to make a copy
|
||||||
// since we'll mutate it
|
// since we'll mutate it
|
||||||
char* buf = static_cast<char*>(malloc(size));
|
char* buf = static_cast<char*>(malloc(size));
|
||||||
memcpy(buf, buffer, size);
|
std::memcpy(buf, buffer, size);
|
||||||
append_send_buffer(buf, size, ®ular_c_free, nullptr);
|
append_send_buffer(buf, size, ®ular_c_free, nullptr);
|
||||||
destructor(const_cast<char*>(buffer), userdata, ref);
|
destructor(const_cast<char*>(buffer), userdata, ref);
|
||||||
}
|
}
|
||||||
|
@ -757,7 +760,7 @@ namespace libtorrent
|
||||||
// length of version string
|
// length of version string
|
||||||
detail::write_uint8(string_len, ptr);
|
detail::write_uint8(string_len, ptr);
|
||||||
// protocol identifier
|
// protocol identifier
|
||||||
memcpy(ptr, version_string, string_len);
|
std::memcpy(ptr, version_string, string_len);
|
||||||
ptr += string_len;
|
ptr += string_len;
|
||||||
// 8 zeroes
|
// 8 zeroes
|
||||||
memset(ptr, 0, 8);
|
memset(ptr, 0, 8);
|
||||||
|
@ -798,7 +801,7 @@ namespace libtorrent
|
||||||
|
|
||||||
// info hash
|
// info hash
|
||||||
sha1_hash const& ih = t->torrent_file().info_hash();
|
sha1_hash const& ih = t->torrent_file().info_hash();
|
||||||
memcpy(ptr, &ih[0], 20);
|
std::memcpy(ptr, ih.data(), ih.size());
|
||||||
ptr += 20;
|
ptr += 20;
|
||||||
|
|
||||||
// peer id
|
// peer id
|
||||||
|
@ -810,7 +813,7 @@ namespace libtorrent
|
||||||
m_our_peer_id[i] = random() & 0xff;
|
m_our_peer_id[i] = random() & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(ptr, &m_our_peer_id[0], 20);
|
std::memcpy(ptr, m_our_peer_id.data(), 20);
|
||||||
ptr += 20;
|
ptr += 20;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
|
@ -2632,15 +2635,14 @@ namespace libtorrent
|
||||||
if (!m_sync_hash.get())
|
if (!m_sync_hash.get())
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_sync_bytes_read == 0);
|
TORRENT_ASSERT(m_sync_bytes_read == 0);
|
||||||
hasher h;
|
|
||||||
|
|
||||||
|
static char const req1[4] = {'r', 'e', 'q', '1'};
|
||||||
// compute synchash (hash('req1',S))
|
// compute synchash (hash('req1',S))
|
||||||
std::array<char, 96> buffer;
|
std::array<char, 96> buffer;
|
||||||
mp::export_bits(m_dh_key_exchange->get_secret()
|
mp::export_bits(m_dh_key_exchange->get_secret()
|
||||||
, reinterpret_cast<std::uint8_t*>(buffer.data()), 8);
|
, reinterpret_cast<std::uint8_t*>(buffer.data()), 8);
|
||||||
h.update("req1", 4);
|
hasher h(req1);
|
||||||
h.update(buffer);
|
h.update(buffer);
|
||||||
|
|
||||||
m_sync_hash.reset(new sha1_hash(h.final()));
|
m_sync_hash.reset(new sha1_hash(h.final()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -570,7 +570,7 @@ namespace libtorrent
|
||||||
|
|
||||||
std::string split = split_path(m_files.symlink(0));
|
std::string split = split_path(m_files.symlink(0));
|
||||||
for (char const* e = split.c_str(); e != nullptr; e = next_path_element(e))
|
for (char const* e = split.c_str(); e != nullptr; e = next_path_element(e))
|
||||||
sympath_e.list().push_back(entry(e));
|
sympath_e.list().push_back(e);
|
||||||
}
|
}
|
||||||
if (!m_filehashes.empty())
|
if (!m_filehashes.empty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -85,27 +85,13 @@ namespace
|
||||||
std::set<peer_entry> peers;
|
std::set<peer_entry> peers;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
|
||||||
struct count_peers
|
|
||||||
{
|
|
||||||
int* count;
|
|
||||||
explicit count_peers(int* c): count(c) {}
|
|
||||||
void operator()(std::pair<libtorrent::sha1_hash
|
|
||||||
, torrent_entry> const& t)
|
|
||||||
{
|
|
||||||
*count += int(t.second.peers.size());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO: 2 make this configurable in dht_settings
|
// TODO: 2 make this configurable in dht_settings
|
||||||
enum { announce_interval = 30 };
|
enum { announce_interval = 30 };
|
||||||
|
|
||||||
struct dht_immutable_item
|
struct dht_immutable_item
|
||||||
{
|
{
|
||||||
dht_immutable_item() : value(nullptr), num_announcers(0), size(0) {}
|
// the actual value
|
||||||
// malloced space for the actual value
|
std::unique_ptr<char[]> value;
|
||||||
char* value;
|
|
||||||
// this counts the number of IPs we have seen
|
// this counts the number of IPs we have seen
|
||||||
// announcing this item, this is used to determine
|
// announcing this item, this is used to determine
|
||||||
// popularity if we reach the limit of items to store
|
// popularity if we reach the limit of items to store
|
||||||
|
@ -113,20 +99,17 @@ namespace
|
||||||
// the last time we heard about this
|
// the last time we heard about this
|
||||||
time_point last_seen;
|
time_point last_seen;
|
||||||
// number of IPs in the bloom filter
|
// number of IPs in the bloom filter
|
||||||
int num_announcers;
|
int num_announcers = 0;
|
||||||
// size of malloced space pointed to by value
|
// size of malloced space pointed to by value
|
||||||
int size;
|
int size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ed25519_public_key { char bytes[item_pk_len]; };
|
|
||||||
|
|
||||||
struct dht_mutable_item : dht_immutable_item
|
struct dht_mutable_item : dht_immutable_item
|
||||||
{
|
{
|
||||||
char sig[item_sig_len];
|
signature sig;
|
||||||
std::int64_t seq;
|
sequence_number seq;
|
||||||
ed25519_public_key key;
|
public_key key;
|
||||||
char* salt;
|
std::string salt;
|
||||||
int salt_size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void touch_item(dht_immutable_item* f, address const& address)
|
void touch_item(dht_immutable_item* f, address const& address)
|
||||||
|
@ -150,11 +133,12 @@ namespace
|
||||||
explicit immutable_item_comparator(std::vector<node_id> const& node_ids) : m_node_ids(node_ids) {}
|
explicit immutable_item_comparator(std::vector<node_id> const& node_ids) : m_node_ids(node_ids) {}
|
||||||
immutable_item_comparator(immutable_item_comparator const&) = default;
|
immutable_item_comparator(immutable_item_comparator const&) = default;
|
||||||
|
|
||||||
bool operator() (std::pair<node_id, dht_immutable_item> const& lhs
|
template <typename Item>
|
||||||
, std::pair<node_id, dht_immutable_item> const& rhs) const
|
bool operator()(std::pair<node_id const, Item> const& lhs
|
||||||
|
, std::pair<node_id const, Item> const& rhs) const
|
||||||
{
|
{
|
||||||
int l_distance = min_distance_exp(lhs.first, m_node_ids);
|
int const l_distance = min_distance_exp(lhs.first, m_node_ids);
|
||||||
int r_distance = min_distance_exp(rhs.first, m_node_ids);
|
int const r_distance = min_distance_exp(rhs.first, m_node_ids);
|
||||||
|
|
||||||
// this is a score taking the popularity (number of announcers) and the
|
// this is a score taking the popularity (number of announcers) and the
|
||||||
// fit, in terms of distance from ideal storing node, into account.
|
// fit, in terms of distance from ideal storing node, into account.
|
||||||
|
@ -180,16 +164,15 @@ namespace
|
||||||
typename std::map<node_id, Item>::const_iterator pick_least_important_item(
|
typename std::map<node_id, Item>::const_iterator pick_least_important_item(
|
||||||
std::vector<node_id> const& node_ids, std::map<node_id, Item> const& table)
|
std::vector<node_id> const& node_ids, std::map<node_id, Item> const& table)
|
||||||
{
|
{
|
||||||
return std::min_element(table.begin()
|
return std::min_element(table.begin(), table.end()
|
||||||
, table.end()
|
|
||||||
, immutable_item_comparator(node_ids));
|
, immutable_item_comparator(node_ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
class dht_default_storage final : public dht_storage_interface, boost::noncopyable
|
class dht_default_storage final : public dht_storage_interface, boost::noncopyable
|
||||||
{
|
{
|
||||||
typedef std::map<node_id, torrent_entry> table_t;
|
using table_t = std::map<node_id, torrent_entry>;
|
||||||
typedef std::map<node_id, dht_immutable_item> dht_immutable_table_t;
|
using dht_immutable_table_t = std::map<node_id, dht_immutable_item>;
|
||||||
typedef std::map<node_id, dht_mutable_item> dht_mutable_table_t;
|
using dht_mutable_table_t = std::map<node_id, dht_mutable_item>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -205,8 +188,9 @@ namespace
|
||||||
size_t num_torrents() const override { return m_map.size(); }
|
size_t num_torrents() const override { return m_map.size(); }
|
||||||
size_t num_peers() const override
|
size_t num_peers() const override
|
||||||
{
|
{
|
||||||
int ret = 0;
|
size_t ret = 0;
|
||||||
std::for_each(m_map.begin(), m_map.end(), count_peers(&ret));
|
for (auto const& t : m_map)
|
||||||
|
ret += t.second.peers.size();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -216,7 +200,7 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_peers(sha1_hash const& info_hash
|
bool get_peers(sha1_hash const& info_hash
|
||||||
, bool noseed, bool scrape
|
, bool const noseed, bool const scrape
|
||||||
, entry& peers) const override
|
, entry& peers) const override
|
||||||
{
|
{
|
||||||
table_t::const_iterator i = m_map.lower_bound(info_hash);
|
table_t::const_iterator i = m_map.lower_bound(info_hash);
|
||||||
|
@ -275,7 +259,7 @@ namespace
|
||||||
|
|
||||||
void announce_peer(sha1_hash const& info_hash
|
void announce_peer(sha1_hash const& info_hash
|
||||||
, tcp::endpoint const& endp
|
, tcp::endpoint const& endp
|
||||||
, std::string const& name, bool seed) override
|
, std::string const& name, bool const seed) override
|
||||||
{
|
{
|
||||||
table_t::iterator ti = m_map.find(info_hash);
|
table_t::iterator ti = m_map.find(info_hash);
|
||||||
torrent_entry* v;
|
torrent_entry* v;
|
||||||
|
@ -348,12 +332,13 @@ namespace
|
||||||
dht_immutable_table_t::const_iterator i = m_immutable_table.find(target);
|
dht_immutable_table_t::const_iterator i = m_immutable_table.find(target);
|
||||||
if (i == m_immutable_table.end()) return false;
|
if (i == m_immutable_table.end()) return false;
|
||||||
|
|
||||||
item["v"] = bdecode(i->second.value, i->second.value + i->second.size);
|
item["v"] = bdecode(i->second.value.get()
|
||||||
|
, i->second.value.get() + i->second.size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_immutable_item(sha1_hash const& target
|
void put_immutable_item(sha1_hash const& target
|
||||||
, char const* buf, int size
|
, span<char const> buf
|
||||||
, address const& addr) override
|
, address const& addr) override
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(!m_node_ids.empty());
|
TORRENT_ASSERT(!m_node_ids.empty());
|
||||||
|
@ -367,17 +352,16 @@ namespace
|
||||||
, m_immutable_table);
|
, m_immutable_table);
|
||||||
|
|
||||||
TORRENT_ASSERT(j != m_immutable_table.end());
|
TORRENT_ASSERT(j != m_immutable_table.end());
|
||||||
free(j->second.value);
|
|
||||||
m_immutable_table.erase(j);
|
m_immutable_table.erase(j);
|
||||||
m_counters.immutable_data -= 1;
|
m_counters.immutable_data -= 1;
|
||||||
}
|
}
|
||||||
dht_immutable_item to_add;
|
dht_immutable_item to_add;
|
||||||
to_add.value = static_cast<char*>(malloc(size));
|
to_add.value.reset(new char[buf.size()]);
|
||||||
to_add.size = size;
|
to_add.size = int(buf.size());
|
||||||
memcpy(to_add.value, buf, size);
|
memcpy(to_add.value.get(), buf.data(), buf.size());
|
||||||
|
|
||||||
std::tie(i, std::ignore) = m_immutable_table.insert(
|
std::tie(i, std::ignore) = m_immutable_table.insert(
|
||||||
std::make_pair(target, to_add));
|
std::make_pair(target, std::move(to_add)));
|
||||||
m_counters.immutable_data += 1;
|
m_counters.immutable_data += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +371,7 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_mutable_item_seq(sha1_hash const& target
|
bool get_mutable_item_seq(sha1_hash const& target
|
||||||
, std::int64_t& seq) const override
|
, sequence_number& seq) const override
|
||||||
{
|
{
|
||||||
dht_mutable_table_t::const_iterator i = m_mutable_table.find(target);
|
dht_mutable_table_t::const_iterator i = m_mutable_table.find(target);
|
||||||
if (i == m_mutable_table.end()) return false;
|
if (i == m_mutable_table.end()) return false;
|
||||||
|
@ -397,29 +381,29 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_mutable_item(sha1_hash const& target
|
bool get_mutable_item(sha1_hash const& target
|
||||||
, std::int64_t seq, bool force_fill
|
, sequence_number seq, bool force_fill
|
||||||
, entry& item) const override
|
, entry& item) const override
|
||||||
{
|
{
|
||||||
dht_mutable_table_t::const_iterator i = m_mutable_table.find(target);
|
dht_mutable_table_t::const_iterator i = m_mutable_table.find(target);
|
||||||
if (i == m_mutable_table.end()) return false;
|
if (i == m_mutable_table.end()) return false;
|
||||||
|
|
||||||
dht_mutable_item const& f = i->second;
|
dht_mutable_item const& f = i->second;
|
||||||
item["seq"] = f.seq;
|
item["seq"] = f.seq.value;
|
||||||
if (force_fill || (0 <= seq && seq < f.seq))
|
if (force_fill || (sequence_number(0) <= seq && seq < f.seq))
|
||||||
{
|
{
|
||||||
item["v"] = bdecode(f.value, f.value + f.size);
|
item["v"] = bdecode(f.value.get(), f.value.get() + f.size);
|
||||||
item["sig"] = std::string(f.sig, f.sig + sizeof(f.sig));
|
item["sig"] = f.sig.bytes;
|
||||||
item["k"] = std::string(f.key.bytes, f.key.bytes + sizeof(f.key.bytes));
|
item["k"] = f.key.bytes;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_mutable_item(sha1_hash const& target
|
void put_mutable_item(sha1_hash const& target
|
||||||
, char const* buf, int size
|
, span<char const> buf
|
||||||
, char const* sig
|
, signature const& sig
|
||||||
, std::int64_t seq
|
, sequence_number seq
|
||||||
, char const* pk
|
, public_key const& pk
|
||||||
, char const* salt, int salt_size
|
, span<char const> salt
|
||||||
, address const& addr) override
|
, address const& addr) override
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(!m_node_ids.empty());
|
TORRENT_ASSERT(!m_node_ids.empty());
|
||||||
|
@ -434,47 +418,37 @@ namespace
|
||||||
, m_mutable_table);
|
, m_mutable_table);
|
||||||
|
|
||||||
TORRENT_ASSERT(j != m_mutable_table.end());
|
TORRENT_ASSERT(j != m_mutable_table.end());
|
||||||
free(j->second.value);
|
|
||||||
free(j->second.salt);
|
|
||||||
m_mutable_table.erase(j);
|
m_mutable_table.erase(j);
|
||||||
m_counters.mutable_data -= 1;
|
m_counters.mutable_data -= 1;
|
||||||
}
|
}
|
||||||
dht_mutable_item to_add;
|
dht_mutable_item to_add;
|
||||||
to_add.value = static_cast<char*>(malloc(size));
|
to_add.value.reset(new char[buf.size()]);
|
||||||
to_add.size = size;
|
to_add.size = int(buf.size());
|
||||||
to_add.seq = seq;
|
to_add.seq = seq;
|
||||||
to_add.salt = nullptr;
|
to_add.salt.assign(salt.data(), salt.size());
|
||||||
to_add.salt_size = 0;
|
to_add.sig = sig;
|
||||||
if (salt_size > 0)
|
to_add.key = pk;
|
||||||
{
|
memcpy(to_add.value.get(), buf.data(), buf.size());
|
||||||
to_add.salt = static_cast<char*>(malloc(salt_size));
|
|
||||||
to_add.salt_size = salt_size;
|
|
||||||
memcpy(to_add.salt, salt, salt_size);
|
|
||||||
}
|
|
||||||
memcpy(to_add.sig, sig, sizeof(to_add.sig));
|
|
||||||
memcpy(to_add.value, buf, size);
|
|
||||||
memcpy(&to_add.key, pk, sizeof(to_add.key));
|
|
||||||
|
|
||||||
std::tie(i, std::ignore) = m_mutable_table.insert(
|
std::tie(i, std::ignore) = m_mutable_table.insert(
|
||||||
std::make_pair(target, to_add));
|
std::make_pair(target, std::move(to_add)));
|
||||||
m_counters.mutable_data += 1;
|
m_counters.mutable_data += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// this is the case where we already
|
// this is the case where we already
|
||||||
dht_mutable_item* item = &i->second;
|
dht_mutable_item& item = i->second;
|
||||||
|
|
||||||
if (item->seq < seq)
|
if (item.seq < seq)
|
||||||
{
|
{
|
||||||
if (item->size != size)
|
if (item.size != buf.size())
|
||||||
{
|
{
|
||||||
free(item->value);
|
item.value.reset(new char[buf.size()]);
|
||||||
item->value = static_cast<char*>(malloc(size));
|
item.size = int(buf.size());
|
||||||
item->size = size;
|
|
||||||
}
|
}
|
||||||
item->seq = seq;
|
item.seq = seq;
|
||||||
memcpy(item->sig, sig, sizeof(item->sig));
|
item.sig = sig;
|
||||||
memcpy(item->value, buf, size);
|
memcpy(item.value.get(), buf.data(), buf.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,7 +490,6 @@ namespace
|
||||||
++i;
|
++i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
free(i->second.value);
|
|
||||||
m_immutable_table.erase(i++);
|
m_immutable_table.erase(i++);
|
||||||
m_counters.immutable_data -= 1;
|
m_counters.immutable_data -= 1;
|
||||||
}
|
}
|
||||||
|
@ -529,8 +502,6 @@ namespace
|
||||||
++i;
|
++i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
free(i->second.value);
|
|
||||||
free(i->second.salt);
|
|
||||||
m_mutable_table.erase(i++);
|
m_mutable_table.erase(i++);
|
||||||
m_counters.mutable_data -= 1;
|
m_counters.mutable_data -= 1;
|
||||||
}
|
}
|
||||||
|
@ -556,7 +527,7 @@ namespace
|
||||||
, end(peers.end()); i != end;)
|
, end(peers.end()); i != end;)
|
||||||
{
|
{
|
||||||
// the peer has timed out
|
// the peer has timed out
|
||||||
if (i->added + minutes(int(announce_interval * 1.5f)) < aux::time_now())
|
if (i->added + minutes(int(announce_interval * 3 / 2)) < aux::time_now())
|
||||||
{
|
{
|
||||||
peers.erase(i++);
|
peers.erase(i++);
|
||||||
m_counters.peers -= 1;
|
m_counters.peers -= 1;
|
||||||
|
|
|
@ -444,7 +444,7 @@ namespace libtorrent { namespace dht
|
||||||
|
|
||||||
// key is a 32-byte binary string, the public key to look up.
|
// key is a 32-byte binary string, the public key to look up.
|
||||||
// the salt is optional
|
// the salt is optional
|
||||||
void dht_tracker::get_item(char const* key
|
void dht_tracker::get_item(public_key const& key
|
||||||
, boost::function<void(item const&, bool)> cb
|
, boost::function<void(item const&, bool)> cb
|
||||||
, std::string salt)
|
, std::string salt)
|
||||||
{
|
{
|
||||||
|
@ -461,8 +461,7 @@ namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
std::string flat_data;
|
std::string flat_data;
|
||||||
bencode(std::back_inserter(flat_data), data);
|
bencode(std::back_inserter(flat_data), data);
|
||||||
sha1_hash target = item_target_id(
|
sha1_hash const target = item_target_id(flat_data);
|
||||||
std::pair<char const*, int>(flat_data.c_str(), flat_data.size()));
|
|
||||||
|
|
||||||
boost::shared_ptr<put_item_ctx>
|
boost::shared_ptr<put_item_ctx>
|
||||||
ctx = boost::make_shared<put_item_ctx>((TORRENT_USE_IPV6) ? 2 : 1);
|
ctx = boost::make_shared<put_item_ctx>((TORRENT_USE_IPV6) ? 2 : 1);
|
||||||
|
@ -474,7 +473,7 @@ namespace libtorrent { namespace dht
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void dht_tracker::put_item(char const* key
|
void dht_tracker::put_item(public_key const& key
|
||||||
, boost::function<void(item const&, int)> cb
|
, boost::function<void(item const&, int)> cb
|
||||||
, boost::function<void(item&)> data_cb, std::string salt)
|
, boost::function<void(item&)> data_cb, std::string salt)
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,9 +45,9 @@ namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
|
|
||||||
void get_item::got_data(bdecode_node const& v,
|
void get_item::got_data(bdecode_node const& v,
|
||||||
char const* pk,
|
public_key const& pk,
|
||||||
std::uint64_t seq,
|
sequence_number const seq,
|
||||||
char const* sig)
|
signature const& sig)
|
||||||
{
|
{
|
||||||
// we received data!
|
// we received data!
|
||||||
// if no data_callback, we needn't care about the data we get.
|
// if no data_callback, we needn't care about the data we get.
|
||||||
|
@ -74,13 +74,11 @@ void get_item::got_data(bdecode_node const& v,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// immutalbe data should has been handled before this line, only mutable
|
// immutable data should have been handled before this line, only mutable
|
||||||
// data can reach here, which means pk and sig must be valid.
|
// data can reach here, which means pk, sig and seq must be valid.
|
||||||
if (!pk || !sig) return;
|
|
||||||
|
|
||||||
std::string temp_copy(m_data.salt());
|
std::string const salt_copy(m_data.salt());
|
||||||
std::pair<char const*, int> salt(temp_copy.c_str(), int(temp_copy.size()));
|
sha1_hash const incoming_target = item_target_id(salt_copy, pk);
|
||||||
sha1_hash incoming_target = item_target_id(salt, pk);
|
|
||||||
if (incoming_target != m_target) return;
|
if (incoming_target != m_target) return;
|
||||||
|
|
||||||
// this is mutable data. If it passes the signature
|
// this is mutable data. If it passes the signature
|
||||||
|
@ -88,7 +86,7 @@ void get_item::got_data(bdecode_node const& v,
|
||||||
// the highest sequence number.
|
// the highest sequence number.
|
||||||
if (m_data.empty() || m_data.seq() < seq)
|
if (m_data.empty() || m_data.seq() < seq)
|
||||||
{
|
{
|
||||||
if (!m_data.assign(v, salt, seq, pk, sig))
|
if (!m_data.assign(v, salt_copy, seq, pk, sig))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// for get_item, we should call callback when we get data,
|
// for get_item, we should call callback when we get data,
|
||||||
|
@ -114,13 +112,11 @@ get_item::get_item(
|
||||||
|
|
||||||
get_item::get_item(
|
get_item::get_item(
|
||||||
node& dht_node
|
node& dht_node
|
||||||
, char const* pk
|
, public_key const& pk
|
||||||
, std::string const& salt
|
, span<char const> salt
|
||||||
, data_callback const& dcallback
|
, data_callback const& dcallback
|
||||||
, nodes_callback const& ncallback)
|
, nodes_callback const& ncallback)
|
||||||
: find_data(dht_node, item_target_id(
|
: find_data(dht_node, item_target_id(salt, pk), ncallback)
|
||||||
std::make_pair(salt.c_str(), int(salt.size())), pk)
|
|
||||||
, ncallback)
|
|
||||||
, m_data_callback(dcallback)
|
, m_data_callback(dcallback)
|
||||||
, m_data(pk, salt)
|
, m_data(pk, salt)
|
||||||
, m_immutable(false)
|
, m_immutable(false)
|
||||||
|
@ -172,10 +168,7 @@ void get_item::done()
|
||||||
#if TORRENT_USE_ASSERTS
|
#if TORRENT_USE_ASSERTS
|
||||||
if (m_data.is_mutable())
|
if (m_data.is_mutable())
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_target
|
TORRENT_ASSERT(m_target == item_target_id(m_data.salt(), m_data.pk()));
|
||||||
== item_target_id(std::pair<char const*, int>(m_data.salt().c_str()
|
|
||||||
, m_data.salt().size())
|
|
||||||
, m_data.pk().data()));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -185,9 +178,9 @@ void get_item::done()
|
||||||
|
|
||||||
void get_item_observer::reply(msg const& m)
|
void get_item_observer::reply(msg const& m)
|
||||||
{
|
{
|
||||||
char const* pk = nullptr;
|
public_key pk;
|
||||||
char const* sig = nullptr;
|
signature sig;
|
||||||
std::uint64_t seq = 0;
|
sequence_number seq{0};
|
||||||
|
|
||||||
bdecode_node r = m.message.dict_find_dict("r");
|
bdecode_node r = m.message.dict_find_dict("r");
|
||||||
if (!r)
|
if (!r)
|
||||||
|
@ -201,17 +194,19 @@ void get_item_observer::reply(msg const& m)
|
||||||
}
|
}
|
||||||
|
|
||||||
bdecode_node k = r.dict_find_string("k");
|
bdecode_node k = r.dict_find_string("k");
|
||||||
if (k && k.string_length() == item_pk_len)
|
if (k && k.string_length() == public_key::len)
|
||||||
pk = k.string_ptr();
|
std::memcpy(pk.bytes.data(), k.string_ptr(), public_key::len);
|
||||||
|
|
||||||
bdecode_node s = r.dict_find_string("sig");
|
bdecode_node s = r.dict_find_string("sig");
|
||||||
if (s && s.string_length() == item_sig_len)
|
if (s && s.string_length() == signature::len)
|
||||||
sig = s.string_ptr();
|
std::memcpy(sig.bytes.data(), s.string_ptr(), signature::len);
|
||||||
|
|
||||||
bdecode_node q = r.dict_find_int("seq");
|
bdecode_node q = r.dict_find_int("seq");
|
||||||
if (q)
|
if (q)
|
||||||
seq = q.int_value();
|
{
|
||||||
else if (pk && sig)
|
seq = sequence_number(q.int_value());
|
||||||
|
}
|
||||||
|
else if (k && s)
|
||||||
{
|
{
|
||||||
timeout();
|
timeout();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -33,10 +33,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <libtorrent/hasher.hpp>
|
#include <libtorrent/hasher.hpp>
|
||||||
#include <libtorrent/kademlia/item.hpp>
|
#include <libtorrent/kademlia/item.hpp>
|
||||||
#include <libtorrent/bencode.hpp>
|
#include <libtorrent/bencode.hpp>
|
||||||
|
#include <libtorrent/span.hpp>
|
||||||
#include <libtorrent/ed25519.hpp>
|
#include <libtorrent/ed25519.hpp>
|
||||||
|
|
||||||
#include <cstdio> // for snprintf
|
#include <cstdio> // for snprintf
|
||||||
#include <cinttypes> // for PRId64 et.al.
|
#include <cinttypes> // for PRId64 et.al.
|
||||||
|
#include <cstring> // for memcpy
|
||||||
|
|
||||||
#if TORRENT_USE_ASSERTS
|
#if TORRENT_USE_ASSERTS
|
||||||
#include "libtorrent/bdecode.hpp"
|
#include "libtorrent/bdecode.hpp"
|
||||||
|
@ -47,67 +49,67 @@ namespace libtorrent { namespace dht
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
enum { canonical_length = 1200 };
|
int canonical_string(span<char const> v
|
||||||
int canonical_string(std::pair<char const*, int> v, std::uint64_t seq
|
, sequence_number const seq
|
||||||
, std::pair<char const*, int> salt, char out[canonical_length])
|
, span<char const> salt
|
||||||
|
, span<char> out)
|
||||||
{
|
{
|
||||||
// v must be valid bencoding!
|
// v must be valid bencoding!
|
||||||
#if TORRENT_USE_ASSERTS
|
#if TORRENT_USE_ASSERTS
|
||||||
bdecode_node e;
|
bdecode_node e;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
TORRENT_ASSERT(bdecode(v.first, v.first + v.second, e, ec) == 0);
|
TORRENT_ASSERT(bdecode(v.data(), v.data() + v.size(), e, ec) == 0);
|
||||||
#endif
|
#endif
|
||||||
char* ptr = out;
|
char* ptr = out.data();
|
||||||
|
|
||||||
int left = canonical_length - (ptr - out);
|
size_t left = out.size() - (ptr - out.data());
|
||||||
if (salt.second > 0)
|
if (salt.size() > 0)
|
||||||
{
|
{
|
||||||
ptr += std::snprintf(ptr, left, "4:salt%d:", salt.second);
|
ptr += std::snprintf(ptr, left, "4:salt%d:", int(salt.size()));
|
||||||
left = canonical_length - (ptr - out);
|
left = out.size() - (ptr - out.data());
|
||||||
memcpy(ptr, salt.first, (std::min)(salt.second, left));
|
std::memcpy(ptr, salt.data(), (std::min)(salt.size(), left));
|
||||||
ptr += (std::min)(salt.second, left);
|
ptr += (std::min)(salt.size(), left);
|
||||||
left = canonical_length - (ptr - out);
|
left = out.size() - (ptr - out.data());
|
||||||
}
|
}
|
||||||
ptr += std::snprintf(ptr, canonical_length - (ptr - out)
|
ptr += std::snprintf(ptr, out.size() - (ptr - out.data())
|
||||||
, "3:seqi%" PRId64 "e1:v", seq);
|
, "3:seqi%" PRId64 "e1:v", seq.value);
|
||||||
left = canonical_length - (ptr - out);
|
left = out.size() - (ptr - out.data());
|
||||||
memcpy(ptr, v.first, (std::min)(v.second, left));
|
std::memcpy(ptr, v.data(), (std::min)(v.size(), left));
|
||||||
ptr += (std::min)(v.second, left);
|
ptr += (std::min)(v.size(), left);
|
||||||
TORRENT_ASSERT((ptr - out) <= canonical_length);
|
TORRENT_ASSERT((ptr - out.data()) <= out.size());
|
||||||
return ptr - out;
|
return ptr - out.data();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the target hash for an immutable item.
|
// calculate the target hash for an immutable item.
|
||||||
sha1_hash item_target_id(std::pair<char const*, int> v)
|
sha1_hash item_target_id(span<char const> v)
|
||||||
{
|
{
|
||||||
return hasher(v.first, v.second).final();
|
return hasher(v).final();
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the target hash for a mutable item.
|
// calculate the target hash for a mutable item.
|
||||||
sha1_hash item_target_id(std::pair<char const*, int> salt
|
sha1_hash item_target_id(span<char const> salt
|
||||||
, char const* pk)
|
, public_key const& pk)
|
||||||
{
|
{
|
||||||
hasher h;
|
hasher h(pk.bytes);
|
||||||
h.update(pk, item_pk_len);
|
if (salt.size() > 0) h.update(salt);
|
||||||
if (salt.second > 0) h.update(salt.first, salt.second);
|
|
||||||
return h.final();
|
return h.final();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool verify_mutable_item(
|
bool verify_mutable_item(
|
||||||
std::pair<char const*, int> v
|
span<char const> v
|
||||||
, std::pair<char const*, int> salt
|
, span<char const> salt
|
||||||
, std::uint64_t seq
|
, sequence_number const seq
|
||||||
, char const* pk
|
, public_key const& pk
|
||||||
, char const* sig)
|
, signature const& sig)
|
||||||
{
|
{
|
||||||
char str[canonical_length];
|
char str[1200];
|
||||||
int len = canonical_string(v, seq, salt, str);
|
int len = canonical_string(v, seq, salt, str);
|
||||||
|
|
||||||
return ed25519_verify(reinterpret_cast<unsigned char const*>(sig)
|
return ed25519_verify(reinterpret_cast<unsigned char const*>(sig.bytes.data())
|
||||||
, reinterpret_cast<unsigned char const*>(str)
|
, reinterpret_cast<unsigned char const*>(str)
|
||||||
, len
|
, len
|
||||||
, reinterpret_cast<unsigned char const*>(pk)) == 1;
|
, reinterpret_cast<unsigned char const*>(pk.bytes.data())) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// given the bencoded buffer ``v``, the salt (which is optional and may have
|
// given the bencoded buffer ``v``, the salt (which is optional and may have
|
||||||
|
@ -117,104 +119,107 @@ bool verify_mutable_item(
|
||||||
// at least 64 bytes of available space. This space is where the signature is
|
// at least 64 bytes of available space. This space is where the signature is
|
||||||
// written.
|
// written.
|
||||||
void sign_mutable_item(
|
void sign_mutable_item(
|
||||||
std::pair<char const*, int> v
|
span<char const> v
|
||||||
, std::pair<char const*, int> salt
|
, span<char const> salt
|
||||||
, std::uint64_t seq
|
, sequence_number const seq
|
||||||
, char const* pk
|
, public_key const& pk
|
||||||
, char const* sk
|
, secret_key const& sk
|
||||||
, char* sig)
|
, signature& sig)
|
||||||
{
|
{
|
||||||
char str[canonical_length];
|
char str[1200];
|
||||||
int len = canonical_string(v, seq, salt, str);
|
int const len = canonical_string(v, seq, salt, str);
|
||||||
|
|
||||||
ed25519_sign(reinterpret_cast<unsigned char*>(sig)
|
ed25519_sign(reinterpret_cast<unsigned char*>(sig.bytes.data())
|
||||||
, reinterpret_cast<unsigned char const*>(str)
|
, reinterpret_cast<unsigned char const*>(str)
|
||||||
, len
|
, len
|
||||||
, reinterpret_cast<unsigned char const*>(pk)
|
, reinterpret_cast<unsigned char const*>(pk.bytes.data())
|
||||||
, reinterpret_cast<unsigned char const*>(sk)
|
, reinterpret_cast<unsigned char const*>(sk.bytes.data())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
item::item(char const* pk, std::string const& salt)
|
item::item(public_key const& pk, span<char const> salt)
|
||||||
: m_salt(salt)
|
: m_salt(salt.data(), salt.size())
|
||||||
|
, m_pk(pk)
|
||||||
, m_seq(0)
|
, m_seq(0)
|
||||||
, m_mutable(true)
|
, m_mutable(true)
|
||||||
|
{}
|
||||||
|
|
||||||
|
item::item(entry v)
|
||||||
|
: m_value(std::move(v))
|
||||||
|
, m_seq(0)
|
||||||
|
, m_mutable(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
item::item(bdecode_node const& v)
|
||||||
|
: m_value(std::move(v))
|
||||||
|
, m_seq(0)
|
||||||
|
, m_mutable(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
item::item(entry v, span<char const> salt
|
||||||
|
, sequence_number const seq, public_key const& pk, secret_key const& sk)
|
||||||
{
|
{
|
||||||
memcpy(m_pk.data(), pk, item_pk_len);
|
assign(std::move(v), salt, seq, pk, sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
item::item(entry const& v
|
void item::assign(entry v)
|
||||||
, std::pair<char const*, int> salt
|
|
||||||
, std::uint64_t seq, char const* pk, char const* sk)
|
|
||||||
{
|
{
|
||||||
assign(v, salt, seq, pk, sk);
|
m_mutable = false;
|
||||||
|
m_value = std::move(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void item::assign(entry const& v, std::pair<char const*, int> salt
|
void item::assign(entry v, span<char const> salt
|
||||||
, std::uint64_t seq, char const* pk, char const* sk)
|
, sequence_number const seq, public_key const& pk, secret_key const& sk)
|
||||||
{
|
{
|
||||||
m_value = v;
|
|
||||||
if (pk && sk)
|
|
||||||
{
|
|
||||||
char buffer[1000];
|
char buffer[1000];
|
||||||
int bsize = bencode(buffer, v);
|
int bsize = bencode(buffer, v);
|
||||||
TORRENT_ASSERT(bsize <= 1000);
|
TORRENT_ASSERT(bsize <= 1000);
|
||||||
sign_mutable_item(std::make_pair(buffer, bsize)
|
sign_mutable_item(span<char const>(buffer, bsize)
|
||||||
, salt, seq, pk, sk, m_sig.data());
|
, salt, seq, pk, sk, m_sig);
|
||||||
m_salt.assign(salt.first, salt.second);
|
m_salt.assign(salt.data(), salt.size());
|
||||||
memcpy(m_pk.data(), pk, item_pk_len);
|
m_pk = pk;
|
||||||
m_seq = seq;
|
m_seq = seq;
|
||||||
m_mutable = true;
|
m_mutable = true;
|
||||||
}
|
m_value = std::move(v);
|
||||||
else
|
|
||||||
m_mutable = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool item::assign(bdecode_node const& v
|
void item::assign(bdecode_node const& v)
|
||||||
, std::pair<char const*, int> salt
|
|
||||||
, std::uint64_t seq, char const* pk, char const* sig)
|
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(v.data_section().second <= 1000);
|
m_mutable = false;
|
||||||
if (pk && sig)
|
m_value = v;
|
||||||
{
|
}
|
||||||
|
|
||||||
|
bool item::assign(bdecode_node const& v, span<char const> salt
|
||||||
|
, sequence_number const seq, public_key const& pk, signature const& sig)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(v.data_section().size() <= 1000);
|
||||||
if (!verify_mutable_item(v.data_section(), salt, seq, pk, sig))
|
if (!verify_mutable_item(v.data_section(), salt, seq, pk, sig))
|
||||||
return false;
|
return false;
|
||||||
memcpy(m_pk.data(), pk, item_pk_len);
|
m_pk = pk;
|
||||||
memcpy(m_sig.data(), sig, item_sig_len);
|
m_sig = sig;
|
||||||
if (salt.second > 0)
|
if (salt.size() > 0)
|
||||||
m_salt.assign(salt.first, salt.second);
|
m_salt.assign(salt.data(), salt.size());
|
||||||
else
|
else
|
||||||
m_salt.clear();
|
m_salt.clear();
|
||||||
m_seq = seq;
|
m_seq = seq;
|
||||||
m_mutable = true;
|
m_mutable = true;
|
||||||
}
|
|
||||||
else
|
|
||||||
m_mutable = false;
|
|
||||||
|
|
||||||
m_value = v;
|
m_value = v;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void item::assign(entry const& v, std::string salt, std::uint64_t seq
|
void item::assign(entry v, span<char const> salt
|
||||||
, char const* pk, char const* sig)
|
, sequence_number const seq
|
||||||
|
, public_key const& pk, signature const& sig)
|
||||||
{
|
{
|
||||||
#if TORRENT_USE_ASSERTS
|
|
||||||
TORRENT_ASSERT(pk && sig);
|
|
||||||
char buffer[1000];
|
|
||||||
int bsize = bencode(buffer, v);
|
|
||||||
TORRENT_ASSERT(bsize <= 1000);
|
|
||||||
TORRENT_ASSERT(verify_mutable_item(
|
|
||||||
std::make_pair(buffer, bsize)
|
|
||||||
, std::make_pair(salt.data(), int(salt.size()))
|
|
||||||
, seq, pk, sig));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memcpy(m_pk.data(), pk, item_pk_len);
|
m_pk = pk;
|
||||||
memcpy(m_sig.data(), sig, item_sig_len);
|
m_sig = sig;
|
||||||
m_salt = salt;
|
m_salt.assign(salt.data(), salt.size());
|
||||||
m_seq = seq;
|
m_seq = seq;
|
||||||
m_mutable = true;
|
m_mutable = true;
|
||||||
m_value = v;
|
m_value = std::move(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
} } // namespace libtorrent::dht
|
} } // namespace libtorrent::dht
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ void node::update_node_id()
|
||||||
m_table.update_node_id(m_id);
|
m_table.update_node_id(m_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool node::verify_token(std::string const& token, char const* info_hash
|
bool node::verify_token(std::string const& token, sha1_hash const& info_hash
|
||||||
, udp::endpoint const& addr) const
|
, udp::endpoint const& addr) const
|
||||||
{
|
{
|
||||||
if (token.length() != 4)
|
if (token.length() != 4)
|
||||||
|
@ -166,7 +166,7 @@ bool node::verify_token(std::string const& token, char const* info_hash
|
||||||
if (ec) return false;
|
if (ec) return false;
|
||||||
h1.update(address);
|
h1.update(address);
|
||||||
h1.update(reinterpret_cast<char const*>(&m_secret[0]), sizeof(m_secret[0]));
|
h1.update(reinterpret_cast<char const*>(&m_secret[0]), sizeof(m_secret[0]));
|
||||||
h1.update(info_hash, 20);
|
h1.update(info_hash);
|
||||||
|
|
||||||
sha1_hash h = h1.final();
|
sha1_hash h = h1.final();
|
||||||
if (std::equal(token.begin(), token.end(), reinterpret_cast<char*>(&h[0])))
|
if (std::equal(token.begin(), token.end(), reinterpret_cast<char*>(&h[0])))
|
||||||
|
@ -175,7 +175,7 @@ bool node::verify_token(std::string const& token, char const* info_hash
|
||||||
hasher h2;
|
hasher h2;
|
||||||
h2.update(address);
|
h2.update(address);
|
||||||
h2.update(reinterpret_cast<char const*>(&m_secret[1]), sizeof(m_secret[1]));
|
h2.update(reinterpret_cast<char const*>(&m_secret[1]), sizeof(m_secret[1]));
|
||||||
h2.update(info_hash, 20);
|
h2.update(info_hash);
|
||||||
h = h2.final();
|
h = h2.final();
|
||||||
if (std::equal(token.begin(), token.end(), reinterpret_cast<char*>(&h[0])))
|
if (std::equal(token.begin(), token.end(), reinterpret_cast<char*>(&h[0])))
|
||||||
return true;
|
return true;
|
||||||
|
@ -183,7 +183,7 @@ bool node::verify_token(std::string const& token, char const* info_hash
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string node::generate_token(udp::endpoint const& addr
|
std::string node::generate_token(udp::endpoint const& addr
|
||||||
, char const* info_hash)
|
, sha1_hash const& info_hash)
|
||||||
{
|
{
|
||||||
std::string token;
|
std::string token;
|
||||||
token.resize(4);
|
token.resize(4);
|
||||||
|
@ -193,7 +193,7 @@ std::string node::generate_token(udp::endpoint const& addr
|
||||||
TORRENT_ASSERT(!ec);
|
TORRENT_ASSERT(!ec);
|
||||||
h.update(address);
|
h.update(address);
|
||||||
h.update(reinterpret_cast<char*>(&m_secret[0]), sizeof(m_secret[0]));
|
h.update(reinterpret_cast<char*>(&m_secret[0]), sizeof(m_secret[0]));
|
||||||
h.update(info_hash, 20);
|
h.update(info_hash);
|
||||||
|
|
||||||
sha1_hash const hash = h.final();
|
sha1_hash const hash = h.final();
|
||||||
std::copy(hash.begin(), hash.begin() + 4, reinterpret_cast<char*>(&token[0]));
|
std::copy(hash.begin(), hash.begin() + 4, reinterpret_cast<char*>(&token[0]));
|
||||||
|
@ -360,7 +360,7 @@ namespace
|
||||||
if (node.observer())
|
if (node.observer())
|
||||||
{
|
{
|
||||||
char hex_ih[41];
|
char hex_ih[41];
|
||||||
aux::to_hex(reinterpret_cast<char const*>(&ih[0]), 20, hex_ih);
|
aux::to_hex(ih.data(), 20, hex_ih);
|
||||||
node.observer()->log(dht_logger::node, "sending announce_peer [ ih: %s "
|
node.observer()->log(dht_logger::node, "sending announce_peer [ ih: %s "
|
||||||
" p: %d nodes: %d ]", hex_ih, listen_port, int(v.size()));
|
" p: %d nodes: %d ]", hex_ih, listen_port, int(v.size()));
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ namespace
|
||||||
e["y"] = "q";
|
e["y"] = "q";
|
||||||
e["q"] = "announce_peer";
|
e["q"] = "announce_peer";
|
||||||
entry& a = e["a"];
|
entry& a = e["a"];
|
||||||
a["info_hash"] = ih.to_string();
|
a["info_hash"] = ih;
|
||||||
a["port"] = listen_port;
|
a["port"] = listen_port;
|
||||||
a["token"] = i->second;
|
a["token"] = i->second;
|
||||||
a["seed"] = (flags & node::flag_seed) ? 1 : 0;
|
a["seed"] = (flags & node::flag_seed) ? 1 : 0;
|
||||||
|
@ -450,7 +450,7 @@ void node::announce(sha1_hash const& info_hash, int listen_port, int flags
|
||||||
if (m_observer)
|
if (m_observer)
|
||||||
{
|
{
|
||||||
char hex_ih[41];
|
char hex_ih[41];
|
||||||
aux::to_hex(reinterpret_cast<char const*>(&info_hash[0]), 20, hex_ih);
|
aux::to_hex(info_hash.data(), 20, hex_ih);
|
||||||
m_observer->log(dht_logger::node, "announcing [ ih: %s p: %d ]"
|
m_observer->log(dht_logger::node, "announcing [ ih: %s p: %d ]"
|
||||||
, hex_ih, listen_port);
|
, hex_ih, listen_port);
|
||||||
}
|
}
|
||||||
|
@ -484,7 +484,7 @@ void node::get_item(sha1_hash const& target
|
||||||
if (m_observer)
|
if (m_observer)
|
||||||
{
|
{
|
||||||
char hex_target[41];
|
char hex_target[41];
|
||||||
aux::to_hex(reinterpret_cast<char const*>(&target[0]), 20, hex_target);
|
aux::to_hex(target.data(), 20, hex_target);
|
||||||
m_observer->log(dht_logger::node, "starting get for [ hash: %s ]"
|
m_observer->log(dht_logger::node, "starting get for [ hash: %s ]"
|
||||||
, hex_target);
|
, hex_target);
|
||||||
}
|
}
|
||||||
|
@ -495,14 +495,14 @@ void node::get_item(sha1_hash const& target
|
||||||
ta->start();
|
ta->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void node::get_item(char const* pk, std::string const& salt
|
void node::get_item(public_key const& pk, std::string const& salt
|
||||||
, boost::function<void(item const&, bool)> f)
|
, boost::function<void(item const&, bool)> f)
|
||||||
{
|
{
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
if (m_observer)
|
if (m_observer)
|
||||||
{
|
{
|
||||||
char hex_key[65];
|
char hex_key[65];
|
||||||
aux::to_hex(pk, 32, hex_key);
|
aux::to_hex(pk.bytes.data(), 32, hex_key);
|
||||||
m_observer->log(dht_logger::node, "starting get for [ key: %s ]", hex_key);
|
m_observer->log(dht_logger::node, "starting get for [ key: %s ]", hex_key);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -559,7 +559,7 @@ void node::put_item(sha1_hash const& target, entry const& data, boost::function<
|
||||||
ta->start();
|
ta->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void node::put_item(char const* pk, std::string const& salt
|
void node::put_item(public_key const& pk, std::string const& salt
|
||||||
, boost::function<void(item const&, int)> f
|
, boost::function<void(item const&, int)> f
|
||||||
, boost::function<void(item&)> data_cb)
|
, boost::function<void(item&)> data_cb)
|
||||||
{
|
{
|
||||||
|
@ -567,7 +567,7 @@ void node::put_item(char const* pk, std::string const& salt
|
||||||
if (m_observer)
|
if (m_observer)
|
||||||
{
|
{
|
||||||
char hex_key[65];
|
char hex_key[65];
|
||||||
aux::to_hex(pk, 32, hex_key);
|
aux::to_hex(pk.bytes.data(), 32, hex_key);
|
||||||
m_observer->log(dht_logger::node, "starting get for [ key: %s ]", hex_key);
|
m_observer->log(dht_logger::node, "starting get for [ key: %s ]", hex_key);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -866,7 +866,7 @@ void node::incoming_request(msg const& m, entry& e)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reply["token"] = generate_token(m.addr, msg_keys[0].string_ptr());
|
reply["token"] = generate_token(m.addr, sha1_hash(msg_keys[0].string_ptr()));
|
||||||
|
|
||||||
m_counters.inc_stats_counter(counters::dht_get_peers_in);
|
m_counters.inc_stats_counter(counters::dht_get_peers_in);
|
||||||
|
|
||||||
|
@ -944,7 +944,8 @@ void node::incoming_request(msg const& m, entry& e)
|
||||||
if (m_observer)
|
if (m_observer)
|
||||||
m_observer->announce(info_hash, m.addr.address(), port);
|
m_observer->announce(info_hash, m.addr.address(), port);
|
||||||
|
|
||||||
if (!verify_token(msg_keys[2].string_value(), msg_keys[0].string_ptr(), m.addr))
|
if (!verify_token(msg_keys[2].string_value()
|
||||||
|
, sha1_hash(msg_keys[0].string_ptr()), m.addr))
|
||||||
{
|
{
|
||||||
m_counters.inc_stats_counter(counters::dht_invalid_announce);
|
m_counters.inc_stats_counter(counters::dht_invalid_announce);
|
||||||
incoming_error(e, "invalid token");
|
incoming_error(e, "invalid token");
|
||||||
|
@ -973,8 +974,8 @@ void node::incoming_request(msg const& m, entry& e)
|
||||||
{"v", bdecode_node::none_t, 0, 0},
|
{"v", bdecode_node::none_t, 0, 0},
|
||||||
{"seq", bdecode_node::int_t, 0, key_desc_t::optional},
|
{"seq", bdecode_node::int_t, 0, key_desc_t::optional},
|
||||||
// public key
|
// public key
|
||||||
{"k", bdecode_node::string_t, item_pk_len, key_desc_t::optional},
|
{"k", bdecode_node::string_t, public_key::len, key_desc_t::optional},
|
||||||
{"sig", bdecode_node::string_t, item_sig_len, key_desc_t::optional},
|
{"sig", bdecode_node::string_t, signature::len, key_desc_t::optional},
|
||||||
{"cas", bdecode_node::int_t, 0, key_desc_t::optional},
|
{"cas", bdecode_node::int_t, 0, key_desc_t::optional},
|
||||||
{"salt", bdecode_node::string_t, 0, key_desc_t::optional},
|
{"salt", bdecode_node::string_t, 0, key_desc_t::optional},
|
||||||
};
|
};
|
||||||
|
@ -994,38 +995,35 @@ void node::incoming_request(msg const& m, entry& e)
|
||||||
bool mutable_put = (msg_keys[2] && msg_keys[3] && msg_keys[4]);
|
bool mutable_put = (msg_keys[2] && msg_keys[3] && msg_keys[4]);
|
||||||
|
|
||||||
// public key (only set if it's a mutable put)
|
// public key (only set if it's a mutable put)
|
||||||
char const* pk = nullptr;
|
char const* pub_key = nullptr;
|
||||||
if (msg_keys[3]) pk = msg_keys[3].string_ptr();
|
if (msg_keys[3]) pub_key = msg_keys[3].string_ptr();
|
||||||
|
|
||||||
// signature (only set if it's a mutable put)
|
// signature (only set if it's a mutable put)
|
||||||
char const* sig = nullptr;
|
char const* sign = nullptr;
|
||||||
if (msg_keys[4]) sig = msg_keys[4].string_ptr();
|
if (msg_keys[4]) sign = msg_keys[4].string_ptr();
|
||||||
|
|
||||||
// pointer and length to the whole entry
|
// pointer and length to the whole entry
|
||||||
std::pair<char const*, int> buf = msg_keys[1].data_section();
|
span<char const> buf = msg_keys[1].data_section();
|
||||||
if (buf.second > 1000 || buf.second <= 0)
|
if (buf.size() > 1000 || buf.size() <= 0)
|
||||||
{
|
{
|
||||||
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
||||||
incoming_error(e, "message too big", 205);
|
incoming_error(e, "message too big", 205);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<char const*, int> salt(static_cast<char const*>(nullptr), 0);
|
span<char const> salt;
|
||||||
if (msg_keys[6])
|
if (msg_keys[6])
|
||||||
salt = std::pair<char const*, int>(
|
salt = { msg_keys[6].string_ptr(), size_t(msg_keys[6].string_length()) };
|
||||||
msg_keys[6].string_ptr(), msg_keys[6].string_length());
|
if (salt.size() > 64)
|
||||||
if (salt.second > 64)
|
|
||||||
{
|
{
|
||||||
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
||||||
incoming_error(e, "salt too big", 207);
|
incoming_error(e, "salt too big", 207);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sha1_hash target;
|
sha1_hash const target = pub_key
|
||||||
if (pk)
|
? item_target_id(salt, public_key(pub_key))
|
||||||
target = item_target_id(salt, pk);
|
: item_target_id(buf);
|
||||||
else
|
|
||||||
target = item_target_id(buf);
|
|
||||||
|
|
||||||
// std::fprintf(stderr, "%s PUT target: %s salt: %s key: %s\n"
|
// std::fprintf(stderr, "%s PUT target: %s salt: %s key: %s\n"
|
||||||
// , mutable_put ? "mutable":"immutable"
|
// , mutable_put ? "mutable":"immutable"
|
||||||
|
@ -1035,8 +1033,7 @@ void node::incoming_request(msg const& m, entry& e)
|
||||||
|
|
||||||
// verify the write-token. tokens are only valid to write to
|
// verify the write-token. tokens are only valid to write to
|
||||||
// specific target hashes. it must match the one we got a "get" for
|
// specific target hashes. it must match the one we got a "get" for
|
||||||
if (!verify_token(msg_keys[0].string_value()
|
if (!verify_token(msg_keys[0].string_value(), target, m.addr))
|
||||||
, reinterpret_cast<char const*>(&target[0]), m.addr))
|
|
||||||
{
|
{
|
||||||
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
||||||
incoming_error(e, "invalid token");
|
incoming_error(e, "invalid token");
|
||||||
|
@ -1045,14 +1042,16 @@ void node::incoming_request(msg const& m, entry& e)
|
||||||
|
|
||||||
if (!mutable_put)
|
if (!mutable_put)
|
||||||
{
|
{
|
||||||
m_storage.put_immutable_item(target, buf.first, buf.second, m.addr.address());
|
m_storage.put_immutable_item(target, buf, m.addr.address());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// mutable put, we must verify the signature
|
// mutable put, we must verify the signature
|
||||||
std::int64_t const seq = msg_keys[2].int_value();
|
sequence_number const seq(msg_keys[2].int_value());
|
||||||
|
public_key const pk(pub_key);
|
||||||
|
signature const sig(sign);
|
||||||
|
|
||||||
if (seq < 0)
|
if (seq < sequence_number(0))
|
||||||
{
|
{
|
||||||
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
||||||
incoming_error(e, "invalid (negative) sequence number");
|
incoming_error(e, "invalid (negative) sequence number");
|
||||||
|
@ -1060,23 +1059,19 @@ void node::incoming_request(msg const& m, entry& e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// msg_keys[4] is the signature, msg_keys[3] is the public key
|
// msg_keys[4] is the signature, msg_keys[3] is the public key
|
||||||
if (!verify_mutable_item(buf, salt
|
if (!verify_mutable_item(buf, salt, seq, pk, sig))
|
||||||
, seq, pk, sig))
|
|
||||||
{
|
{
|
||||||
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
||||||
incoming_error(e, "invalid signature", 206);
|
incoming_error(e, "invalid signature", 206);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(item_sig_len == msg_keys[4].string_length());
|
TORRENT_ASSERT(signature::len == msg_keys[4].string_length());
|
||||||
|
|
||||||
std::int64_t item_seq;
|
sequence_number item_seq;
|
||||||
if (!m_storage.get_mutable_item_seq(target, item_seq))
|
if (!m_storage.get_mutable_item_seq(target, item_seq))
|
||||||
{
|
{
|
||||||
m_storage.put_mutable_item(target
|
m_storage.put_mutable_item(target, buf, sig, seq, pk, salt
|
||||||
, buf.first, buf.second
|
|
||||||
, sig, seq, pk
|
|
||||||
, salt.first, salt.second
|
|
||||||
, m.addr.address());
|
, m.addr.address());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1086,7 +1081,7 @@ void node::incoming_request(msg const& m, entry& e)
|
||||||
// number matches the expected value before replacing it
|
// number matches the expected value before replacing it
|
||||||
// this is critical for avoiding race conditions when multiple
|
// this is critical for avoiding race conditions when multiple
|
||||||
// writers are accessing the same slot
|
// writers are accessing the same slot
|
||||||
if (msg_keys[5] && item_seq != msg_keys[5].int_value())
|
if (msg_keys[5] && item_seq.value != msg_keys[5].int_value())
|
||||||
{
|
{
|
||||||
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
m_counters.inc_stats_counter(counters::dht_invalid_put);
|
||||||
incoming_error(e, "CAS mismatch", 301);
|
incoming_error(e, "CAS mismatch", 301);
|
||||||
|
@ -1100,10 +1095,7 @@ void node::incoming_request(msg const& m, entry& e)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_storage.put_mutable_item(target
|
m_storage.put_mutable_item(target, buf, sig, seq, pk, salt
|
||||||
, buf.first, buf.second
|
|
||||||
, sig, seq, pk
|
|
||||||
, salt.first, salt.second
|
|
||||||
, m.addr.address());
|
, m.addr.address());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1137,7 +1129,7 @@ void node::incoming_request(msg const& m, entry& e)
|
||||||
// , msg_keys[1] ? "mutable":"immutable"
|
// , msg_keys[1] ? "mutable":"immutable"
|
||||||
// , aux::to_hex(target.to_string()).c_str());
|
// , aux::to_hex(target.to_string()).c_str());
|
||||||
|
|
||||||
reply["token"] = generate_token(m.addr, msg_keys[1].string_ptr());
|
reply["token"] = generate_token(m.addr, sha1_hash(msg_keys[1].string_ptr()));
|
||||||
|
|
||||||
// always return nodes as well as peers
|
// always return nodes as well as peers
|
||||||
write_nodes_entries(target, msg_keys[2], reply);
|
write_nodes_entries(target, msg_keys[2], reply);
|
||||||
|
@ -1148,13 +1140,14 @@ void node::incoming_request(msg const& m, entry& e)
|
||||||
{
|
{
|
||||||
if (!m_storage.get_immutable_item(target, reply)) // ok, check for a mutable one
|
if (!m_storage.get_immutable_item(target, reply)) // ok, check for a mutable one
|
||||||
{
|
{
|
||||||
m_storage.get_mutable_item(target, 0, true, reply);
|
m_storage.get_mutable_item(target, sequence_number(0)
|
||||||
|
, true, reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_storage.get_mutable_item(target
|
m_storage.get_mutable_item(target
|
||||||
, msg_keys[0].int_value(), false
|
, sequence_number(msg_keys[0].int_value()), false
|
||||||
, reply);
|
, reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,9 +106,9 @@ bool put_data::invoke(observer_ptr o)
|
||||||
a["token"] = po->m_token;
|
a["token"] = po->m_token;
|
||||||
if (m_data.is_mutable())
|
if (m_data.is_mutable())
|
||||||
{
|
{
|
||||||
a["k"] = std::string(m_data.pk().data(), item_pk_len);
|
a["k"] = m_data.pk().bytes;
|
||||||
a["seq"] = m_data.seq();
|
a["seq"] = m_data.seq().value;
|
||||||
a["sig"] = std::string(m_data.sig().data(), item_sig_len);
|
a["sig"] = m_data.sig().bytes;
|
||||||
if (!m_data.salt().empty())
|
if (!m_data.salt().empty())
|
||||||
{
|
{
|
||||||
a["salt"] = m_data.salt();
|
a["salt"] = m_data.salt();
|
||||||
|
|
|
@ -96,11 +96,9 @@ namespace libtorrent
|
||||||
std::array<char, 96> buffer;
|
std::array<char, 96> buffer;
|
||||||
mp::export_bits(m_dh_shared_secret, reinterpret_cast<std::uint8_t*>(buffer.data()), 8);
|
mp::export_bits(m_dh_shared_secret, reinterpret_cast<std::uint8_t*>(buffer.data()), 8);
|
||||||
|
|
||||||
|
static char const req3[4] = {'r', 'e', 'q', '3'};
|
||||||
// calculate the xor mask for the obfuscated hash
|
// calculate the xor mask for the obfuscated hash
|
||||||
hasher h;
|
m_xor_mask = hasher(req3).update(buffer).final();
|
||||||
h.update("req3", 4);
|
|
||||||
h.update(buffer);
|
|
||||||
m_xor_mask = h.final();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<int, span<aux::const_buffer>>
|
std::tuple<int, span<aux::const_buffer>>
|
||||||
|
@ -148,7 +146,7 @@ namespace libtorrent
|
||||||
if (num_bufs != 0)
|
if (num_bufs != 0)
|
||||||
{
|
{
|
||||||
std::tie(next_barrier, out_iovec)
|
std::tie(next_barrier, out_iovec)
|
||||||
= m_send_barriers.front().enc_handler->encrypt({bufs, num_bufs});
|
= m_send_barriers.front().enc_handler->encrypt({bufs, size_t(num_bufs)});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_send_barriers.front().next != INT_MAX)
|
if (m_send_barriers.front().next != INT_MAX)
|
||||||
|
|
|
@ -97,8 +97,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
// verify the info-hash of the metadata stored in the resume file matches
|
// verify the info-hash of the metadata stored in the resume file matches
|
||||||
// the torrent we're loading
|
// the torrent we're loading
|
||||||
sha1_hash const resume_ih = hasher(info.data_section().first
|
sha1_hash const resume_ih = hasher(info.data_section()).final();
|
||||||
, info.data_section().second).final();
|
|
||||||
|
|
||||||
// if url is set, the info_hash is not actually the info-hash of the
|
// if url is set, the info_hash is not actually the info-hash of the
|
||||||
// torrent, but the hash of the URL, until we have the full torrent
|
// torrent, but the hash of the URL, until we have the full torrent
|
||||||
|
|
|
@ -521,6 +521,8 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 3 expose the sequence_number, public_key, secret_key and signature
|
||||||
|
// types to the client
|
||||||
sha1_hash session_handle::dht_put_item(entry data)
|
sha1_hash session_handle::dht_put_item(entry data)
|
||||||
{
|
{
|
||||||
std::vector<char> buf;
|
std::vector<char> buf;
|
||||||
|
|
|
@ -81,6 +81,7 @@ const rlim_t rlim_infinity = RLIM_INFINITY;
|
||||||
#include "libtorrent/aux_/session_impl.hpp"
|
#include "libtorrent/aux_/session_impl.hpp"
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
#include "libtorrent/kademlia/dht_tracker.hpp"
|
#include "libtorrent/kademlia/dht_tracker.hpp"
|
||||||
|
#include "libtorrent/kademlia/types.hpp"
|
||||||
#endif
|
#endif
|
||||||
#include "libtorrent/enum_net.hpp"
|
#include "libtorrent/enum_net.hpp"
|
||||||
#include "libtorrent/config.hpp"
|
#include "libtorrent/config.hpp"
|
||||||
|
@ -4716,9 +4717,9 @@ namespace aux {
|
||||||
TORRENT_ASSERT(m_torrents.size() >= m_torrent_lru.size());
|
TORRENT_ASSERT(m_torrents.size() >= m_torrent_lru.size());
|
||||||
|
|
||||||
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
hasher h;
|
static char const req2[4] = {'r', 'e', 'q', '2'};
|
||||||
h.update("req2", 4);
|
hasher h(req2);
|
||||||
h.update(params.info_hash.data(), 20);
|
h.update(params.info_hash);
|
||||||
// this is SHA1("req2" + info-hash), used for
|
// this is SHA1("req2" + info-hash), used for
|
||||||
// encrypted hand shakes
|
// encrypted hand shakes
|
||||||
m_obfuscated_torrents.insert(std::make_pair(h.final(), torrent_ptr));
|
m_obfuscated_torrents.insert(std::make_pair(h.final(), torrent_ptr));
|
||||||
|
@ -5044,8 +5045,7 @@ namespace aux {
|
||||||
if (i == m_torrents.end() && !tptr->url().empty())
|
if (i == m_torrents.end() && !tptr->url().empty())
|
||||||
{
|
{
|
||||||
std::string const& url = tptr->url();
|
std::string const& url = tptr->url();
|
||||||
sha1_hash urlhash = hasher(&url[0], int(url.size())).final();
|
i = m_torrents.find(hasher(url).final());
|
||||||
i = m_torrents.find(urlhash);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -5085,9 +5085,9 @@ namespace aux {
|
||||||
TORRENT_ASSERT(m_torrents.size() >= m_torrent_lru.size());
|
TORRENT_ASSERT(m_torrents.size() >= m_torrent_lru.size());
|
||||||
|
|
||||||
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
hasher h;
|
static char const req2[4] = {'r', 'e', 'q', '2'};
|
||||||
h.update("req2", 4);
|
hasher h(req2);
|
||||||
h.update(tptr->info_hash().data(), 20);
|
h.update(tptr->info_hash());
|
||||||
m_obfuscated_torrents.erase(h.final());
|
m_obfuscated_torrents.erase(h.final());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -5714,20 +5714,23 @@ namespace aux {
|
||||||
}
|
}
|
||||||
|
|
||||||
// callback for dht_mutable_get
|
// callback for dht_mutable_get
|
||||||
void session_impl::get_mutable_callback(dht::item const& i, bool authoritative)
|
void session_impl::get_mutable_callback(dht::item const& i
|
||||||
|
, bool const authoritative)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(i.is_mutable());
|
TORRENT_ASSERT(i.is_mutable());
|
||||||
m_alerts.emplace_alert<dht_mutable_item_alert>(i.pk(), i.sig(), i.seq()
|
m_alerts.emplace_alert<dht_mutable_item_alert>(i.pk().bytes
|
||||||
|
, i.sig().bytes, i.seq().value
|
||||||
, i.salt(), i.value(), authoritative);
|
, i.salt(), i.value(), authoritative);
|
||||||
}
|
}
|
||||||
|
|
||||||
// key is a 32-byte binary string, the public key to look up.
|
// key is a 32-byte binary string, the public key to look up.
|
||||||
// the salt is optional
|
// the salt is optional
|
||||||
|
// TODO: 3 use public_key here instead of std::array
|
||||||
void session_impl::dht_get_mutable_item(std::array<char, 32> key
|
void session_impl::dht_get_mutable_item(std::array<char, 32> key
|
||||||
, std::string salt)
|
, std::string salt)
|
||||||
{
|
{
|
||||||
if (!m_dht) return;
|
if (!m_dht) return;
|
||||||
m_dht->get_item(key.data(), std::bind(&session_impl::get_mutable_callback
|
m_dht->get_item(dht::public_key(key.data()), std::bind(&session_impl::get_mutable_callback
|
||||||
, this, _1, _2), salt);
|
, this, _1, _2), salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5741,26 +5744,29 @@ namespace aux {
|
||||||
|
|
||||||
void on_dht_put_mutable_item(alert_manager& alerts, dht::item const& i, int num)
|
void on_dht_put_mutable_item(alert_manager& alerts, dht::item const& i, int num)
|
||||||
{
|
{
|
||||||
std::array<char, 64> sig = i.sig();
|
dht::signature sig = i.sig();
|
||||||
std::array<char, 32> pk = i.pk();
|
dht::public_key pk = i.pk();
|
||||||
std::uint64_t seq = i.seq();
|
dht::sequence_number seq = i.seq();
|
||||||
std::string salt = i.salt();
|
std::string salt = i.salt();
|
||||||
|
|
||||||
if (alerts.should_post<dht_put_alert>())
|
if (alerts.should_post<dht_put_alert>())
|
||||||
alerts.emplace_alert<dht_put_alert>(pk, sig, salt, seq, num);
|
{
|
||||||
|
alerts.emplace_alert<dht_put_alert>(pk.bytes, sig.bytes, salt
|
||||||
|
, seq.value, num);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_mutable_callback(dht::item& i
|
void put_mutable_callback(dht::item& i
|
||||||
, boost::function<void(entry&, std::array<char,64>&
|
, boost::function<void(entry&, std::array<char, 64>&
|
||||||
, std::uint64_t&, std::string const&)> cb)
|
, std::uint64_t&, std::string const&)> cb)
|
||||||
{
|
{
|
||||||
entry value = i.value();
|
entry value = i.value();
|
||||||
std::array<char, 64> sig = i.sig();
|
dht::signature sig = i.sig();
|
||||||
std::array<char, 32> pk = i.pk();
|
dht::public_key pk = i.pk();
|
||||||
std::uint64_t seq = i.seq();
|
dht::sequence_number seq = i.seq();
|
||||||
std::string salt = i.salt();
|
std::string salt = i.salt();
|
||||||
cb(value, sig, seq, salt);
|
cb(value, sig.bytes, seq.value, salt);
|
||||||
i.assign(value, salt, seq, pk.data(), sig.data());
|
i.assign(std::move(value), salt, seq, pk, sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_dht_get_peers(alert_manager& alerts, sha1_hash info_hash, std::vector<tcp::endpoint> const& peers)
|
void on_dht_get_peers(alert_manager& alerts, sha1_hash info_hash, std::vector<tcp::endpoint> const& peers)
|
||||||
|
@ -5792,9 +5798,9 @@ namespace aux {
|
||||||
, std::string salt)
|
, std::string salt)
|
||||||
{
|
{
|
||||||
if (!m_dht) return;
|
if (!m_dht) return;
|
||||||
m_dht->put_item(key.data(),
|
m_dht->put_item(dht::public_key(key.data())
|
||||||
std::bind(&on_dht_put_mutable_item, boost::ref(m_alerts), _1, _2),
|
, std::bind(&on_dht_put_mutable_item, boost::ref(m_alerts), _1, _2)
|
||||||
std::bind(&put_mutable_callback, _1, cb), salt);
|
, std::bind(&put_mutable_callback, _1, cb), salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::dht_get_peers(sha1_hash const& info_hash)
|
void session_impl::dht_get_peers(sha1_hash const& info_hash)
|
||||||
|
|
|
@ -195,7 +195,7 @@ namespace
|
||||||
h.update(j->buffer.disk_block, j->d.io.buffer_size);
|
h.update(j->buffer.disk_block, j->d.io.buffer_size);
|
||||||
h.update(reinterpret_cast<char const*>(&m_salt), sizeof(m_salt));
|
h.update(reinterpret_cast<char const*>(&m_salt), sizeof(m_salt));
|
||||||
|
|
||||||
std::pair<peer_list::iterator, peer_list::iterator> range
|
std::pair<peer_list::iterator, peer_list::iterator> const range
|
||||||
= m_torrent.find_peers(a);
|
= m_torrent.find_peers(a);
|
||||||
|
|
||||||
// there is no peer with this address anymore
|
// there is no peer with this address anymore
|
||||||
|
@ -270,7 +270,7 @@ namespace
|
||||||
hasher h;
|
hasher h;
|
||||||
h.update(j->buffer.disk_block, j->d.io.buffer_size);
|
h.update(j->buffer.disk_block, j->d.io.buffer_size);
|
||||||
h.update(reinterpret_cast<char const*>(&m_salt), sizeof(m_salt));
|
h.update(reinterpret_cast<char const*>(&m_salt), sizeof(m_salt));
|
||||||
sha1_hash ok_digest = h.final();
|
sha1_hash const ok_digest = h.final();
|
||||||
|
|
||||||
if (b.second.digest == ok_digest) return;
|
if (b.second.digest == ok_digest) return;
|
||||||
|
|
||||||
|
|
|
@ -537,8 +537,8 @@ namespace libtorrent
|
||||||
m_web_seeds.insert(m_web_seeds.end(), web_seeds.begin(), web_seeds.end());
|
m_web_seeds.insert(m_web_seeds.end(), web_seeds.begin(), web_seeds.end());
|
||||||
|
|
||||||
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
#if !defined(TORRENT_DISABLE_ENCRYPTION) && !defined(TORRENT_DISABLE_EXTENSIONS)
|
||||||
hasher h;
|
static char const req2[4] = {'r', 'e', 'q', '2'};
|
||||||
h.update("req2", 4);
|
hasher h(req2);
|
||||||
h.update(m_torrent_file->info_hash());
|
h.update(m_torrent_file->info_hash());
|
||||||
m_ses.add_obfuscated_hash(h.final(), shared_from_this());
|
m_ses.add_obfuscated_hash(h.final(), shared_from_this());
|
||||||
#endif
|
#endif
|
||||||
|
@ -7011,6 +7011,7 @@ namespace libtorrent
|
||||||
return peerinfo->connection != nullptr;
|
return peerinfo->connection != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 3 make this take a span<char const> instead
|
||||||
bool torrent::set_metadata(char const* metadata_buf, int metadata_size)
|
bool torrent::set_metadata(char const* metadata_buf, int metadata_size)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(is_single_thread());
|
TORRENT_ASSERT(is_single_thread());
|
||||||
|
@ -7031,7 +7032,8 @@ namespace libtorrent
|
||||||
|
|
||||||
bdecode_node metadata;
|
bdecode_node metadata;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
int ret = bdecode(metadata_buf, metadata_buf + metadata_size, metadata, ec);
|
int ret = bdecode(metadata_buf
|
||||||
|
, metadata_buf + metadata_size, metadata, ec);
|
||||||
if (ret != 0 || !m_torrent_file->parse_info_section(metadata, ec, 0))
|
if (ret != 0 || !m_torrent_file->parse_info_section(metadata, ec, 0))
|
||||||
{
|
{
|
||||||
update_gauge();
|
update_gauge();
|
||||||
|
|
|
@ -1050,28 +1050,25 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash the info-field to calculate info-hash
|
// hash the info-field to calculate info-hash
|
||||||
hasher h;
|
auto section = info.data_section();
|
||||||
std::pair<char const*, int> section = info.data_section();
|
m_info_hash = hasher(section).final();
|
||||||
h.update(section.first, section.second);
|
if (info.data_section().size() >= (std::numeric_limits<std::uint32_t>::max)())
|
||||||
m_info_hash = h.final();
|
|
||||||
|
|
||||||
if (section.second >= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
{
|
||||||
ec = errors::metadata_too_large;
|
ec = errors::metadata_too_large;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy the info section
|
// copy the info section
|
||||||
m_info_section_size = section.second;
|
m_info_section_size = int(section.size());
|
||||||
m_info_section.reset(new char[m_info_section_size]);
|
m_info_section.reset(new char[m_info_section_size]);
|
||||||
std::memcpy(m_info_section.get(), section.first, m_info_section_size);
|
std::memcpy(m_info_section.get(), section.data(), m_info_section_size);
|
||||||
TORRENT_ASSERT(section.first[0] == 'd');
|
TORRENT_ASSERT(section[0] == 'd');
|
||||||
TORRENT_ASSERT(section.first[m_info_section_size-1] == 'e');
|
TORRENT_ASSERT(section[m_info_section_size-1] == 'e');
|
||||||
|
|
||||||
// when translating a pointer that points into the 'info' tree's
|
// when translating a pointer that points into the 'info' tree's
|
||||||
// backing buffer, into a pointer to our copy of the info section,
|
// backing buffer, into a pointer to our copy of the info section,
|
||||||
// this is the pointer offset to use.
|
// this is the pointer offset to use.
|
||||||
ptrdiff_t info_ptr_diff = m_info_section.get() - section.first;
|
ptrdiff_t const info_ptr_diff = m_info_section.get() - section.data();
|
||||||
|
|
||||||
// extract piece length
|
// extract piece length
|
||||||
int piece_length = info.dict_find_int_value("piece length", -1);
|
int piece_length = info.dict_find_int_value("piece length", -1);
|
||||||
|
|
|
@ -143,6 +143,7 @@ test-suite libtorrent :
|
||||||
|
|
||||||
[ run test_dht.cpp
|
[ run test_dht.cpp
|
||||||
test_dht_storage.cpp
|
test_dht_storage.cpp
|
||||||
|
test_direct_dht.cpp
|
||||||
]
|
]
|
||||||
|
|
||||||
[ run test_string.cpp
|
[ run test_string.cpp
|
||||||
|
@ -154,7 +155,6 @@ test-suite libtorrent :
|
||||||
[ run test_crc32.cpp ]
|
[ run test_crc32.cpp ]
|
||||||
[ run test_receive_buffer.cpp ]
|
[ run test_receive_buffer.cpp ]
|
||||||
[ run test_alert_manager.cpp ]
|
[ run test_alert_manager.cpp ]
|
||||||
[ run test_direct_dht.cpp ]
|
|
||||||
[ run test_magnet.cpp ]
|
[ run test_magnet.cpp ]
|
||||||
[ run test_storage.cpp ]
|
[ run test_storage.cpp ]
|
||||||
[ run test_session.cpp ]
|
[ run test_session.cpp ]
|
||||||
|
|
|
@ -42,13 +42,13 @@ TORRENT_TEST(integer)
|
||||||
bdecode_node e;
|
bdecode_node e;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
||||||
TEST_CHECK(ret == 0);
|
TEST_EQUAL(ret, 0);
|
||||||
std::printf("%s\n", print_entry(e).c_str());
|
std::printf("%s\n", print_entry(e).c_str());
|
||||||
std::pair<const char*, int> section = e.data_section();
|
span<const char> section = e.data_section();
|
||||||
TEST_CHECK(std::memcmp(b, section.first, section.second) == 0);
|
TEST_CHECK(std::memcmp(b, section.data(), section.size()) == 0);
|
||||||
TEST_CHECK(section.second == sizeof(b) - 1);
|
TEST_EQUAL(section.size(), sizeof(b) - 1);
|
||||||
TEST_CHECK(e.type() == bdecode_node::int_t);
|
TEST_EQUAL(e.type(), bdecode_node::int_t);
|
||||||
TEST_CHECK(e.int_value() == 12453);
|
TEST_EQUAL(e.int_value(), 12453);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test string
|
// test string
|
||||||
|
@ -58,11 +58,11 @@ TORRENT_TEST(string)
|
||||||
bdecode_node e;
|
bdecode_node e;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
||||||
TEST_CHECK(ret == 0);
|
TEST_EQUAL(ret, 0);
|
||||||
std::printf("%s\n", print_entry(e).c_str());
|
std::printf("%s\n", print_entry(e).c_str());
|
||||||
std::pair<const char*, int> section = e.data_section();
|
span<const char> section = e.data_section();
|
||||||
TEST_CHECK(std::memcmp(b, section.first, section.second) == 0);
|
TEST_CHECK(std::memcmp(b, section.data(), section.size()) == 0);
|
||||||
TEST_EQUAL(section.second, sizeof(b) - 1);
|
TEST_EQUAL(section.size(), sizeof(b) - 1);
|
||||||
TEST_EQUAL(e.type(), bdecode_node::string_t);
|
TEST_EQUAL(e.type(), bdecode_node::string_t);
|
||||||
TEST_EQUAL(e.string_value(), std::string("abcdefghijklmnopqrstuvwxyz"));
|
TEST_EQUAL(e.string_value(), std::string("abcdefghijklmnopqrstuvwxyz"));
|
||||||
TEST_EQUAL(e.string_length(), 26);
|
TEST_EQUAL(e.string_length(), 26);
|
||||||
|
@ -79,11 +79,11 @@ TORRENT_TEST(string_prefix1)
|
||||||
bdecode_node e;
|
bdecode_node e;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
int ret = bdecode(test.c_str(), test.c_str() + test.size(), e, ec);
|
int ret = bdecode(test.c_str(), test.c_str() + test.size(), e, ec);
|
||||||
TEST_CHECK(ret == 0);
|
TEST_EQUAL(ret, 0);
|
||||||
std::printf("%d bytes string\n", e.string_length());
|
std::printf("%d bytes string\n", e.string_length());
|
||||||
std::pair<const char*, int> section = e.data_section();
|
span<const char> section = e.data_section();
|
||||||
TEST_CHECK(std::memcmp(test.c_str(), section.first, section.second) == 0);
|
TEST_CHECK(std::memcmp(test.c_str(), section.data(), section.size()) == 0);
|
||||||
TEST_EQUAL(section.second, int(test.size()));
|
TEST_EQUAL(section.size(), test.size());
|
||||||
TEST_EQUAL(e.type(), bdecode_node::string_t);
|
TEST_EQUAL(e.type(), bdecode_node::string_t);
|
||||||
TEST_EQUAL(e.string_length(), 1000000);
|
TEST_EQUAL(e.string_length(), 1000000);
|
||||||
TEST_EQUAL(e.string_ptr(), test.c_str() + 8);
|
TEST_EQUAL(e.string_ptr(), test.c_str() + 8);
|
||||||
|
@ -96,21 +96,21 @@ TORRENT_TEST(list)
|
||||||
bdecode_node e;
|
bdecode_node e;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
||||||
TEST_CHECK(ret == 0);
|
TEST_EQUAL(ret, 0);
|
||||||
std::printf("%s\n", print_entry(e).c_str());
|
std::printf("%s\n", print_entry(e).c_str());
|
||||||
std::pair<const char*, int> section = e.data_section();
|
span<const char> section = e.data_section();
|
||||||
TEST_CHECK(std::memcmp(b, section.first, section.second) == 0);
|
TEST_CHECK(std::memcmp(b, section.data(), section.size()) == 0);
|
||||||
TEST_CHECK(section.second == sizeof(b) - 1);
|
TEST_EQUAL(section.size(), sizeof(b) - 1);
|
||||||
TEST_CHECK(e.type() == bdecode_node::list_t);
|
TEST_EQUAL(e.type(), bdecode_node::list_t);
|
||||||
TEST_CHECK(e.list_size() == 2);
|
TEST_EQUAL(e.list_size(), 2);
|
||||||
TEST_CHECK(e.list_at(0).type() == bdecode_node::int_t);
|
TEST_EQUAL(e.list_at(0).type(), bdecode_node::int_t);
|
||||||
TEST_CHECK(e.list_at(1).type() == bdecode_node::string_t);
|
TEST_EQUAL(e.list_at(1).type(), bdecode_node::string_t);
|
||||||
TEST_CHECK(e.list_at(0).int_value() == 12453);
|
TEST_EQUAL(e.list_at(0).int_value(), 12453);
|
||||||
TEST_CHECK(e.list_at(1).string_value() == std::string("aaa"));
|
TEST_EQUAL(e.list_at(1).string_value(), std::string("aaa"));
|
||||||
TEST_CHECK(e.list_at(1).string_length() == 3);
|
TEST_EQUAL(e.list_at(1).string_length(), 3);
|
||||||
section = e.list_at(1).data_section();
|
section = e.list_at(1).data_section();
|
||||||
TEST_CHECK(std::memcmp("3:aaa", section.first, section.second) == 0);
|
TEST_CHECK(std::memcmp("3:aaa", section.data(), section.size()) == 0);
|
||||||
TEST_CHECK(section.second == 5);
|
TEST_EQUAL(section.size(), 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test dict
|
// test dict
|
||||||
|
@ -122,20 +122,20 @@ TORRENT_TEST(dict)
|
||||||
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
||||||
TEST_EQUAL(ret, 0);
|
TEST_EQUAL(ret, 0);
|
||||||
std::printf("%s\n", print_entry(e).c_str());
|
std::printf("%s\n", print_entry(e).c_str());
|
||||||
std::pair<const char*, int> section = e.data_section();
|
span<const char> section = e.data_section();
|
||||||
TEST_CHECK(std::memcmp(b, section.first, section.second) == 0);
|
TEST_CHECK(std::memcmp(b, section.data(), section.size()) == 0);
|
||||||
TEST_CHECK(section.second == sizeof(b) - 1);
|
TEST_EQUAL(section.size(), sizeof(b) - 1);
|
||||||
TEST_CHECK(e.type() == bdecode_node::dict_t);
|
TEST_EQUAL(e.type(), bdecode_node::dict_t);
|
||||||
TEST_CHECK(e.dict_size() == 4);
|
TEST_EQUAL(e.dict_size(), 4);
|
||||||
TEST_CHECK(e.dict_find("a").type() == bdecode_node::int_t);
|
TEST_EQUAL(e.dict_find("a").type(), bdecode_node::int_t);
|
||||||
TEST_CHECK(e.dict_find("a").int_value() == 12453);
|
TEST_EQUAL(e.dict_find("a").int_value(), 12453);
|
||||||
TEST_CHECK(e.dict_find("b").type() == bdecode_node::string_t);
|
TEST_EQUAL(e.dict_find("b").type(), bdecode_node::string_t);
|
||||||
TEST_CHECK(e.dict_find("b").string_value() == std::string("aaa"));
|
TEST_EQUAL(e.dict_find("b").string_value(), std::string("aaa"));
|
||||||
TEST_CHECK(e.dict_find("b").string_length() == 3);
|
TEST_EQUAL(e.dict_find("b").string_length(), 3);
|
||||||
TEST_CHECK(e.dict_find("c").type() == bdecode_node::string_t);
|
TEST_EQUAL(e.dict_find("c").type(), bdecode_node::string_t);
|
||||||
TEST_CHECK(e.dict_find("c").string_value() == std::string("bbb"));
|
TEST_EQUAL(e.dict_find("c").string_value(), std::string("bbb"));
|
||||||
TEST_CHECK(e.dict_find("c").string_length() == 3);
|
TEST_EQUAL(e.dict_find("c").string_length(), 3);
|
||||||
TEST_CHECK(e.dict_find_string_value("X") == "0123456789");
|
TEST_EQUAL(e.dict_find_string_value("X"), "0123456789");
|
||||||
}
|
}
|
||||||
|
|
||||||
// test dictionary with a key without a value
|
// test dictionary with a key without a value
|
||||||
|
@ -173,7 +173,7 @@ TORRENT_TEST(dict_null_key)
|
||||||
bdecode_node e;
|
bdecode_node e;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
||||||
TEST_CHECK(ret == 0);
|
TEST_EQUAL(ret, 0);
|
||||||
TEST_CHECK(e.dict_size() == 1);
|
TEST_CHECK(e.dict_size() == 1);
|
||||||
bdecode_node d = e.dict_find(std::string("a\0b", 3));
|
bdecode_node d = e.dict_find(std::string("a\0b", 3));
|
||||||
TEST_EQUAL(d.type(), bdecode_node::int_t);
|
TEST_EQUAL(d.type(), bdecode_node::int_t);
|
||||||
|
@ -350,7 +350,7 @@ TORRENT_TEST(64bit_int)
|
||||||
bdecode_node e;
|
bdecode_node e;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
||||||
TEST_CHECK(ret == 0);
|
TEST_EQUAL(ret, 0);
|
||||||
std::printf("%s\n", print_entry(e).c_str());
|
std::printf("%s\n", print_entry(e).c_str());
|
||||||
TEST_CHECK(e.int_value() == 9223372036854775807LL);
|
TEST_CHECK(e.int_value() == 9223372036854775807LL);
|
||||||
}
|
}
|
||||||
|
@ -362,7 +362,7 @@ TORRENT_TEST(64bit_int_negative)
|
||||||
bdecode_node e;
|
bdecode_node e;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
int ret = bdecode(b, b + sizeof(b)-1, e, ec);
|
||||||
TEST_CHECK(ret == 0);
|
TEST_EQUAL(ret, 0);
|
||||||
std::printf("%s\n", print_entry(e).c_str());
|
std::printf("%s\n", print_entry(e).c_str());
|
||||||
TEST_CHECK(e.int_value() == -9223372036854775807LL);
|
TEST_CHECK(e.int_value() == -9223372036854775807LL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,11 +70,21 @@ sha1_hash to_hash(char const* s)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_test_keypair(char* public_key, char* private_key)
|
void get_test_keypair(public_key& pk, secret_key& sk)
|
||||||
{
|
{
|
||||||
aux::from_hex("77ff84905a91936367c01360803104f92432fcd904a43511876df5cdf3e7e548", 64, public_key);
|
aux::from_hex("77ff84905a91936367c01360803104f92432fcd904a43511876df5cdf3e7e548", 64, pk.bytes.data());
|
||||||
aux::from_hex("e06d3183d14159228433ed599221b80bd0a5ce8352e4bdf0262f76786ef1c74d"
|
aux::from_hex("e06d3183d14159228433ed599221b80bd0a5ce8352e4bdf0262f76786ef1c74d"
|
||||||
"b7e7a9fea2c0eb269d61e3b38e450a22e754941ac78479d6c54e1faf6037881d", 128, private_key);
|
"b7e7a9fea2c0eb269d61e3b38e450a22e754941ac78479d6c54e1faf6037881d", 128, sk.bytes.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence_number prev_seq(sequence_number s)
|
||||||
|
{
|
||||||
|
return sequence_number(s.value - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence_number next_seq(sequence_number s)
|
||||||
|
{
|
||||||
|
return sequence_number(s.value + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_and_replace(libtorrent::dht::node_id& dst, libtorrent::dht::node_id const& add)
|
void add_and_replace(libtorrent::dht::node_id& dst, libtorrent::dht::node_id const& add)
|
||||||
|
@ -163,8 +173,8 @@ struct msg_args
|
||||||
msg_args& port(int p)
|
msg_args& port(int p)
|
||||||
{ a["port"] = p; return *this; }
|
{ a["port"] = p; return *this; }
|
||||||
|
|
||||||
msg_args& target(char const* t)
|
msg_args& target(sha1_hash const& t)
|
||||||
{ if (t) a["target"] = std::string(t, 20); return *this; }
|
{ a["target"] = t.to_string(); return *this; }
|
||||||
|
|
||||||
msg_args& value(entry const& v)
|
msg_args& value(entry const& v)
|
||||||
{ a["v"] = v; return *this; }
|
{ a["v"] = v; return *this; }
|
||||||
|
@ -175,23 +185,23 @@ struct msg_args
|
||||||
msg_args& seed(bool s)
|
msg_args& seed(bool s)
|
||||||
{ a["seed"] = s ? 1 : 0; return *this; }
|
{ a["seed"] = s ? 1 : 0; return *this; }
|
||||||
|
|
||||||
msg_args& key(std::string k)
|
msg_args& key(public_key const& k)
|
||||||
{ a["k"] = k; return *this; }
|
{ a["k"] = k.bytes; return *this; }
|
||||||
|
|
||||||
msg_args& sig(std::string s)
|
msg_args& sig(signature const& s)
|
||||||
{ a["sig"] = s; return *this; }
|
{ a["sig"] = s.bytes; return *this; }
|
||||||
|
|
||||||
msg_args& seq(int s)
|
msg_args& seq(sequence_number s)
|
||||||
{ a["seq"] = s; return *this; }
|
{ a["seq"] = s.value; return *this; }
|
||||||
|
|
||||||
msg_args& cas(std::int64_t c)
|
msg_args& cas(sequence_number c)
|
||||||
{ a["cas"] = c; return *this; }
|
{ a["cas"] = c.value; return *this; }
|
||||||
|
|
||||||
msg_args& nid(sha1_hash const& n)
|
msg_args& nid(sha1_hash const& n)
|
||||||
{ a["id"] = n.to_string(); return *this; }
|
{ a["id"] = n.to_string(); return *this; }
|
||||||
|
|
||||||
msg_args& salt(char const* s)
|
msg_args& salt(span<char const> s)
|
||||||
{ if (s) a["salt"] = s; return *this; }
|
{ if (!s.empty()) a["salt"] = s; return *this; }
|
||||||
|
|
||||||
msg_args& want(std::string w)
|
msg_args& want(std::string w)
|
||||||
{ a["want"].list().push_back(w); return *this; }
|
{ a["want"].list().push_back(w); return *this; }
|
||||||
|
@ -312,7 +322,7 @@ void announce_immutable_items(node& node, udp::endpoint const* eps
|
||||||
if ((i % items[j].num_peers) == 0) continue;
|
if ((i % items[j].num_peers) == 0) continue;
|
||||||
bdecode_node response;
|
bdecode_node response;
|
||||||
send_dht_request(node, "get", eps[i], &response
|
send_dht_request(node, "get", eps[i], &response
|
||||||
, msg_args().target((char const*)&items[j].target[0]));
|
, msg_args().target(items[j].target));
|
||||||
|
|
||||||
key_desc_t const desc[] =
|
key_desc_t const desc[] =
|
||||||
{
|
{
|
||||||
|
@ -353,7 +363,7 @@ void announce_immutable_items(node& node, udp::endpoint const* eps
|
||||||
send_dht_request(node, "put", eps[i], &response
|
send_dht_request(node, "put", eps[i], &response
|
||||||
, msg_args()
|
, msg_args()
|
||||||
.token(token)
|
.token(token)
|
||||||
.target((char const*)&items[j].target[0])
|
.target(items[j].target)
|
||||||
.value(items[j].ent));
|
.value(items[j].ent));
|
||||||
|
|
||||||
key_desc_t const desc2[] =
|
key_desc_t const desc2[] =
|
||||||
|
@ -385,7 +395,7 @@ void announce_immutable_items(node& node, udp::endpoint const* eps
|
||||||
{
|
{
|
||||||
bdecode_node response;
|
bdecode_node response;
|
||||||
send_dht_request(node, "get", eps[j], &response
|
send_dht_request(node, "get", eps[j], &response
|
||||||
, msg_args().target((char const*)&items[j].target[0]));
|
, msg_args().target(items[j].target));
|
||||||
|
|
||||||
key_desc_t const desc[] =
|
key_desc_t const desc[] =
|
||||||
{
|
{
|
||||||
|
@ -554,9 +564,9 @@ dht::key_desc_t const put_mutable_item_desc[] = {
|
||||||
{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
|
{"a", bdecode_node::dict_t, 0, key_desc_t::parse_children},
|
||||||
{"id", bdecode_node::string_t, 20, 0},
|
{"id", bdecode_node::string_t, 20, 0},
|
||||||
{"cas", bdecode_node::string_t, 20, key_desc_t::optional},
|
{"cas", bdecode_node::string_t, 20, key_desc_t::optional},
|
||||||
{"k", bdecode_node::string_t, item_pk_len, 0},
|
{"k", bdecode_node::string_t, public_key::len, 0},
|
||||||
{"seq", bdecode_node::int_t, 0, 0},
|
{"seq", bdecode_node::int_t, 0, 0},
|
||||||
{"sig", bdecode_node::string_t, item_sig_len, 0},
|
{"sig", bdecode_node::string_t, signature::len, 0},
|
||||||
{"token", bdecode_node::string_t, 2, 0},
|
{"token", bdecode_node::string_t, 2, 0},
|
||||||
{"v", bdecode_node::none_t, 0, key_desc_t::last_child},
|
{"v", bdecode_node::none_t, 0, key_desc_t::last_child},
|
||||||
};
|
};
|
||||||
|
@ -820,7 +830,9 @@ void test_id_enforcement(address(&rand_addr)())
|
||||||
nid[0] = 0x18;
|
nid[0] = 0x18;
|
||||||
int nodes_num = std::get<0>(t.dht_node.size());
|
int nodes_num = std::get<0>(t.dht_node.size());
|
||||||
send_dht_request(t.dht_node, "find_node", t.source, &response
|
send_dht_request(t.dht_node, "find_node", t.source, &response
|
||||||
, msg_args().target("0101010101010101010101010101010101010101").nid(nid));
|
, msg_args()
|
||||||
|
.target(sha1_hash("0101010101010101010101010101010101010101"))
|
||||||
|
.nid(nid));
|
||||||
|
|
||||||
bdecode_node err_keys[2];
|
bdecode_node err_keys[2];
|
||||||
bool ret = dht::verify_message(response, err_desc, err_keys, t.error_string
|
bool ret = dht::verify_message(response, err_desc, err_keys, t.error_string
|
||||||
|
@ -855,7 +867,9 @@ void test_id_enforcement(address(&rand_addr)())
|
||||||
else
|
else
|
||||||
nid[0] = 0x0a;
|
nid[0] = 0x0a;
|
||||||
send_dht_request(t.dht_node, "find_node", t.source, &response
|
send_dht_request(t.dht_node, "find_node", t.source, &response
|
||||||
, msg_args().target("0101010101010101010101010101010101010101").nid(nid));
|
, msg_args()
|
||||||
|
.target(sha1_hash("0101010101010101010101010101010101010101"))
|
||||||
|
.nid(nid));
|
||||||
|
|
||||||
dht::key_desc_t const nodes_desc[] = {
|
dht::key_desc_t const nodes_desc[] = {
|
||||||
{"y", bdecode_node::string_t, 1, 0},
|
{"y", bdecode_node::string_t, 1, 0},
|
||||||
|
@ -981,7 +995,7 @@ namespace {
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<char const*, int> const empty_salt(nullptr, 0);
|
span<char const> const empty_salt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 3 split this up into smaller tests
|
// TODO: 3 split this up into smaller tests
|
||||||
|
@ -1018,41 +1032,42 @@ void test_put(address(&rand_addr)())
|
||||||
|
|
||||||
// ==== get / put mutable items ===
|
// ==== get / put mutable items ===
|
||||||
|
|
||||||
std::pair<char const*, int> itemv;
|
span<char const> itemv;
|
||||||
|
|
||||||
char signature[item_sig_len];
|
signature sig;
|
||||||
char buffer[1200];
|
char buffer[1200];
|
||||||
int seq = 4;
|
sequence_number seq(4);
|
||||||
char public_key[item_pk_len];
|
public_key pk;
|
||||||
char private_key[item_sk_len];
|
secret_key sk;
|
||||||
get_test_keypair(public_key, private_key);
|
get_test_keypair(pk, sk);
|
||||||
|
|
||||||
|
// TODO: 4 pass in the actual salt as a parameter
|
||||||
for (int with_salt = 0; with_salt < 2; ++with_salt)
|
for (int with_salt = 0; with_salt < 2; ++with_salt)
|
||||||
{
|
{
|
||||||
seq = 4;
|
seq = sequence_number(4);
|
||||||
std::fprintf(stderr, "\nTEST GET/PUT%s \ngenerating ed25519 keys\n\n"
|
std::fprintf(stderr, "\nTEST GET/PUT%s \ngenerating ed25519 keys\n\n"
|
||||||
, with_salt ? " with-salt" : " no-salt");
|
, with_salt ? " with-salt" : " no-salt");
|
||||||
unsigned char seed[32];
|
unsigned char seed[32];
|
||||||
ed25519_create_seed(seed);
|
ed25519_create_seed(seed);
|
||||||
|
|
||||||
ed25519_create_keypair((unsigned char*)public_key, (unsigned char*)private_key, seed);
|
ed25519_create_keypair((unsigned char*)pk.bytes.data()
|
||||||
|
, (unsigned char*)sk.bytes.data(), seed);
|
||||||
std::fprintf(stderr, "pub: %s priv: %s\n"
|
std::fprintf(stderr, "pub: %s priv: %s\n"
|
||||||
, aux::to_hex(std::string(public_key, item_pk_len)).c_str()
|
, aux::to_hex(std::string(pk.bytes.data(), public_key::len)).c_str()
|
||||||
, aux::to_hex(std::string(private_key, item_sk_len)).c_str());
|
, aux::to_hex(std::string(sk.bytes.data(), secret_key::len)).c_str());
|
||||||
|
|
||||||
std::pair<const char*, int> salt(nullptr, 0);
|
std::string salt;
|
||||||
if (with_salt)
|
if (with_salt) salt = "foobar";
|
||||||
salt = std::pair<char const*, int>("foobar", 6);
|
|
||||||
|
|
||||||
hasher h(public_key, 32);
|
hasher h(pk.bytes);
|
||||||
if (with_salt) h.update(salt.first, salt.second);
|
if (with_salt) h.update(salt);
|
||||||
sha1_hash target_id = h.final();
|
sha1_hash target_id = h.final();
|
||||||
|
|
||||||
std::fprintf(stderr, "target_id: %s\n"
|
std::fprintf(stderr, "target_id: %s\n"
|
||||||
, aux::to_hex(target_id.to_string()).c_str());
|
, aux::to_hex(target_id.to_string()).c_str());
|
||||||
|
|
||||||
send_dht_request(t.dht_node, "get", t.source, &response
|
send_dht_request(t.dht_node, "get", t.source, &response
|
||||||
, msg_args().target((char*)&target_id[0]));
|
, msg_args().target(target_id));
|
||||||
|
|
||||||
key_desc_t const desc[] =
|
key_desc_t const desc[] =
|
||||||
{
|
{
|
||||||
|
@ -1084,18 +1099,18 @@ void test_put(address(&rand_addr)())
|
||||||
TEST_ERROR(t.error_string);
|
TEST_ERROR(t.error_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
itemv = std::pair<char const*, int>(buffer, bencode(buffer, items[0].ent));
|
itemv = span<char const>(buffer, bencode(buffer, items[0].ent));
|
||||||
sign_mutable_item(itemv, salt, seq, public_key, private_key, signature);
|
sign_mutable_item(itemv, salt, seq, pk, sk, sig);
|
||||||
TEST_EQUAL(verify_mutable_item(itemv, salt, seq, public_key, signature), true);
|
TEST_EQUAL(verify_mutable_item(itemv, salt, seq, pk, sig), true);
|
||||||
|
|
||||||
send_dht_request(t.dht_node, "put", t.source, &response
|
send_dht_request(t.dht_node, "put", t.source, &response
|
||||||
, msg_args()
|
, msg_args()
|
||||||
.token(token)
|
.token(token)
|
||||||
.value(items[0].ent)
|
.value(items[0].ent)
|
||||||
.key(std::string(public_key, item_pk_len))
|
.key(pk)
|
||||||
.sig(std::string(signature, item_sig_len))
|
.sig(sig)
|
||||||
.seq(seq)
|
.seq(seq)
|
||||||
.salt(salt.first));
|
.salt(salt));
|
||||||
|
|
||||||
ret = verify_message(response, desc2, desc2_keys, t.error_string
|
ret = verify_message(response, desc2, desc2_keys, t.error_string
|
||||||
, sizeof(t.error_string));
|
, sizeof(t.error_string));
|
||||||
|
@ -1113,7 +1128,7 @@ void test_put(address(&rand_addr)())
|
||||||
}
|
}
|
||||||
|
|
||||||
send_dht_request(t.dht_node, "get", t.source, &response
|
send_dht_request(t.dht_node, "get", t.source, &response
|
||||||
, msg_args().target((char*)&target_id[0]));
|
, msg_args().target(target_id));
|
||||||
|
|
||||||
std::fprintf(stderr, "target_id: %s\n"
|
std::fprintf(stderr, "target_id: %s\n"
|
||||||
, aux::to_hex(target_id.to_string()).c_str());
|
, aux::to_hex(target_id.to_string()).c_str());
|
||||||
|
@ -1146,33 +1161,33 @@ void test_put(address(&rand_addr)())
|
||||||
, print_entry(response).c_str());
|
, print_entry(response).c_str());
|
||||||
char value[1020];
|
char value[1020];
|
||||||
char* ptr = value;
|
char* ptr = value;
|
||||||
int value_len = bencode(ptr, items[0].ent);
|
int const value_len = bencode(ptr, items[0].ent);
|
||||||
TEST_EQUAL(value_len, desc3_keys[2].data_section().second);
|
TEST_EQUAL(value_len, int(desc3_keys[2].data_section().size()));
|
||||||
TEST_CHECK(memcmp(desc3_keys[2].data_section().first, value, value_len) == 0);
|
TEST_CHECK(memcmp(desc3_keys[2].data_section().data(), value, value_len) == 0);
|
||||||
|
|
||||||
TEST_EQUAL(seq, desc3_keys[3].int_value());
|
TEST_EQUAL(int(seq.value), desc3_keys[3].int_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
// also test that invalid signatures fail!
|
// also test that invalid signatures fail!
|
||||||
|
|
||||||
itemv = std::pair<char const*, int>(buffer, bencode(buffer, items[0].ent));
|
itemv = span<char const>(buffer, bencode(buffer, items[0].ent));
|
||||||
sign_mutable_item(itemv, salt, seq, public_key, private_key, signature);
|
sign_mutable_item(itemv, salt, seq, pk, sk, sig);
|
||||||
TEST_EQUAL(verify_mutable_item(itemv, salt, seq, public_key, signature), 1);
|
TEST_EQUAL(verify_mutable_item(itemv, salt, seq, pk, sig), 1);
|
||||||
// break the signature
|
// break the signature
|
||||||
signature[2] ^= 0xaa;
|
sig.bytes[2] ^= 0xaa;
|
||||||
|
|
||||||
std::fprintf(stderr, "PUT broken signature\n");
|
std::fprintf(stderr, "PUT broken signature\n");
|
||||||
|
|
||||||
TEST_CHECK(verify_mutable_item(itemv, salt, seq, public_key, signature) != 1);
|
TEST_CHECK(verify_mutable_item(itemv, salt, seq, pk, sig) != 1);
|
||||||
|
|
||||||
send_dht_request(t.dht_node, "put", t.source, &response
|
send_dht_request(t.dht_node, "put", t.source, &response
|
||||||
, msg_args()
|
, msg_args()
|
||||||
.token(token)
|
.token(token)
|
||||||
.value(items[0].ent)
|
.value(items[0].ent)
|
||||||
.key(std::string(public_key, item_pk_len))
|
.key(pk)
|
||||||
.sig(std::string(signature, item_sig_len))
|
.sig(sig)
|
||||||
.seq(seq)
|
.seq(seq)
|
||||||
.salt(salt.first));
|
.salt(salt));
|
||||||
|
|
||||||
ret = verify_message(response, desc_error, desc_error_keys, t.error_string
|
ret = verify_message(response, desc_error, desc_error_keys, t.error_string
|
||||||
, sizeof(t.error_string));
|
, sizeof(t.error_string));
|
||||||
|
@ -1193,7 +1208,7 @@ void test_put(address(&rand_addr)())
|
||||||
// === test conditional get ===
|
// === test conditional get ===
|
||||||
|
|
||||||
send_dht_request(t.dht_node, "get", t.source, &response
|
send_dht_request(t.dht_node, "get", t.source, &response
|
||||||
, msg_args().target((char*)&target_id[0]).seq(seq - 1));
|
, msg_args().target(target_id).seq(prev_seq(seq)));
|
||||||
|
|
||||||
{
|
{
|
||||||
bdecode_node const r = response.dict_find_dict("r");
|
bdecode_node const r = response.dict_find_dict("r");
|
||||||
|
@ -1203,7 +1218,7 @@ void test_put(address(&rand_addr)())
|
||||||
}
|
}
|
||||||
|
|
||||||
send_dht_request(t.dht_node, "get", t.source, &response
|
send_dht_request(t.dht_node, "get", t.source, &response
|
||||||
, msg_args().target((char*)&target_id[0]).seq(seq));
|
, msg_args().target(target_id).seq(seq));
|
||||||
|
|
||||||
{
|
{
|
||||||
bdecode_node r = response.dict_find_dict("r");
|
bdecode_node r = response.dict_find_dict("r");
|
||||||
|
@ -1215,16 +1230,16 @@ void test_put(address(&rand_addr)())
|
||||||
// === test CAS put ===
|
// === test CAS put ===
|
||||||
|
|
||||||
// this is the sequence number we expect to be there
|
// this is the sequence number we expect to be there
|
||||||
std::uint64_t cas = seq;
|
sequence_number cas = seq;
|
||||||
|
|
||||||
// increment sequence number
|
// increment sequence number
|
||||||
++seq;
|
seq = next_seq(seq);
|
||||||
// put item 1
|
// put item 1
|
||||||
itemv = std::pair<char const*, int>(buffer, bencode(buffer, items[1].ent));
|
itemv = span<char const>(buffer, bencode(buffer, items[1].ent));
|
||||||
sign_mutable_item(itemv, salt, seq, public_key, private_key, signature);
|
sign_mutable_item(itemv, salt, seq, pk, sk, sig);
|
||||||
TEST_EQUAL(verify_mutable_item(itemv, salt, seq, public_key, signature), 1);
|
TEST_EQUAL(verify_mutable_item(itemv, salt, seq, pk, sig), 1);
|
||||||
|
|
||||||
TEST_CHECK(item_target_id(salt, public_key) == target_id);
|
TEST_CHECK(item_target_id(salt, pk) == target_id);
|
||||||
|
|
||||||
std::fprintf(stderr, "PUT CAS 1\n");
|
std::fprintf(stderr, "PUT CAS 1\n");
|
||||||
|
|
||||||
|
@ -1232,11 +1247,11 @@ void test_put(address(&rand_addr)())
|
||||||
, msg_args()
|
, msg_args()
|
||||||
.token(token)
|
.token(token)
|
||||||
.value(items[1].ent)
|
.value(items[1].ent)
|
||||||
.key(std::string(public_key, item_pk_len))
|
.key(pk)
|
||||||
.sig(std::string(signature, item_sig_len))
|
.sig(sig)
|
||||||
.seq(seq)
|
.seq(seq)
|
||||||
.cas(cas)
|
.cas(cas)
|
||||||
.salt(salt.first));
|
.salt(salt));
|
||||||
|
|
||||||
ret = verify_message(response, desc2, desc2_keys, t.error_string
|
ret = verify_message(response, desc2, desc2_keys, t.error_string
|
||||||
, sizeof(t.error_string));
|
, sizeof(t.error_string));
|
||||||
|
@ -1262,11 +1277,11 @@ void test_put(address(&rand_addr)())
|
||||||
, msg_args()
|
, msg_args()
|
||||||
.token(token)
|
.token(token)
|
||||||
.value(items[1].ent)
|
.value(items[1].ent)
|
||||||
.key(std::string(public_key, item_pk_len))
|
.key(pk)
|
||||||
.sig(std::string(signature, item_sig_len))
|
.sig(sig)
|
||||||
.seq(seq)
|
.seq(seq)
|
||||||
.cas(cas)
|
.cas(cas)
|
||||||
.salt(salt.first));
|
.salt(salt));
|
||||||
|
|
||||||
ret = verify_message(response, desc_error, desc_error_keys, t.error_string
|
ret = verify_message(response, desc_error, desc_error_keys, t.error_string
|
||||||
, sizeof(t.error_string));
|
, sizeof(t.error_string));
|
||||||
|
@ -1767,23 +1782,22 @@ TORRENT_TEST(get_peers_v6)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// TODO: 4 pass in th actual salt as the argument
|
||||||
void test_mutable_get(address(&rand_addr)(), bool const with_salt)
|
void test_mutable_get(address(&rand_addr)(), bool const with_salt)
|
||||||
{
|
{
|
||||||
dht_test_setup t(udp::endpoint(rand_addr(), 20));
|
dht_test_setup t(udp::endpoint(rand_addr(), 20));
|
||||||
|
|
||||||
char public_key[item_pk_len];
|
public_key pk;
|
||||||
char private_key[item_sk_len];
|
secret_key sk;
|
||||||
get_test_keypair(public_key, private_key);
|
get_test_keypair(pk, sk);
|
||||||
|
|
||||||
char signature[item_sig_len];
|
|
||||||
char buffer[1200];
|
char buffer[1200];
|
||||||
int seq = 4;
|
sequence_number seq(4);
|
||||||
std::pair<char const*, int> itemv;
|
span<char const> itemv;
|
||||||
bdecode_node response;
|
bdecode_node response;
|
||||||
|
|
||||||
std::pair<const char*, int> salt(nullptr, 0);
|
std::string salt;
|
||||||
if (with_salt)
|
if (with_salt) salt = "foobar";
|
||||||
salt = std::pair<char const*, int>("foobar", 6);
|
|
||||||
|
|
||||||
// mutable get
|
// mutable get
|
||||||
|
|
||||||
|
@ -1792,9 +1806,8 @@ void test_mutable_get(address(&rand_addr)(), bool const with_salt)
|
||||||
udp::endpoint const initial_node(rand_addr(), 1234);
|
udp::endpoint const initial_node(rand_addr(), 1234);
|
||||||
t.dht_node.m_table.add_node(initial_node);
|
t.dht_node.m_table.add_node(initial_node);
|
||||||
|
|
||||||
g_put_item.assign(items[0].ent, salt, seq, public_key, private_key);
|
g_put_item.assign(items[0].ent, salt, seq, pk, sk);
|
||||||
std::string sig(g_put_item.sig().data(), item_sig_len);
|
t.dht_node.put_item(pk, std::string()
|
||||||
t.dht_node.put_item(public_key, std::string()
|
|
||||||
, std::bind(&put_mutable_item_cb, _1, _2, 0)
|
, std::bind(&put_mutable_item_cb, _1, _2, 0)
|
||||||
, put_mutable_item_data_cb);
|
, put_mutable_item_data_cb);
|
||||||
|
|
||||||
|
@ -1804,7 +1817,7 @@ void test_mutable_get(address(&rand_addr)(), bool const with_salt)
|
||||||
|
|
||||||
g_sent_packets.clear();
|
g_sent_packets.clear();
|
||||||
|
|
||||||
t.dht_node.get_item(public_key, std::string(salt.first, salt.second), get_mutable_item_cb);
|
t.dht_node.get_item(pk, salt, get_mutable_item_cb);
|
||||||
|
|
||||||
TEST_EQUAL(g_sent_packets.size(), 1);
|
TEST_EQUAL(g_sent_packets.size(), 1);
|
||||||
if (g_sent_packets.empty()) return;
|
if (g_sent_packets.empty()) return;
|
||||||
|
@ -1831,16 +1844,17 @@ void test_mutable_get(address(&rand_addr)(), bool const with_salt)
|
||||||
|
|
||||||
g_sent_packets.clear();
|
g_sent_packets.clear();
|
||||||
|
|
||||||
itemv = std::pair<char const*, int>(buffer, bencode(buffer, items[0].ent));
|
signature sig;
|
||||||
sign_mutable_item(itemv, salt, seq, public_key, private_key, signature);
|
itemv = span<char const>(buffer, bencode(buffer, items[0].ent));
|
||||||
|
sign_mutable_item(itemv, salt, seq, pk, sk, sig);
|
||||||
send_dht_response(t.dht_node, response, initial_node
|
send_dht_response(t.dht_node, response, initial_node
|
||||||
, msg_args()
|
, msg_args()
|
||||||
.token("10")
|
.token("10")
|
||||||
.port(1234)
|
.port(1234)
|
||||||
.value(items[0].ent)
|
.value(items[0].ent)
|
||||||
.key(std::string(public_key, item_pk_len))
|
.key(pk)
|
||||||
.sig(std::string(signature, item_sig_len))
|
.sig(sig)
|
||||||
.salt(salt.first)
|
.salt(salt)
|
||||||
.seq(seq));
|
.seq(seq));
|
||||||
|
|
||||||
TEST_CHECK(g_sent_packets.empty());
|
TEST_CHECK(g_sent_packets.empty());
|
||||||
|
@ -1848,9 +1862,9 @@ void test_mutable_get(address(&rand_addr)(), bool const with_salt)
|
||||||
if (g_got_items.empty()) return;
|
if (g_got_items.empty()) return;
|
||||||
|
|
||||||
TEST_EQUAL(g_got_items.front().value(), items[0].ent);
|
TEST_EQUAL(g_got_items.front().value(), items[0].ent);
|
||||||
TEST_CHECK(memcmp(g_got_items.front().pk().data(), public_key, item_pk_len) == 0);
|
TEST_CHECK(g_got_items.front().pk() == pk);
|
||||||
TEST_CHECK(memcmp(g_got_items.front().sig().data(), signature, item_sig_len) == 0);
|
TEST_CHECK(g_got_items.front().sig() == sig);
|
||||||
TEST_EQUAL(int(g_got_items.front().seq()), seq);
|
TEST_CHECK(g_got_items.front().seq() == seq);
|
||||||
g_got_items.clear();
|
g_got_items.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1929,7 +1943,7 @@ TORRENT_TEST(immutable_get)
|
||||||
TORRENT_TEST(immutable_put)
|
TORRENT_TEST(immutable_put)
|
||||||
{
|
{
|
||||||
bdecode_node response;
|
bdecode_node response;
|
||||||
std::pair<char const*, int> itemv;
|
span<char const> itemv;
|
||||||
char buffer[1200];
|
char buffer[1200];
|
||||||
|
|
||||||
dht::key_desc_t const put_immutable_item_desc[] = {
|
dht::key_desc_t const put_immutable_item_desc[] = {
|
||||||
|
@ -1963,7 +1977,7 @@ TORRENT_TEST(immutable_put)
|
||||||
std::string flat_data;
|
std::string flat_data;
|
||||||
bencode(std::back_inserter(flat_data), put_data);
|
bencode(std::back_inserter(flat_data), put_data);
|
||||||
sha1_hash target = item_target_id(
|
sha1_hash target = item_target_id(
|
||||||
std::pair<char const*, int>(flat_data.c_str(), int(flat_data.size())));
|
span<char const>(flat_data.c_str(), int(flat_data.size())));
|
||||||
|
|
||||||
t.dht_node.put_item(target, put_data, std::bind(&put_immutable_item_cb, _1, loop));
|
t.dht_node.put_item(target, put_data, std::bind(&put_immutable_item_cb, _1, loop));
|
||||||
|
|
||||||
|
@ -1998,7 +2012,7 @@ TORRENT_TEST(immutable_put)
|
||||||
TEST_EQUAL(g_sent_packets.size(), 8);
|
TEST_EQUAL(g_sent_packets.size(), 8);
|
||||||
if (g_sent_packets.size() != 8) break;
|
if (g_sent_packets.size() != 8) break;
|
||||||
|
|
||||||
itemv = std::pair<char const*, int>(buffer, bencode(buffer, put_data));
|
itemv = span<char const>(buffer, bencode(buffer, put_data));
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
|
@ -2013,8 +2027,8 @@ TORRENT_TEST(immutable_put)
|
||||||
{
|
{
|
||||||
TEST_EQUAL(put_immutable_item_keys[0].string_value(), "q");
|
TEST_EQUAL(put_immutable_item_keys[0].string_value(), "q");
|
||||||
TEST_EQUAL(put_immutable_item_keys[2].string_value(), "put");
|
TEST_EQUAL(put_immutable_item_keys[2].string_value(), "put");
|
||||||
std::pair<const char*, int> v = put_immutable_item_keys[6].data_section();
|
span<const char> v = put_immutable_item_keys[6].data_section();
|
||||||
TEST_EQUAL(std::string(v.first, v.second), flat_data);
|
TEST_EQUAL(std::string(v.data(), v.size()), flat_data);
|
||||||
char tok[10];
|
char tok[10];
|
||||||
std::snprintf(tok, sizeof(tok), "%02d", i);
|
std::snprintf(tok, sizeof(tok), "%02d", i);
|
||||||
TEST_EQUAL(put_immutable_item_keys[5].string_value(), tok);
|
TEST_EQUAL(put_immutable_item_keys[5].string_value(), tok);
|
||||||
|
@ -2039,14 +2053,14 @@ TORRENT_TEST(immutable_put)
|
||||||
TORRENT_TEST(mutable_put)
|
TORRENT_TEST(mutable_put)
|
||||||
{
|
{
|
||||||
bdecode_node response;
|
bdecode_node response;
|
||||||
std::pair<char const*, int> itemv;
|
span<char const> itemv;
|
||||||
char buffer[1200];
|
char buffer[1200];
|
||||||
bdecode_node put_mutable_item_keys[11];
|
bdecode_node put_mutable_item_keys[11];
|
||||||
char public_key[item_pk_len];
|
public_key pk;
|
||||||
char private_key[item_sk_len];
|
secret_key sk;
|
||||||
get_test_keypair(public_key, private_key);
|
get_test_keypair(pk, sk);
|
||||||
|
|
||||||
int seq = 4;
|
sequence_number seq(4);
|
||||||
|
|
||||||
// mutable put
|
// mutable put
|
||||||
g_sent_packets.clear();
|
g_sent_packets.clear();
|
||||||
|
@ -2063,9 +2077,9 @@ TORRENT_TEST(mutable_put)
|
||||||
for (int i = 0; i < num_test_nodes; ++i)
|
for (int i = 0; i < num_test_nodes; ++i)
|
||||||
t.dht_node.m_table.add_node(nodes[i]);
|
t.dht_node.m_table.add_node(nodes[i]);
|
||||||
|
|
||||||
g_put_item.assign(items[0].ent, empty_salt, seq, public_key, private_key);
|
g_put_item.assign(items[0].ent, empty_salt, seq, pk, sk);
|
||||||
std::string sig(g_put_item.sig().data(), item_sig_len);
|
signature const sig = g_put_item.sig();
|
||||||
t.dht_node.put_item(public_key, std::string()
|
t.dht_node.put_item(pk, std::string()
|
||||||
, std::bind(&put_mutable_item_cb, _1, _2, loop)
|
, std::bind(&put_mutable_item_cb, _1, _2, loop)
|
||||||
, put_mutable_item_data_cb);
|
, put_mutable_item_data_cb);
|
||||||
|
|
||||||
|
@ -2100,7 +2114,7 @@ TORRENT_TEST(mutable_put)
|
||||||
TEST_EQUAL(g_sent_packets.size(), 8);
|
TEST_EQUAL(g_sent_packets.size(), 8);
|
||||||
if (g_sent_packets.size() != 8) break;
|
if (g_sent_packets.size() != 8) break;
|
||||||
|
|
||||||
itemv = std::pair<char const*, int>(buffer, bencode(buffer, items[0].ent));
|
itemv = span<char const>(buffer, bencode(buffer, items[0].ent));
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
|
@ -2115,12 +2129,12 @@ TORRENT_TEST(mutable_put)
|
||||||
{
|
{
|
||||||
TEST_EQUAL(put_mutable_item_keys[0].string_value(), "q");
|
TEST_EQUAL(put_mutable_item_keys[0].string_value(), "q");
|
||||||
TEST_EQUAL(put_mutable_item_keys[2].string_value(), "put");
|
TEST_EQUAL(put_mutable_item_keys[2].string_value(), "put");
|
||||||
TEST_EQUAL(put_mutable_item_keys[6].string_value(), std::string(public_key, item_pk_len));
|
TEST_EQUAL(put_mutable_item_keys[6].string_value(), std::string(pk.bytes.data(), public_key::len));
|
||||||
TEST_EQUAL(put_mutable_item_keys[7].int_value(), seq);
|
TEST_EQUAL(put_mutable_item_keys[7].int_value(), int(seq.value));
|
||||||
TEST_EQUAL(put_mutable_item_keys[8].string_value(), sig);
|
TEST_EQUAL(put_mutable_item_keys[8].string_value(), std::string(sig.bytes.data(), signature::len));
|
||||||
std::pair<const char*, int> v = put_mutable_item_keys[10].data_section();
|
span<const char> v = put_mutable_item_keys[10].data_section();
|
||||||
TEST_EQUAL(v.second, itemv.second);
|
TEST_EQUAL(v.size(), itemv.size());
|
||||||
TEST_CHECK(memcmp(v.first, itemv.first, itemv.second) == 0);
|
TEST_CHECK(memcmp(v.data(), itemv.data(), itemv.size()) == 0);
|
||||||
char tok[10];
|
char tok[10];
|
||||||
std::snprintf(tok, sizeof(tok), "%02d", i);
|
std::snprintf(tok, sizeof(tok), "%02d", i);
|
||||||
TEST_EQUAL(put_mutable_item_keys[9].string_value(), tok);
|
TEST_EQUAL(put_mutable_item_keys[9].string_value(), tok);
|
||||||
|
@ -2149,18 +2163,18 @@ TORRENT_TEST(traversal_done)
|
||||||
// set the branching factor to k to make this a little easier
|
// set the branching factor to k to make this a little easier
|
||||||
t.sett.search_branching = 8;
|
t.sett.search_branching = 8;
|
||||||
|
|
||||||
char public_key[item_pk_len];
|
public_key pk;
|
||||||
char private_key[item_sk_len];
|
secret_key sk;
|
||||||
get_test_keypair(public_key, private_key);
|
get_test_keypair(pk, sk);
|
||||||
|
|
||||||
int seq = 4;
|
sequence_number seq(4);
|
||||||
bdecode_node response;
|
bdecode_node response;
|
||||||
|
|
||||||
// verify that done() is only invoked once
|
// verify that done() is only invoked once
|
||||||
// See PR 252
|
// See PR 252
|
||||||
g_sent_packets.clear();
|
g_sent_packets.clear();
|
||||||
|
|
||||||
sha1_hash target = hasher(public_key, item_pk_len).final();
|
sha1_hash const target = hasher(pk.bytes).final();
|
||||||
enum { num_test_nodes = 9 }; // we need K + 1 nodes to create the failing sequence
|
enum { num_test_nodes = 9 }; // we need K + 1 nodes to create the failing sequence
|
||||||
|
|
||||||
std::array<node_entry, 9> nodes = build_nodes(target);
|
std::array<node_entry, 9> nodes = build_nodes(target);
|
||||||
|
@ -2175,8 +2189,8 @@ TORRENT_TEST(traversal_done)
|
||||||
t.dht_node.m_table.add_node(nodes[i]);
|
t.dht_node.m_table.add_node(nodes[i]);
|
||||||
|
|
||||||
// kick off a mutable put request
|
// kick off a mutable put request
|
||||||
g_put_item.assign(items[0].ent, empty_salt, seq, public_key, private_key);
|
g_put_item.assign(items[0].ent, empty_salt, seq, pk, sk);
|
||||||
t.dht_node.put_item(public_key, std::string()
|
t.dht_node.put_item(pk, std::string()
|
||||||
, std::bind(&put_mutable_item_cb, _1, _2, 0)
|
, std::bind(&put_mutable_item_cb, _1, _2, 0)
|
||||||
, put_mutable_item_data_cb);
|
, put_mutable_item_data_cb);
|
||||||
TEST_EQUAL(g_sent_packets.size(), 8);
|
TEST_EQUAL(g_sent_packets.size(), 8);
|
||||||
|
@ -2259,7 +2273,9 @@ TORRENT_TEST(dht_dual_stack)
|
||||||
udp::endpoint source(addr("10.0.0.1"), 20);
|
udp::endpoint source(addr("10.0.0.1"), 20);
|
||||||
|
|
||||||
send_dht_request(node4, "find_node", source, &response
|
send_dht_request(node4, "find_node", source, &response
|
||||||
, msg_args().target("0101010101010101010101010101010101010101").want("n6"));
|
, msg_args()
|
||||||
|
.target(sha1_hash("0101010101010101010101010101010101010101"))
|
||||||
|
.want("n6"));
|
||||||
|
|
||||||
dht::key_desc_t const nodes6_desc[] = {
|
dht::key_desc_t const nodes6_desc[] = {
|
||||||
{ "y", bdecode_node::string_t, 1, 0 },
|
{ "y", bdecode_node::string_t, 1, 0 },
|
||||||
|
@ -2366,50 +2382,47 @@ TORRENT_TEST(signing_test1)
|
||||||
// test vector 1
|
// test vector 1
|
||||||
|
|
||||||
// test content
|
// test content
|
||||||
std::pair<char const*, int> test_content("12:Hello World!", 15);
|
span<char const> test_content("12:Hello World!", 15);
|
||||||
// test salt
|
// test salt
|
||||||
std::pair<char const*, int> test_salt("foobar", 6);
|
span<char const> test_salt("foobar", 6);
|
||||||
|
|
||||||
char public_key[item_pk_len];
|
public_key pk;
|
||||||
char private_key[item_sk_len];
|
secret_key sk;
|
||||||
get_test_keypair(public_key, private_key);
|
get_test_keypair(pk, sk);
|
||||||
std::pair<char const*, int> empty_salt;
|
span<char const> empty_salt;
|
||||||
|
|
||||||
char signature[item_sig_len];
|
signature sig;
|
||||||
|
sign_mutable_item(test_content, empty_salt, sequence_number(1), pk, sk, sig);
|
||||||
|
|
||||||
sign_mutable_item(test_content, empty_salt, 1, public_key
|
TEST_EQUAL(aux::to_hex(std::string(sig.bytes.data(), signature::len))
|
||||||
, private_key, signature);
|
|
||||||
|
|
||||||
TEST_EQUAL(aux::to_hex(std::string(signature, 64))
|
|
||||||
, "305ac8aeb6c9c151fa120f120ea2cfb923564e11552d06a5d856091e5e853cff"
|
, "305ac8aeb6c9c151fa120f120ea2cfb923564e11552d06a5d856091e5e853cff"
|
||||||
"1260d3f39e4999684aa92eb73ffd136e6f4f3ecbfda0ce53a1608ecd7ae21f01");
|
"1260d3f39e4999684aa92eb73ffd136e6f4f3ecbfda0ce53a1608ecd7ae21f01");
|
||||||
|
|
||||||
sha1_hash target_id = item_target_id(empty_salt, public_key);
|
sha1_hash target_id = item_target_id(empty_salt, pk);
|
||||||
TEST_EQUAL(aux::to_hex(target_id.to_string()), "4a533d47ec9c7d95b1ad75f576cffc641853b750");
|
TEST_EQUAL(aux::to_hex(target_id.to_string()), "4a533d47ec9c7d95b1ad75f576cffc641853b750");
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(signing_test2)
|
TORRENT_TEST(signing_test2)
|
||||||
{
|
{
|
||||||
char public_key[item_pk_len];
|
public_key pk;
|
||||||
char private_key[item_sk_len];
|
secret_key sk;
|
||||||
get_test_keypair(public_key, private_key);
|
get_test_keypair(pk, sk);
|
||||||
|
|
||||||
// test content
|
// test content
|
||||||
std::pair<char const*, int> test_content("12:Hello World!", 15);
|
span<char const> test_content("12:Hello World!", 15);
|
||||||
|
|
||||||
char signature[item_sig_len];
|
signature sig;
|
||||||
// test salt
|
// test salt
|
||||||
std::pair<char const*, int> test_salt("foobar", 6);
|
span<char const> test_salt("foobar", 6);
|
||||||
|
|
||||||
// test vector 2 (the keypair is the same as test 1)
|
// test vector 2 (the keypair is the same as test 1)
|
||||||
sign_mutable_item(test_content, test_salt, 1, public_key
|
sign_mutable_item(test_content, test_salt, sequence_number(1), pk, sk, sig);
|
||||||
, private_key, signature);
|
|
||||||
|
|
||||||
TEST_EQUAL(aux::to_hex(std::string(signature, 64))
|
TEST_EQUAL(aux::to_hex(std::string(sig.bytes.data(), signature::len))
|
||||||
, "6834284b6b24c3204eb2fea824d82f88883a3d95e8b4a21b8c0ded553d17d17d"
|
, "6834284b6b24c3204eb2fea824d82f88883a3d95e8b4a21b8c0ded553d17d17d"
|
||||||
"df9a8a7104b1258f30bed3787e6cb896fca78c58f8e03b5f18f14951a87d9a08");
|
"df9a8a7104b1258f30bed3787e6cb896fca78c58f8e03b5f18f14951a87d9a08");
|
||||||
|
|
||||||
sha1_hash target_id = item_target_id(test_salt, public_key);
|
sha1_hash target_id = item_target_id(test_salt, pk);
|
||||||
TEST_EQUAL(aux::to_hex(target_id.to_string()), "411eba73b6f087ca51a3795d9c8c938d365e32c1");
|
TEST_EQUAL(aux::to_hex(target_id.to_string()), "411eba73b6f087ca51a3795d9c8c938d365e32c1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2418,7 +2431,7 @@ TORRENT_TEST(signing_test3)
|
||||||
// test vector 3
|
// test vector 3
|
||||||
|
|
||||||
// test content
|
// test content
|
||||||
std::pair<char const*, int> test_content("12:Hello World!", 15);
|
span<char const> test_content("12:Hello World!", 15);
|
||||||
|
|
||||||
sha1_hash target_id = item_target_id(test_content);
|
sha1_hash target_id = item_target_id(test_content);
|
||||||
TEST_EQUAL(aux::to_hex(target_id.to_string()), "e5f96f6f38320f0f33959cb4d3d656452117aadb");
|
TEST_EQUAL(aux::to_hex(target_id.to_string()), "e5f96f6f38320f0f33959cb4d3d656452117aadb");
|
||||||
|
@ -2704,7 +2717,7 @@ TORRENT_TEST(read_only_node)
|
||||||
send_dht_request(node, "ping", source, &response, args, "10", false);
|
send_dht_request(node, "ping", source, &response, args, "10", false);
|
||||||
TEST_EQUAL(response.type(), bdecode_node::none_t);
|
TEST_EQUAL(response.type(), bdecode_node::none_t);
|
||||||
|
|
||||||
args.target("01010101010101010101");
|
args.target(sha1_hash("01010101010101010101"));
|
||||||
send_dht_request(node, "get", source, &response, args, "10", false);
|
send_dht_request(node, "get", source, &response, args, "10", false);
|
||||||
TEST_EQUAL(response.type(), bdecode_node::none_t);
|
TEST_EQUAL(response.type(), bdecode_node::none_t);
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "libtorrent/config.hpp"
|
#include "libtorrent/config.hpp"
|
||||||
#include "libtorrent/session.hpp"
|
#include "libtorrent/session.hpp"
|
||||||
#include "libtorrent/kademlia/node.hpp" // for verify_message
|
#include "libtorrent/kademlia/msg.hpp" // for verify_message
|
||||||
#include "libtorrent/bencode.hpp"
|
#include "libtorrent/bencode.hpp"
|
||||||
#include "libtorrent/socket_io.hpp" // for hash_address
|
#include "libtorrent/socket_io.hpp" // for hash_address
|
||||||
#include "libtorrent/broadcast_socket.hpp" // for supports_ipv6
|
#include "libtorrent/broadcast_socket.hpp" // for supports_ipv6
|
||||||
|
@ -138,23 +138,24 @@ TORRENT_TEST(put_immutable_item)
|
||||||
bool r = s->get_immutable_item(n4, item);
|
bool r = s->get_immutable_item(n4, item);
|
||||||
TEST_CHECK(!r);
|
TEST_CHECK(!r);
|
||||||
|
|
||||||
s->put_immutable_item(n4, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(n4, {"123", 3}, addr("124.31.75.21"));
|
||||||
r = s->get_immutable_item(n4, item);
|
r = s->get_immutable_item(n4, item);
|
||||||
TEST_CHECK(r);
|
TEST_CHECK(r);
|
||||||
|
|
||||||
s->put_immutable_item(n1, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(n1, {"123", 3}, addr("124.31.75.21"));
|
||||||
s->put_immutable_item(n2, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(n2, {"123", 3}, addr("124.31.75.21"));
|
||||||
s->put_immutable_item(n3, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(n3, {"123", 3}, addr("124.31.75.21"));
|
||||||
r = s->get_immutable_item(n1, item);
|
r = s->get_immutable_item(n1, item);
|
||||||
TEST_CHECK(!r);
|
TEST_CHECK(!r);
|
||||||
|
|
||||||
r = s->get_mutable_item(n4, 0, false, item);
|
r = s->get_mutable_item(n4, sequence_number(0), false, item);
|
||||||
TEST_CHECK(!r);
|
TEST_CHECK(!r);
|
||||||
|
|
||||||
char public_key[item_pk_len];
|
public_key pk;
|
||||||
char signature[item_sig_len];
|
signature sig;
|
||||||
s->put_mutable_item(n4, "123", 3, signature, 1, public_key, "salt", 4, address::from_string("124.31.75.21"));
|
s->put_mutable_item(n4, {"123", 3}, sig, sequence_number(1), pk
|
||||||
r = s->get_mutable_item(n4, 0, false, item);
|
, {"salt", 4}, addr("124.31.75.21"));
|
||||||
|
r = s->get_mutable_item(n4, sequence_number(0), false, item);
|
||||||
TEST_CHECK(r);
|
TEST_CHECK(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,17 +189,18 @@ TORRENT_TEST(counters)
|
||||||
|
|
||||||
entry item;
|
entry item;
|
||||||
|
|
||||||
s->put_immutable_item(n4, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(n4, {"123", 3}, addr("124.31.75.21"));
|
||||||
TEST_EQUAL(s->counters().immutable_data, 1);
|
TEST_EQUAL(s->counters().immutable_data, 1);
|
||||||
|
|
||||||
s->put_immutable_item(n1, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(n1, {"123", 3}, addr("124.31.75.21"));
|
||||||
s->put_immutable_item(n2, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(n2, {"123", 3}, addr("124.31.75.21"));
|
||||||
s->put_immutable_item(n3, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(n3, {"123", 3}, addr("124.31.75.21"));
|
||||||
TEST_EQUAL(s->counters().immutable_data, 2);
|
TEST_EQUAL(s->counters().immutable_data, 2);
|
||||||
|
|
||||||
char public_key[item_pk_len];
|
public_key pk;
|
||||||
char signature[item_sig_len];
|
signature sig;
|
||||||
s->put_mutable_item(n4, "123", 3, signature, 1, public_key, "salt", 4, address::from_string("124.31.75.21"));
|
s->put_mutable_item(n4, {"123", 3}, sig, sequence_number(1), pk
|
||||||
|
, {"salt", 4}, addr("124.31.75.21"));
|
||||||
TEST_EQUAL(s->counters().mutable_data, 1);
|
TEST_EQUAL(s->counters().mutable_data, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +288,7 @@ TORRENT_TEST(immutable_item_limit)
|
||||||
|
|
||||||
for (int i = 0; i < 200; ++i)
|
for (int i = 0; i < 200; ++i)
|
||||||
{
|
{
|
||||||
s->put_immutable_item(rand_hash(), "123", 3, rand_v4());
|
s->put_immutable_item(rand_hash(), {"123", 3}, rand_v4());
|
||||||
dht_storage_counters cnt = s->counters();
|
dht_storage_counters cnt = s->counters();
|
||||||
TEST_CHECK(cnt.immutable_data <= 42);
|
TEST_CHECK(cnt.immutable_data <= 42);
|
||||||
}
|
}
|
||||||
|
@ -300,11 +302,12 @@ TORRENT_TEST(mutable_item_limit)
|
||||||
sett.max_dht_items = 42;
|
sett.max_dht_items = 42;
|
||||||
std::unique_ptr<dht_storage_interface> s(create_default_dht_storage(sett));
|
std::unique_ptr<dht_storage_interface> s(create_default_dht_storage(sett));
|
||||||
|
|
||||||
char public_key[item_pk_len];
|
public_key pk;
|
||||||
char signature[item_sig_len];
|
signature sig;
|
||||||
for (int i = 0; i < 200; ++i)
|
for (int i = 0; i < 200; ++i)
|
||||||
{
|
{
|
||||||
s->put_mutable_item(rand_hash(), "123", 3, signature, 1, public_key, "salt", 4, rand_v4());
|
s->put_mutable_item(rand_hash(), {"123", 3}, sig, sequence_number(1)
|
||||||
|
, pk, {"salt", 4}, rand_v4());
|
||||||
dht_storage_counters cnt = s->counters();
|
dht_storage_counters cnt = s->counters();
|
||||||
TEST_CHECK(cnt.mutable_data <= 42);
|
TEST_CHECK(cnt.mutable_data <= 42);
|
||||||
}
|
}
|
||||||
|
@ -342,15 +345,15 @@ TORRENT_TEST(update_node_ids)
|
||||||
|
|
||||||
// all items will have one announcer, all calculations
|
// all items will have one announcer, all calculations
|
||||||
// for item erase will be reduced to the distance
|
// for item erase will be reduced to the distance
|
||||||
s->put_immutable_item(h1, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(h1, {"123", 3}, addr("124.31.75.21"));
|
||||||
cnt = s->counters();
|
cnt = s->counters();
|
||||||
TEST_EQUAL(cnt.immutable_data, 1);
|
TEST_EQUAL(cnt.immutable_data, 1);
|
||||||
s->put_immutable_item(h2, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(h2, {"123", 3}, addr("124.31.75.21"));
|
||||||
cnt = s->counters();
|
cnt = s->counters();
|
||||||
TEST_EQUAL(cnt.immutable_data, 2);
|
TEST_EQUAL(cnt.immutable_data, 2);
|
||||||
// at this point, the least important (h2) will removed
|
// at this point, the least important (h2) will removed
|
||||||
// to make room for h3
|
// to make room for h3
|
||||||
s->put_immutable_item(h3, "123", 3, address::from_string("124.31.75.21"));
|
s->put_immutable_item(h3, {"123", 3}, addr("124.31.75.21"));
|
||||||
cnt = s->counters();
|
cnt = s->counters();
|
||||||
TEST_EQUAL(cnt.immutable_data, 2);
|
TEST_EQUAL(cnt.immutable_data, 2);
|
||||||
|
|
||||||
|
|
|
@ -69,8 +69,8 @@ dht_direct_response_alert* get_direct_response(lt::session& ses)
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
alert* a = ses.wait_for_alert(seconds(20));
|
alert* a = ses.wait_for_alert(seconds(30));
|
||||||
// it shouldn't take more than 20 seconds to get a response
|
// it shouldn't take more than 30 seconds to get a response
|
||||||
// so fail the test and bail out if we don't get an alert in that time
|
// so fail the test and bail out if we don't get an alert in that time
|
||||||
TEST_CHECK(a);
|
TEST_CHECK(a);
|
||||||
if (!a) return nullptr;
|
if (!a) return nullptr;
|
||||||
|
|
|
@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/bencode.hpp" // for bencode()
|
#include "libtorrent/bencode.hpp" // for bencode()
|
||||||
#include "libtorrent/kademlia/item.hpp" // for sign_mutable_item
|
#include "libtorrent/kademlia/item.hpp" // for sign_mutable_item
|
||||||
#include "libtorrent/ed25519.hpp"
|
#include "libtorrent/ed25519.hpp"
|
||||||
|
#include "libtorrent/span.hpp"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <cstdio> // for snprintf
|
#include <cstdio> // for snprintf
|
||||||
|
@ -112,8 +113,11 @@ alert* wait_for_alert(lt::session& s, int alert_type)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_string(entry& e, std::array<char, 64>& sig, std::uint64_t& seq
|
void put_string(entry& e, std::array<char, 64>& sig
|
||||||
, std::string const& salt, char const* public_key, char const* private_key
|
, std::uint64_t& seq
|
||||||
|
, std::string const& salt
|
||||||
|
, std::array<char, 32> const& pk
|
||||||
|
, std::array<char, 64> const& sk
|
||||||
, char const* str)
|
, char const* str)
|
||||||
{
|
{
|
||||||
using libtorrent::dht::sign_mutable_item;
|
using libtorrent::dht::sign_mutable_item;
|
||||||
|
@ -121,13 +125,12 @@ void put_string(entry& e, std::array<char, 64>& sig, std::uint64_t& seq
|
||||||
e = std::string(str);
|
e = std::string(str);
|
||||||
std::vector<char> buf;
|
std::vector<char> buf;
|
||||||
bencode(std::back_inserter(buf), e);
|
bencode(std::back_inserter(buf), e);
|
||||||
|
dht::signature sign;
|
||||||
++seq;
|
++seq;
|
||||||
sign_mutable_item(std::pair<char const*, int>(&buf[0], int(buf.size()))
|
sign_mutable_item(buf, salt, dht::sequence_number(seq)
|
||||||
, std::pair<char const*, int>(&salt[0], int(salt.size()))
|
, dht::public_key(pk.data())
|
||||||
, seq
|
, dht::secret_key(sk.data()), sign);
|
||||||
, public_key
|
sig = sign.bytes;
|
||||||
, private_key
|
|
||||||
, sig.data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bootstrap(lt::session& s)
|
void bootstrap(lt::session& s)
|
||||||
|
@ -156,14 +159,14 @@ int dump_key(char *filename)
|
||||||
}
|
}
|
||||||
std::fclose(f);
|
std::fclose(f);
|
||||||
|
|
||||||
std::array<char, 32> public_key;
|
std::array<char, 32> pk;
|
||||||
std::array<char, 64> private_key;
|
std::array<char, 64> sk;
|
||||||
ed25519_create_keypair((unsigned char*)public_key.data()
|
ed25519_create_keypair((unsigned char*)pk.data()
|
||||||
, (unsigned char*)private_key.data(), seed);
|
, (unsigned char*)sk.data(), seed);
|
||||||
|
|
||||||
std::printf("public key: %s\nprivate key: %s\n",
|
std::printf("public key: %s\nprivate key: %s\n"
|
||||||
to_hex(std::string(public_key.data(), public_key.size())).c_str(),
|
, to_hex(std::string(pk.data(), pk.size())).c_str()
|
||||||
to_hex(std::string(private_key.data(), private_key.size())).c_str());
|
, to_hex(std::string(sk.data(), sk.size())).c_str());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -359,7 +362,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
bootstrap(s);
|
bootstrap(s);
|
||||||
s.dht_put_item(public_key, std::bind(&put_string, _1, _2, _3, _4
|
s.dht_put_item(public_key, std::bind(&put_string, _1, _2, _3, _4
|
||||||
, public_key.data(), private_key.data(), argv[0]));
|
, public_key, private_key, argv[0]));
|
||||||
|
|
||||||
std::printf("MPUT publick key: %s\n", to_hex(std::string(public_key.data()
|
std::printf("MPUT publick key: %s\n", to_hex(std::string(public_key.data()
|
||||||
, public_key.size())).c_str());
|
, public_key.size())).c_str());
|
||||||
|
|
Loading…
Reference in New Issue