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 0657b2eba..e29f87d29 100644 --- a/Jamfile +++ b/Jamfile @@ -670,6 +670,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..9b852c253 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; +class entry; namespace dht { @@ -61,6 +62,51 @@ 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 + }; +}; + +// 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); +} + } } #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..b4a6f9710 --- /dev/null +++ b/src/kademlia/msg.cpp @@ -0,0 +1,145 @@ +/* + +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 { + +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) +{ + // 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..20a4f1066 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) { @@ -868,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); @@ -920,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); @@ -958,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; @@ -984,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); @@ -1047,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); @@ -1192,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);