From c6f1e0bd7bd46ba77c5ba35701919d9dfb89eeb4 Mon Sep 17 00:00:00 2001 From: Steven Siloti Date: Sat, 5 Dec 2015 17:27:01 -0800 Subject: [PATCH 1/3] export verify_message and incoming_error Also move these functions to a new msg.cpp. They are useful for plugins which implement DHT extensions. --- CMakeLists.txt | 1 + Jamfile | 1 + include/libtorrent/kademlia/msg.hpp | 43 +++++++- include/libtorrent/kademlia/node.hpp | 30 ------ src/Makefile.am | 3 +- src/kademlia/msg.cpp | 141 +++++++++++++++++++++++++++ src/kademlia/node.cpp | 104 -------------------- 7 files changed, 184 insertions(+), 139 deletions(-) create mode 100644 src/kademlia/msg.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c6afa06ee..547f25e6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,6 +122,7 @@ set(kademlia_sources dht_storage dos_blocker dht_tracker + msg node node_entry refresh diff --git a/Jamfile b/Jamfile index d513f3ecd..6aa6a4dc8 100644 --- a/Jamfile +++ b/Jamfile @@ -694,6 +694,7 @@ SOURCES = KADEMLIA_SOURCES = dht_storage dht_tracker + msg node node_entry refresh diff --git a/include/libtorrent/kademlia/msg.hpp b/include/libtorrent/kademlia/msg.hpp index 7ffafbac5..03de861bc 100644 --- a/include/libtorrent/kademlia/msg.hpp +++ b/include/libtorrent/kademlia/msg.hpp @@ -30,16 +30,17 @@ POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MSG_HPP -#define MSG_HPP +#ifndef TORRENT_KADEMLIA_MSG_HPP +#define TORRENT_KADEMLIA_MSG_HPP #include -#include -#include +#include "libtorrent/socket.hpp" +#include "libtorrent/kademlia/node_id.hpp" namespace libtorrent { struct bdecode_node; +struct entry; namespace dht { @@ -61,6 +62,40 @@ private: msg& operator=(msg const&); }; +struct key_desc_t +{ + char const* name; + int type; + int size; + int flags; + + enum { + // this argument is optional, parsing will not + // fail if it's not present + optional = 1, + // for dictionaries, the following entries refer + // to child nodes to this node, up until and including + // the next item that has the last_child flag set. + // these flags are nestable + parse_children = 2, + // this is the last item in a child dictionary + last_child = 4, + // the size argument refers to that the size + // has to be divisible by the number, instead + // of having that exact size + size_divisible = 8 + }; +}; + +// verifies that a message has all the required +// entries and returns them in ret +bool TORRENT_EXPORT verify_message(bdecode_node const& msg, key_desc_t const desc[] + , bdecode_node ret[], int size, char* error, int error_size); + +// generate an error response message +void TORRENT_EXPORT incoming_error(entry& e, char const* msg, int error_code = 203); + + } } #endif diff --git a/include/libtorrent/kademlia/node.hpp b/include/libtorrent/kademlia/node.hpp index ae18994c1..2075fb8b4 100644 --- a/include/libtorrent/kademlia/node.hpp +++ b/include/libtorrent/kademlia/node.hpp @@ -73,38 +73,8 @@ namespace libtorrent { namespace dht struct traversal_algorithm; struct dht_observer; -struct key_desc_t -{ - char const* name; - int type; - int size; - int flags; - - enum { - // this argument is optional, parsing will not - // fail if it's not present - optional = 1, - // for dictionaries, the following entries refer - // to child nodes to this node, up until and including - // the next item that has the last_child flag set. - // these flags are nestable - parse_children = 2, - // this is the last item in a child dictionary - last_child = 4, - // the size argument refers to that the size - // has to be divisible by the number, instead - // of having that exact size - size_divisible = 8 - }; -}; - -bool TORRENT_EXTRA_EXPORT verify_message(bdecode_node const& msg, key_desc_t const desc[] - , bdecode_node ret[], int size , char* error, int error_size); - void TORRENT_EXTRA_EXPORT write_nodes_entry(entry& r, nodes_t const& nodes); -void incoming_error(entry& e, char const* msg, int error_code = 203); - struct null_type {}; class announce_observer : public observer diff --git a/src/Makefile.am b/src/Makefile.am index a3a523f02..e47481878 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,8 @@ KADEMLIA_SOURCES = \ kademlia/dht_storage.cpp \ kademlia/dht_tracker.cpp \ kademlia/find_data.cpp \ - kademlia/put_data.cpp \ + kademlia/put_data.cpp \ + kademlia/msg.cpp \ kademlia/node.cpp \ kademlia/node_entry.cpp \ kademlia/node_id.cpp \ diff --git a/src/kademlia/msg.cpp b/src/kademlia/msg.cpp new file mode 100644 index 000000000..0a524038e --- /dev/null +++ b/src/kademlia/msg.cpp @@ -0,0 +1,141 @@ +/* + +Copyright (c) 2003-2015, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. +* Neither the name of the author nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "libtorrent/kademlia/msg.hpp" +#include "libtorrent/bdecode.hpp" +#include "libtorrent/entry.hpp" + +namespace libtorrent { namespace dht { + +bool verify_message(bdecode_node const& message, key_desc_t const desc[] + , bdecode_node ret[], int size, char* error, int error_size) +{ + // get a non-root bdecode_node that still + // points to the root. message should not be copied + bdecode_node msg = message.non_owning(); + + // clear the return buffer + for (int i = 0; i < size; ++i) + ret[i].clear(); + + // when parsing child nodes, this is the stack + // of bdecode_nodes to return to + bdecode_node stack[5]; + int stack_ptr = -1; + + if (msg.type() != bdecode_node::dict_t) + { + snprintf(error, error_size, "not a dictionary"); + return false; + } + ++stack_ptr; + stack[stack_ptr] = msg; + for (int i = 0; i < size; ++i) + { + key_desc_t const& k = desc[i]; + + // fprintf(stderr, "looking for %s in %s\n", k.name, print_entry(*msg).c_str()); + + ret[i] = msg.dict_find(k.name); + // none_t means any type + if (ret[i] && ret[i].type() != k.type && k.type != bdecode_node::none_t) + ret[i].clear(); + if (ret[i] == 0 && (k.flags & key_desc_t::optional) == 0) + { + // the key was not found, and it's not an optional key + snprintf(error, error_size, "missing '%s' key", k.name); + return false; + } + + if (k.size > 0 + && ret[i] + && k.type == bdecode_node::string_t) + { + bool invalid = false; + if (k.flags & key_desc_t::size_divisible) + invalid = (ret[i].string_length() % k.size) != 0; + else + invalid = ret[i].string_length() != k.size; + + if (invalid) + { + // the string was not of the required size + ret[i].clear(); + if ((k.flags & key_desc_t::optional) == 0) + { + snprintf(error, error_size, "invalid value for '%s'", k.name); + return false; + } + } + } + if (k.flags & key_desc_t::parse_children) + { + TORRENT_ASSERT(k.type == bdecode_node::dict_t); + + if (ret[i]) + { + ++stack_ptr; + TORRENT_ASSERT(stack_ptr < int(sizeof(stack) / sizeof(stack[0]))); + msg = ret[i]; + stack[stack_ptr] = msg; + } + else + { + // skip all children + while (i < size && (desc[i].flags & key_desc_t::last_child) == 0) ++i; + // if this assert is hit, desc is incorrect + TORRENT_ASSERT(i < size); + } + } + else if (k.flags & key_desc_t::last_child) + { + TORRENT_ASSERT(stack_ptr > 0); + // this can happen if the specification passed + // in is unbalanced. i.e. contain more last_child + // nodes than parse_children + if (stack_ptr == 0) return false; + --stack_ptr; + msg = stack[stack_ptr]; + } + } + return true; +} + +void incoming_error(entry& e, char const* msg, int error_code) +{ + e["y"] = "e"; + entry::list_type& l = e["e"].list(); + l.push_back(entry(error_code)); + l.push_back(entry(msg)); +} + +} } diff --git a/src/kademlia/node.cpp b/src/kademlia/node.cpp index b7ee97c2d..dd0a9bf9c 100644 --- a/src/kademlia/node.cpp +++ b/src/kademlia/node.cpp @@ -745,110 +745,6 @@ void TORRENT_EXTRA_EXPORT write_nodes_entry(entry& r, nodes_t const& nodes) } } -// verifies that a message has all the required -// entries and returns them in ret -bool verify_message(bdecode_node const& message, key_desc_t const desc[] - , bdecode_node ret[], int size , char* error, int error_size) -{ - // get a non-root bdecode_node that still - // points to the root. message should not be copied - bdecode_node msg = message.non_owning(); - - // clear the return buffer - for (int i = 0; i < size; ++i) - ret[i].clear(); - - // when parsing child nodes, this is the stack - // of bdecode_nodes to return to - bdecode_node stack[5]; - int stack_ptr = -1; - - if (msg.type() != bdecode_node::dict_t) - { - snprintf(error, error_size, "not a dictionary"); - return false; - } - ++stack_ptr; - stack[stack_ptr] = msg; - for (int i = 0; i < size; ++i) - { - key_desc_t const& k = desc[i]; - -// fprintf(stderr, "looking for %s in %s\n", k.name, print_entry(*msg).c_str()); - - ret[i] = msg.dict_find(k.name); - // none_t means any type - if (ret[i] && ret[i].type() != k.type && k.type != bdecode_node::none_t) - ret[i].clear(); - if (ret[i] == 0 && (k.flags & key_desc_t::optional) == 0) - { - // the key was not found, and it's not an optional key - snprintf(error, error_size, "missing '%s' key", k.name); - return false; - } - - if (k.size > 0 - && ret[i] - && k.type == bdecode_node::string_t) - { - bool invalid = false; - if (k.flags & key_desc_t::size_divisible) - invalid = (ret[i].string_length() % k.size) != 0; - else - invalid = ret[i].string_length() != k.size; - - if (invalid) - { - // the string was not of the required size - ret[i].clear(); - if ((k.flags & key_desc_t::optional) == 0) - { - snprintf(error, error_size, "invalid value for '%s'", k.name); - return false; - } - } - } - if (k.flags & key_desc_t::parse_children) - { - TORRENT_ASSERT(k.type == bdecode_node::dict_t); - - if (ret[i]) - { - ++stack_ptr; - TORRENT_ASSERT(stack_ptr < int(sizeof(stack)/sizeof(stack[0]))); - msg = ret[i]; - stack[stack_ptr] = msg; - } - else - { - // skip all children - while (i < size && (desc[i].flags & key_desc_t::last_child) == 0) ++i; - // if this assert is hit, desc is incorrect - TORRENT_ASSERT(i < size); - } - } - else if (k.flags & key_desc_t::last_child) - { - TORRENT_ASSERT(stack_ptr > 0); - // this can happen if the specification passed - // in is unbalanced. i.e. contain more last_child - // nodes than parse_children - if (stack_ptr == 0) return false; - --stack_ptr; - msg = stack[stack_ptr]; - } - } - return true; -} - -void incoming_error(entry& e, char const* msg, int error_code) -{ - e["y"] = "e"; - entry::list_type& l = e["e"].list(); - l.push_back(entry(error_code)); - l.push_back(entry(msg)); -} - // build response void node::incoming_request(msg const& m, entry& e) { From ac01ccc43af3b4df97a3524b6d15919f8f68c8b0 Mon Sep 17 00:00:00 2001 From: Steven Siloti Date: Tue, 29 Dec 2015 20:27:46 -0800 Subject: [PATCH 2/3] add templated wrapper around verify_message It was too easy to forget to update the ret and size parameters when the size of desec changed. With this change we now automatically get the size of desc and enforce that ret has the same size. It would be nice if we could use bdecode_node ret[static Size] from C99 but that is not widely supported. --- include/libtorrent/kademlia/msg.hpp | 21 ++- src/kademlia/msg.cpp | 6 +- src/kademlia/node.cpp | 12 +- test/test_dht.cpp | 252 ++++++++++++++++------------ 4 files changed, 169 insertions(+), 122 deletions(-) diff --git a/include/libtorrent/kademlia/msg.hpp b/include/libtorrent/kademlia/msg.hpp index 03de861bc..09f84c1b3 100644 --- a/include/libtorrent/kademlia/msg.hpp +++ b/include/libtorrent/kademlia/msg.hpp @@ -87,14 +87,25 @@ struct key_desc_t }; }; -// verifies that a message has all the required -// entries and returns them in ret -bool TORRENT_EXPORT verify_message(bdecode_node const& msg, key_desc_t const desc[] - , bdecode_node ret[], int size, char* error, int error_size); - // generate an error response message void TORRENT_EXPORT incoming_error(entry& e, char const* msg, int error_code = 203); +// given a redundent name to avoid clashing with libtorrent::detail +namespace dht_detail { + +bool TORRENT_EXPORT verify_message(bdecode_node const& msg, key_desc_t const desc[] + , bdecode_node ret[], int size, char* error, int error_size); + +} + +// verifies that a message has all the required +// entries and returns them in ret +template +bool verify_message(bdecode_node const& msg, key_desc_t const (&desc)[Size] + , bdecode_node (&ret)[Size], char* error, int error_size) +{ + return dht_detail::verify_message(msg, desc, ret, Size, error, error_size); +} } } diff --git a/src/kademlia/msg.cpp b/src/kademlia/msg.cpp index 0a524038e..b4a6f9710 100644 --- a/src/kademlia/msg.cpp +++ b/src/kademlia/msg.cpp @@ -36,8 +36,10 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { namespace dht { +namespace dht_detail { + bool verify_message(bdecode_node const& message, 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) { // get a non-root bdecode_node that still // points to the root. message should not be copied @@ -130,6 +132,8 @@ bool verify_message(bdecode_node const& message, key_desc_t const desc[] return true; } +} + void incoming_error(entry& e, char const* msg, int error_code) { e["y"] = "e"; diff --git a/src/kademlia/node.cpp b/src/kademlia/node.cpp index dd0a9bf9c..20a4f1066 100644 --- a/src/kademlia/node.cpp +++ b/src/kademlia/node.cpp @@ -764,7 +764,7 @@ void node::incoming_request(msg const& m, entry& e) bdecode_node top_level[4]; char error_string[200]; - if (!verify_message(m.message, top_desc, top_level, 4, error_string + if (!verify_message(m.message, top_desc, top_level, error_string , sizeof(error_string))) { incoming_error(e, error_string); @@ -816,7 +816,7 @@ void node::incoming_request(msg const& m, entry& e) }; bdecode_node msg_keys[3]; - if (!verify_message(arg_ent, msg_desc, msg_keys, 3, error_string + if (!verify_message(arg_ent, msg_desc, msg_keys, error_string , sizeof(error_string))) { m_counters.inc_stats_counter(counters::dht_invalid_get_peers); @@ -854,7 +854,7 @@ void node::incoming_request(msg const& m, entry& e) }; bdecode_node msg_keys[1]; - if (!verify_message(arg_ent, msg_desc, msg_keys, 1, error_string, sizeof(error_string))) + if (!verify_message(arg_ent, msg_desc, msg_keys, error_string, sizeof(error_string))) { incoming_error(e, error_string); return; @@ -880,7 +880,7 @@ void node::incoming_request(msg const& m, entry& e) }; bdecode_node msg_keys[6]; - if (!verify_message(arg_ent, msg_desc, msg_keys, 6, error_string, sizeof(error_string))) + if (!verify_message(arg_ent, msg_desc, msg_keys, error_string, sizeof(error_string))) { m_counters.inc_stats_counter(counters::dht_invalid_announce); incoming_error(e, error_string); @@ -943,7 +943,7 @@ void node::incoming_request(msg const& m, entry& e) // attempt to parse the message bdecode_node msg_keys[7]; - if (!verify_message(arg_ent, msg_desc, msg_keys, 7, error_string, sizeof(error_string))) + if (!verify_message(arg_ent, msg_desc, msg_keys, error_string, sizeof(error_string))) { m_counters.inc_stats_counter(counters::dht_invalid_put); incoming_error(e, error_string); @@ -1088,7 +1088,7 @@ void node::incoming_request(msg const& m, entry& e) // attempt to parse the message bdecode_node msg_keys[2]; - if (!verify_message(arg_ent, msg_desc, msg_keys, 2, error_string + if (!verify_message(arg_ent, msg_desc, msg_keys, error_string , sizeof(error_string))) { m_counters.inc_stats_counter(counters::dht_invalid_get); diff --git a/test/test_dht.cpp b/test/test_dht.cpp index aa6fcc389..cb1b1cd5f 100644 --- a/test/test_dht.cpp +++ b/test/test_dht.cpp @@ -334,11 +334,11 @@ void announce_immutable_items(node& node, udp::endpoint const* eps { "y", bdecode_node::string_t, 1, 0}, }; - bdecode_node parsed[6]; + bdecode_node parsed[5]; char error_string[200]; // fprintf(stderr, "msg: %s\n", print_entry(response).c_str()); - int ret = verify_message(response, desc, parsed, 5, error_string + int ret = verify_message(response, desc, parsed, error_string , sizeof(error_string)); if (ret) { @@ -372,14 +372,15 @@ void announce_immutable_items(node& node, udp::endpoint const* eps { "y", bdecode_node::string_t, 1, 0 } }; - ret = verify_message(response, desc2, parsed, 1, error_string + bdecode_node parsed2[1]; + ret = verify_message(response, desc2, parsed2, error_string , sizeof(error_string)); if (ret) { - if (parsed[0].string_value() != "r") + if (parsed2[0].string_value() != "r") fprintf(stderr, "msg: %s\n", print_entry(response).c_str()); - TEST_EQUAL(parsed[0].string_value(), "r"); + TEST_EQUAL(parsed2[0].string_value(), "r"); } else { @@ -408,7 +409,7 @@ void announce_immutable_items(node& node, udp::endpoint const* eps bdecode_node parsed[4]; char error_string[200]; - int ret = verify_message(response, desc, parsed, 4, error_string + int ret = verify_message(response, desc, parsed, error_string , sizeof(error_string)); if (ret) { @@ -526,7 +527,6 @@ TORRENT_TEST(dht) // DHT should be running on port 48199 now bdecode_node response; - bdecode_node parsed[11]; char error_string[200]; bool ret; @@ -541,14 +541,16 @@ TORRENT_TEST(dht) {"id", bdecode_node::string_t, 20, key_desc_t::last_child}, }; + bdecode_node pong_keys[4]; + fprintf(stderr, "msg: %s\n", print_entry(response).c_str()); - ret = dht::verify_message(response, pong_desc, parsed, 4, error_string + ret = dht::verify_message(response, pong_desc, pong_keys, error_string , sizeof(error_string)); TEST_CHECK(ret); if (ret) { - TEST_CHECK(parsed[0].string_value() == "r"); - TEST_CHECK(parsed[1].string_value() == "10"); + TEST_CHECK(pong_keys[0].string_value() == "r"); + TEST_CHECK(pong_keys[1].string_value() == "10"); } else { @@ -564,17 +566,19 @@ TORRENT_TEST(dht) {"e", bdecode_node::list_t, 2, 0} }; + bdecode_node err_keys[2]; + fprintf(stderr, "msg: %s\n", print_entry(response).c_str()); - ret = dht::verify_message(response, err_desc, parsed, 2, error_string + ret = dht::verify_message(response, err_desc, err_keys, error_string , sizeof(error_string)); TEST_CHECK(ret); if (ret) { - TEST_CHECK(parsed[0].string_value() == "e"); - if (parsed[1].list_at(0).type() == bdecode_node::int_t - && parsed[1].list_at(1).type() == bdecode_node::string_t) + TEST_CHECK(err_keys[0].string_value() == "e"); + if (err_keys[1].list_at(0).type() == bdecode_node::int_t + && err_keys[1].list_at(1).type() == bdecode_node::string_t) { - TEST_CHECK(parsed[1].list_at(1).string_value() == "missing 'target' key"); + TEST_CHECK(err_keys[1].list_at(1).string_value() == "missing 'target' key"); } else { @@ -598,15 +602,17 @@ TORRENT_TEST(dht) {"id", bdecode_node::string_t, 20, key_desc_t::last_child}, }; + bdecode_node peer1_keys[4]; + std::string token; fprintf(stderr, "msg: %s\n", print_entry(response).c_str()); - ret = dht::verify_message(response, peer1_desc, parsed, 4, error_string + ret = dht::verify_message(response, peer1_desc, peer1_keys, error_string , sizeof(error_string)); TEST_CHECK(ret); if (ret) { - TEST_CHECK(parsed[0].string_value() == "r"); - token = parsed[2].string_value(); + TEST_CHECK(peer1_keys[0].string_value() == "r"); + token = peer1_keys[2].string_value(); // fprintf(stderr, "got token: %s\n", token.c_str()); } else @@ -631,13 +637,15 @@ TORRENT_TEST(dht) {"id", bdecode_node::string_t, 20, key_desc_t::last_child}, }; + bdecode_node ann_keys[3]; + fprintf(stderr, "msg: %s\n", print_entry(response).c_str()); - ret = dht::verify_message(response, ann_desc, parsed, 3, error_string + ret = dht::verify_message(response, ann_desc, ann_keys, error_string , sizeof(error_string)); TEST_CHECK(ret); if (ret) { - TEST_CHECK(parsed[0].string_value() == "r"); + TEST_CHECK(ann_keys[0].string_value() == "r"); } else { @@ -654,13 +662,13 @@ TORRENT_TEST(dht) send_dht_request(node, "get_peers", source, &response , msg_args().info_hash("01010101010101010101")); - ret = dht::verify_message(response, peer1_desc, parsed, 4, error_string + ret = dht::verify_message(response, peer1_desc, peer1_keys, error_string , sizeof(error_string)); if (ret) { - TEST_CHECK(parsed[0].string_value() == "r"); - token = parsed[2].string_value(); + TEST_CHECK(peer1_keys[0].string_value() == "r"); + token = peer1_keys[2].string_value(); // fprintf(stderr, "got token: %s\n", token.c_str()); } else @@ -693,19 +701,21 @@ TORRENT_TEST(dht) {"id", bdecode_node::string_t, 20, key_desc_t::last_child}, }; + bdecode_node peer2_keys[5]; + fprintf(stderr, "msg: %s\n", print_entry(response).c_str()); - ret = dht::verify_message(response, peer2_desc, parsed, 5, error_string + ret = dht::verify_message(response, peer2_desc, peer2_keys, error_string , sizeof(error_string)); TEST_CHECK(ret); if (ret) { - TEST_CHECK(parsed[0].string_value() == "r"); - TEST_EQUAL(parsed[1].dict_find_string_value("n"), "test"); + TEST_CHECK(peer2_keys[0].string_value() == "r"); + TEST_EQUAL(peer2_keys[1].dict_find_string_value("n"), "test"); bloom_filter<256> downloaders; bloom_filter<256> seeds; - downloaders.from_string(parsed[2].string_ptr()); - seeds.from_string(parsed[3].string_ptr()); + downloaders.from_string(peer2_keys[2].string_ptr()); + seeds.from_string(peer2_keys[3].string_ptr()); fprintf(stderr, "seeds: %f\n", seeds.size()); fprintf(stderr, "downloaders: %f\n", downloaders.size()); @@ -749,16 +759,16 @@ TORRENT_TEST(dht) send_dht_request(node, "find_node", source, &response , msg_args().target("0101010101010101010101010101010101010101").nid(nid)); - ret = dht::verify_message(response, err_desc, parsed, 2, error_string + ret = dht::verify_message(response, err_desc, err_keys, error_string , sizeof(error_string)); TEST_CHECK(ret); if (ret) { - TEST_CHECK(parsed[0].string_value() == "e"); - if (parsed[1].list_at(0).type() == bdecode_node::int_t - && parsed[1].list_at(1).type() == bdecode_node::string_t) + TEST_CHECK(err_keys[0].string_value() == "e"); + if (err_keys[1].list_at(0).type() == bdecode_node::int_t + && err_keys[1].list_at(1).type() == bdecode_node::string_t) { - TEST_CHECK(parsed[1].list_at(1).string_value() == "invalid node ID"); + TEST_CHECK(err_keys[1].list_at(1).string_value() == "invalid node ID"); } else { @@ -786,13 +796,15 @@ TORRENT_TEST(dht) {"id", bdecode_node::string_t, 20, key_desc_t::last_child}, }; + bdecode_node nodes_keys[3]; + fprintf(stderr, "msg: %s\n", print_entry(response).c_str()); - ret = dht::verify_message(response, nodes_desc, parsed, 3, error_string + ret = dht::verify_message(response, nodes_desc, nodes_keys, error_string , sizeof(error_string)); TEST_CHECK(ret); if (ret) { - TEST_CHECK(parsed[0].string_value() == "r"); + TEST_CHECK(nodes_keys[0].string_value() == "r"); } else { @@ -878,12 +890,16 @@ TORRENT_TEST(dht) { "y", bdecode_node::string_t, 1, 0 } }; + bdecode_node desc2_keys[1]; + key_desc_t desc_error[] = { { "e", bdecode_node::list_t, 2, 0 }, { "y", bdecode_node::string_t, 1, 0}, }; + bdecode_node desc_error_keys[2]; + // ==== get / put mutable items === std::pair itemv; @@ -934,12 +950,14 @@ TORRENT_TEST(dht) { "y", bdecode_node::string_t, 1, 0}, }; - ret = verify_message(response, desc, parsed, 5, error_string + bdecode_node desc_keys[5]; + + ret = verify_message(response, desc, desc_keys, error_string , sizeof(error_string)); if (ret) { - TEST_EQUAL(parsed[4].string_value(), "r"); - token = parsed[2].string_value(); + TEST_EQUAL(desc_keys[4].string_value(), "r"); + token = desc_keys[2].string_value(); fprintf(stderr, "get response: %s\n" , print_entry(response).c_str()); fprintf(stderr, "got token: %s\n", to_hex(token).c_str()); @@ -968,13 +986,13 @@ TORRENT_TEST(dht) .seq(seq) .salt(salt.first)); - ret = verify_message(response, desc2, parsed, 1, error_string + ret = verify_message(response, desc2, desc2_keys, error_string , sizeof(error_string)); if (ret) { fprintf(stderr, "put response: %s\n" , print_entry(response).c_str()); - TEST_EQUAL(parsed[0].string_value(), "r"); + TEST_EQUAL(desc2_keys[0].string_value(), "r"); } else { @@ -1000,7 +1018,9 @@ TORRENT_TEST(dht) { "y", bdecode_node::string_t, 1, 0}, }; - ret = verify_message(response, desc3, parsed, 7, error_string + bdecode_node desc3_keys[7]; + + ret = verify_message(response, desc3, desc3_keys, error_string , sizeof(error_string)); if (ret == 0) { @@ -1016,10 +1036,10 @@ TORRENT_TEST(dht) char value[1020]; char* ptr = value; int value_len = bencode(ptr, items[0].ent); - TEST_EQUAL(value_len, parsed[2].data_section().second); - TEST_CHECK(memcmp(parsed[2].data_section().first, value, value_len) == 0); + TEST_EQUAL(value_len, desc3_keys[2].data_section().second); + TEST_CHECK(memcmp(desc3_keys[2].data_section().first, value, value_len) == 0); - TEST_EQUAL(seq, parsed[3].int_value()); + TEST_EQUAL(seq, desc3_keys[3].int_value()); } // also test that invalid signatures fail! @@ -1046,14 +1066,14 @@ TORRENT_TEST(dht) .seq(seq) .salt(salt.first)); - ret = verify_message(response, desc_error, parsed, 2, error_string + ret = verify_message(response, desc_error, desc_error_keys, error_string , sizeof(error_string)); if (ret) { fprintf(stderr, "put response: %s\n", print_entry(response).c_str()); - TEST_EQUAL(parsed[1].string_value(), "e"); + TEST_EQUAL(desc_error_keys[1].string_value(), "e"); // 206 is the code for invalid signature - TEST_EQUAL(parsed[0].list_int_value_at(0), 206); + TEST_EQUAL(desc_error_keys[0].list_int_value_at(0), 206); } else { @@ -1113,13 +1133,13 @@ TORRENT_TEST(dht) .cas(cas) .salt(salt.first)); - ret = verify_message(response, desc2, parsed, 1, error_string + ret = verify_message(response, desc2, desc2_keys, error_string , sizeof(error_string)); if (ret) { fprintf(stderr, "put response: %s\n" , print_entry(response).c_str()); - TEST_EQUAL(parsed[0].string_value(), "r"); + TEST_EQUAL(desc2_keys[0].string_value(), "r"); } else { @@ -1143,15 +1163,15 @@ TORRENT_TEST(dht) .cas(cas) .salt(salt.first)); - ret = verify_message(response, desc_error, parsed, 2, error_string + ret = verify_message(response, desc_error, desc_error_keys, error_string , sizeof(error_string)); if (ret) { fprintf(stderr, "put response: %s\n" , print_entry(response).c_str()); - TEST_EQUAL(parsed[1].string_value(), "e"); + TEST_EQUAL(desc_error_keys[1].string_value(), "e"); // 301 is the error code for CAS hash mismatch - TEST_EQUAL(parsed[0].list_int_value_at(0), 301); + TEST_EQUAL(desc_error_keys[0].list_int_value_at(0), 301); } else { @@ -1415,6 +1435,8 @@ TORRENT_TEST(dht) {"info_hash", bdecode_node::string_t, 20, key_desc_t::optional | key_desc_t::last_child}, }; + bdecode_node find_node_keys[7]; + dht::key_desc_t get_peers_desc[] = { {"y", bdecode_node::string_t, 1, 0}, {"t", bdecode_node::string_t, 2, 0}, @@ -1424,6 +1446,8 @@ TORRENT_TEST(dht) {"info_hash", bdecode_node::string_t, 20, key_desc_t::last_child}, }; + bdecode_node get_peers_keys[6]; + dht::key_desc_t get_item_desc[] = { {"y", bdecode_node::string_t, 1, 0}, {"t", bdecode_node::string_t, 2, 0}, @@ -1433,6 +1457,8 @@ TORRENT_TEST(dht) {"target", bdecode_node::string_t, 20, key_desc_t::last_child}, }; + bdecode_node get_item_keys[6]; + // bootstrap @@ -1451,17 +1477,17 @@ TORRENT_TEST(dht) TEST_EQUAL(g_sent_packets.front().first, initial_node); lazy_from_entry(g_sent_packets.front().second, response); - ret = verify_message(response, find_node_desc, parsed, 7, error_string + ret = verify_message(response, find_node_desc, find_node_keys, error_string , sizeof(error_string)); if (ret) { - TEST_EQUAL(parsed[0].string_value(), "q"); - TEST_CHECK(parsed[2].string_value() == "find_node" - || parsed[2].string_value() == "get_peers"); + TEST_EQUAL(find_node_keys[0].string_value(), "q"); + TEST_CHECK(find_node_keys[2].string_value() == "find_node" + || find_node_keys[2].string_value() == "get_peers"); - if (parsed[0].string_value() != "q" - || (parsed[2].string_value() != "find_node" - && parsed[2].string_value() != "get_peers")) break; + if (find_node_keys[0].string_value() != "q" + || (find_node_keys[2].string_value() != "find_node" + && find_node_keys[2].string_value() != "get_peers")) break; } else { @@ -1481,15 +1507,15 @@ TORRENT_TEST(dht) TEST_EQUAL(g_sent_packets.front().first, found_node); lazy_from_entry(g_sent_packets.front().second, response); - ret = verify_message(response, find_node_desc, parsed, 7, error_string + ret = verify_message(response, find_node_desc, find_node_keys, error_string , sizeof(error_string)); if (ret) { - TEST_EQUAL(parsed[0].string_value(), "q"); - TEST_CHECK(parsed[2].string_value() == "find_node" - || parsed[2].string_value() == "get_peers"); - if (parsed[0].string_value() != "q" || (parsed[2].string_value() != "find_node" - && parsed[2].string_value() == "get_peers")) break; + TEST_EQUAL(find_node_keys[0].string_value(), "q"); + TEST_CHECK(find_node_keys[2].string_value() == "find_node" + || find_node_keys[2].string_value() == "get_peers"); + if (find_node_keys[0].string_value() != "q" || (find_node_keys[2].string_value() != "find_node" + && find_node_keys[2].string_value() == "get_peers")) break; } else { @@ -1523,14 +1549,14 @@ TORRENT_TEST(dht) TEST_EQUAL(g_sent_packets.front().first, initial_node); lazy_from_entry(g_sent_packets.front().second, response); - ret = verify_message(response, get_peers_desc, parsed, 6, error_string + ret = verify_message(response, get_peers_desc, get_peers_keys, error_string , sizeof(error_string)); if (ret) { - TEST_EQUAL(parsed[0].string_value(), "q"); - TEST_EQUAL(parsed[2].string_value(), "get_peers"); - TEST_EQUAL(parsed[5].string_value(), target.to_string()); - if (parsed[0].string_value() != "q" || parsed[2].string_value() != "get_peers") break; + TEST_EQUAL(get_peers_keys[0].string_value(), "q"); + TEST_EQUAL(get_peers_keys[2].string_value(), "get_peers"); + TEST_EQUAL(get_peers_keys[5].string_value(), target.to_string()); + if (get_peers_keys[0].string_value() != "q" || get_peers_keys[2].string_value() != "get_peers") break; } else { @@ -1557,14 +1583,14 @@ TORRENT_TEST(dht) TEST_EQUAL(g_sent_packets.front().first, next_node); lazy_from_entry(g_sent_packets.front().second, response); - ret = verify_message(response, get_peers_desc, parsed, 6, error_string + ret = verify_message(response, get_peers_desc, get_peers_keys, error_string , sizeof(error_string)); if (ret) { - TEST_EQUAL(parsed[0].string_value(), "q"); - TEST_EQUAL(parsed[2].string_value(), "get_peers"); - TEST_EQUAL(parsed[5].string_value(), target.to_string()); - if (parsed[0].string_value() != "q" || parsed[2].string_value() != "get_peers") break; + TEST_EQUAL(get_peers_keys[0].string_value(), "q"); + TEST_EQUAL(get_peers_keys[2].string_value(), "get_peers"); + TEST_EQUAL(get_peers_keys[5].string_value(), target.to_string()); + if (get_peers_keys[0].string_value() != "q" || get_peers_keys[2].string_value() != "get_peers") break; } else { @@ -1618,14 +1644,14 @@ TORRENT_TEST(dht) TEST_EQUAL(g_sent_packets.front().first, initial_node); lazy_from_entry(g_sent_packets.front().second, response); - ret = verify_message(response, get_item_desc, parsed, 6, error_string + ret = verify_message(response, get_item_desc, get_item_keys, error_string , sizeof(error_string)); if (ret) { - TEST_EQUAL(parsed[0].string_value(), "q"); - TEST_EQUAL(parsed[2].string_value(), "get"); - TEST_EQUAL(parsed[5].string_value(), items[0].target.to_string()); - if (parsed[0].string_value() != "q" || parsed[2].string_value() != "get") break; + TEST_EQUAL(get_item_keys[0].string_value(), "q"); + TEST_EQUAL(get_item_keys[2].string_value(), "get"); + TEST_EQUAL(get_item_keys[5].string_value(), items[0].target.to_string()); + if (get_item_keys[0].string_value() != "q" || get_item_keys[2].string_value() != "get") break; } else { @@ -1664,13 +1690,13 @@ TORRENT_TEST(dht) TEST_EQUAL(g_sent_packets.front().first, initial_node); lazy_from_entry(g_sent_packets.front().second, response); - ret = verify_message(response, get_item_desc, parsed, 6, error_string + ret = verify_message(response, get_item_desc, get_item_keys, error_string , sizeof(error_string)); if (ret) { - TEST_EQUAL(parsed[0].string_value(), "q"); - TEST_EQUAL(parsed[2].string_value(), "get"); - if (parsed[0].string_value() != "q" || parsed[2].string_value() != "get") break; + TEST_EQUAL(get_item_keys[0].string_value(), "q"); + TEST_EQUAL(get_item_keys[2].string_value(), "get"); + if (get_item_keys[0].string_value() != "q" || get_item_keys[2].string_value() != "get") break; } else { @@ -1714,6 +1740,8 @@ TORRENT_TEST(dht) {"v", bdecode_node::none_t, 0, key_desc_t::last_child}, }; + bdecode_node put_immutable_item_keys[7]; + dht::key_desc_t put_mutable_item_desc[] = { {"y", bdecode_node::string_t, 1, 0}, {"t", bdecode_node::string_t, 2, 0}, @@ -1728,6 +1756,8 @@ TORRENT_TEST(dht) {"v", bdecode_node::none_t, 0, key_desc_t::last_child}, }; + bdecode_node put_mutable_item_keys[11]; + // immutable put g_sent_packets.clear(); for (int loop = 0; loop < 9; loop++) @@ -1769,7 +1799,7 @@ TORRENT_TEST(dht) if (packet == g_sent_packets.end()) continue; lazy_from_entry(packet->second, response); - ret = verify_message(response, get_item_desc, parsed, 6, error_string + ret = verify_message(response, get_item_desc, get_item_keys, error_string , sizeof(error_string)); if (!ret) { @@ -1798,18 +1828,19 @@ TORRENT_TEST(dht) if (packet == g_sent_packets.end()) continue; lazy_from_entry(packet->second, response); - ret = verify_message(response, put_immutable_item_desc, parsed, 7 + ret = verify_message(response, put_immutable_item_desc, put_immutable_item_keys , error_string, sizeof(error_string)); if (ret) { - TEST_EQUAL(parsed[0].string_value(), "q"); - TEST_EQUAL(parsed[2].string_value(), "put"); - std::pairv = parsed[6].data_section(); + TEST_EQUAL(put_immutable_item_keys[0].string_value(), "q"); + TEST_EQUAL(put_immutable_item_keys[2].string_value(), "put"); + std::pairv = put_immutable_item_keys[6].data_section(); TEST_EQUAL(std::string(v.first, v.second), flat_data); char t[10]; snprintf(t, sizeof(t), "%02d", i); - TEST_EQUAL(parsed[5].string_value(), t); - if (parsed[0].string_value() != "q" || parsed[2].string_value() != "put") continue; + TEST_EQUAL(put_immutable_item_keys[5].string_value(), t); + if (put_immutable_item_keys[0].string_value() != "q" + || put_immutable_item_keys[2].string_value() != "put") continue; if (i < loop) send_dht_response(node, response, nodes[i].ep()); } @@ -1865,7 +1896,7 @@ TORRENT_TEST(dht) if (packet == g_sent_packets.end()) continue; lazy_from_entry(packet->second, response); - ret = verify_message(response, get_item_desc, parsed, 6, error_string + ret = verify_message(response, get_item_desc, get_item_keys, error_string , sizeof(error_string)); if (!ret) { @@ -1895,22 +1926,23 @@ TORRENT_TEST(dht) if (packet == g_sent_packets.end()) continue; lazy_from_entry(packet->second, response); - ret = verify_message(response, put_mutable_item_desc, parsed, 11 + ret = verify_message(response, put_mutable_item_desc, put_mutable_item_keys , error_string, sizeof(error_string)); if (ret) { - TEST_EQUAL(parsed[0].string_value(), "q"); - TEST_EQUAL(parsed[2].string_value(), "put"); - TEST_EQUAL(parsed[6].string_value(), std::string(public_key, item_pk_len)); - TEST_EQUAL(parsed[7].int_value(), seq); - TEST_EQUAL(parsed[8].string_value(), sig); - std::pair v = parsed[10].data_section(); + 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[6].string_value(), std::string(public_key, item_pk_len)); + TEST_EQUAL(put_mutable_item_keys[7].int_value(), seq); + TEST_EQUAL(put_mutable_item_keys[8].string_value(), sig); + std::pair v = put_mutable_item_keys[10].data_section(); TEST_EQUAL(v.second, itemv.second); TEST_CHECK(memcmp(v.first, itemv.first, itemv.second) == 0); char t[10]; snprintf(t, sizeof(t), "%02d", i); - TEST_EQUAL(parsed[9].string_value(), t); - if (parsed[0].string_value() != "q" || parsed[2].string_value() != "put") continue; + TEST_EQUAL(put_mutable_item_keys[9].string_value(), t); + if (put_mutable_item_keys[0].string_value() != "q" + || put_mutable_item_keys[2].string_value() != "put") continue; if (i < loop) send_dht_response(node, response, nodes[i].ep()); } @@ -1979,7 +2011,7 @@ TORRENT_TEST(dht) if (packet == g_sent_packets.end()) continue; lazy_from_entry(packet->second, response); - ret = verify_message(response, get_item_desc, parsed, 6, error_string + ret = verify_message(response, get_item_desc, get_item_keys, error_string , sizeof(error_string)); if (!ret) { @@ -2111,7 +2143,7 @@ TORRENT_TEST(verify_message) bdecode(test_msg, test_msg + sizeof(test_msg)-1, ent, ec); fprintf(stderr, "%s\n", print_entry(ent).c_str()); - bool ret = verify_message(ent, msg_desc, msg_keys, 7, error_string + bool ret = verify_message(ent, msg_desc, msg_keys, error_string , sizeof(error_string)); TEST_CHECK(ret); TEST_CHECK(msg_keys[0]); @@ -2129,7 +2161,7 @@ TORRENT_TEST(verify_message) bdecode(test_msg2, test_msg2 + sizeof(test_msg2)-1, ent, ec); fprintf(stderr, "%s\n", print_entry(ent).c_str()); - ret = verify_message(ent, msg_desc, msg_keys, 7, error_string + ret = verify_message(ent, msg_desc, msg_keys, error_string , sizeof(error_string)); TEST_CHECK(ret); TEST_CHECK(msg_keys[0]); @@ -2148,7 +2180,7 @@ TORRENT_TEST(verify_message) bdecode(test_msg3, test_msg3 + sizeof(test_msg3)-1, ent, ec); fprintf(stderr, "%s\n", print_entry(ent).c_str()); - ret = verify_message(ent, msg_desc, msg_keys, 7, error_string + ret = verify_message(ent, msg_desc, msg_keys, error_string , sizeof(error_string)); TEST_CHECK(!ret); fprintf(stderr, "%s\n", error_string); @@ -2158,7 +2190,7 @@ TORRENT_TEST(verify_message) bdecode(test_msg4, test_msg4 + sizeof(test_msg4)-1, ent, ec); fprintf(stderr, "%s\n", print_entry(ent).c_str()); - ret = verify_message(ent, msg_desc, msg_keys, 7, error_string + ret = verify_message(ent, msg_desc, msg_keys, error_string , sizeof(error_string)); TEST_CHECK(!ret); fprintf(stderr, "%s\n", error_string); @@ -2168,7 +2200,7 @@ TORRENT_TEST(verify_message) bdecode(test_msg5, test_msg5 + sizeof(test_msg5)-1, ent, ec); fprintf(stderr, "%s\n", print_entry(ent).c_str()); - ret = verify_message(ent, msg_desc, msg_keys, 7, error_string + ret = verify_message(ent, msg_desc, msg_keys, error_string , sizeof(error_string)); TEST_CHECK(!ret); fprintf(stderr, "%s\n", error_string); @@ -2330,7 +2362,7 @@ TORRENT_TEST(read_only_node) }; lazy_from_entry(g_sent_packets.front().second, request); - bool ret = verify_message(request, get_item_desc, parsed, 7, error_string + bool ret = verify_message(request, get_item_desc, parsed, error_string , sizeof(error_string)); TEST_CHECK(ret); @@ -2356,14 +2388,14 @@ TORRENT_TEST(read_only_node) // both of them shouldn't have a 'ro' key. lazy_from_entry(g_sent_packets.front().second, request); - ret = verify_message(request, get_item_desc, parsed, 7, error_string + ret = verify_message(request, get_item_desc, parsed, error_string , sizeof(error_string)); TEST_CHECK(ret); TEST_CHECK(!parsed[3]); lazy_from_entry(g_sent_packets.back().second, request); - ret = verify_message(request, get_item_desc, parsed, 7, error_string + ret = verify_message(request, get_item_desc, parsed, error_string , sizeof(error_string)); TEST_CHECK(ret); From 30076218f801ba33bfb62a3dcd17079c95c28f11 Mon Sep 17 00:00:00 2001 From: Steven Siloti Date: Wed, 30 Dec 2015 17:25:00 -0800 Subject: [PATCH 3/3] entry is a class not a struct --- include/libtorrent/kademlia/msg.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libtorrent/kademlia/msg.hpp b/include/libtorrent/kademlia/msg.hpp index 09f84c1b3..9b852c253 100644 --- a/include/libtorrent/kademlia/msg.hpp +++ b/include/libtorrent/kademlia/msg.hpp @@ -40,7 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { struct bdecode_node; -struct entry; +class entry; namespace dht {