forked from premiere/premiere-libtorrent
extended DHT unit test to include error reporting
This commit is contained in:
parent
7d4338b7f7
commit
138fb8c679
|
@ -72,6 +72,19 @@ TORRENT_DECLARE_LOG(node);
|
|||
|
||||
class traversal_algorithm;
|
||||
|
||||
struct key_desc_t
|
||||
{
|
||||
char const* name;
|
||||
int type;
|
||||
int size;
|
||||
int flags;
|
||||
|
||||
enum { optional = 1};
|
||||
};
|
||||
|
||||
bool TORRENT_EXPORT verify_message(lazy_entry const* msg, key_desc_t const desc[], lazy_entry const* ret[]
|
||||
, int size , char* error, int error_size);
|
||||
|
||||
// this is the entry for every peer
|
||||
// the timestamp is there to make it possible
|
||||
// to remove stale peers
|
||||
|
|
|
@ -651,57 +651,48 @@ namespace
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct key_desc_t
|
||||
// verifies that a message has all the required
|
||||
// entries and returns them in ret
|
||||
bool verify_message(lazy_entry const* msg, key_desc_t const desc[], lazy_entry const* ret[]
|
||||
, int size , char* error, int error_size)
|
||||
{
|
||||
// clear the return buffer
|
||||
memset(ret, 0, sizeof(ret[0]) * size);
|
||||
|
||||
if (msg->type() != lazy_entry::dict_t)
|
||||
{
|
||||
char const* name;
|
||||
int type;
|
||||
int size;
|
||||
int flags;
|
||||
|
||||
enum { optional = 1};
|
||||
};
|
||||
|
||||
// verifies that a message has all the required
|
||||
// entries and returns them in ret
|
||||
bool verify_message(lazy_entry const* msg, key_desc_t const desc[], lazy_entry const* ret[]
|
||||
, int size , char* error, int error_size)
|
||||
snprintf(error, error_size, "not a dictionary");
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
for (int i = 0; i < size; ++i) ret[i] = 0;
|
||||
|
||||
if (msg->type() != lazy_entry::dict_t)
|
||||
key_desc_t const& k = desc[i];
|
||||
ret[i] = msg->dict_find(k.name);
|
||||
if (ret[i] && ret[i]->type() != k.type) ret[i] = 0;
|
||||
if (ret[i] == 0 && (k.flags & key_desc_t::optional) == 0)
|
||||
{
|
||||
snprintf(error, error_size, "not a dictionary");
|
||||
// the key was not found, and it's not an optiona key
|
||||
snprintf(error, error_size, "missing '%s' key", k.name);
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < size; ++i)
|
||||
|
||||
if (k.size > 0
|
||||
&& ret[i]
|
||||
&& k.type == lazy_entry::string_t
|
||||
&& ret[i]->string_length() != k.size)
|
||||
{
|
||||
key_desc_t const& k = desc[i];
|
||||
ret[i] = msg->dict_find(k.name);
|
||||
if (ret[i] && ret[i]->type() != k.type) ret[i] = 0;
|
||||
if (ret[i] == 0 && (k.flags & key_desc_t::optional) == 0)
|
||||
// the string was not of the required size
|
||||
ret[i] = 0;
|
||||
if ((k.flags & key_desc_t::optional) == 0)
|
||||
{
|
||||
// the key was not found, and it's not an optiona key
|
||||
snprintf(error, error_size, "missing '%s' key", k.name);
|
||||
snprintf(error, error_size, "invalid value for '%s'", k.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (k.size > 0
|
||||
&& ret[i]
|
||||
&& k.type == lazy_entry::string_t
|
||||
&& ret[i]->string_length() != k.size)
|
||||
{
|
||||
// the string was not of the required size
|
||||
ret[i] = 0;
|
||||
if ((k.flags & key_desc_t::optional) == 0)
|
||||
{
|
||||
snprintf(error, error_size, "invalid value for '%s'", k.name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void incoming_error(entry& e, char const* msg)
|
||||
|
|
|
@ -31,14 +31,44 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/kademlia/node.hpp" // for verify_message
|
||||
#include "libtorrent/bencode.hpp"
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
using namespace libtorrent;
|
||||
|
||||
int dht_port = 48199;
|
||||
|
||||
void send_dht_msg(datagram_socket& sock, char const* msg, lazy_entry* reply, char const* t = "10")
|
||||
{
|
||||
entry e;
|
||||
e["q"] = msg;
|
||||
e["t"] = t;
|
||||
e["y"] = "q";
|
||||
entry::dictionary_type& a = e["a"].dict();
|
||||
a["id"] = "00000000000000000000";
|
||||
char msg_buf[1500];
|
||||
int size = bencode(msg_buf, e);
|
||||
|
||||
error_code ec;
|
||||
sock.send_to(asio::buffer(msg_buf, size)
|
||||
, udp::endpoint(address::from_string("127.0.0.1"), dht_port), 0, ec);
|
||||
TEST_CHECK(!ec);
|
||||
if (ec) std::cout << ec.message() << std::endl;
|
||||
|
||||
static char inbuf[1500];
|
||||
udp::endpoint ep;
|
||||
size = sock.receive_from(asio::buffer(inbuf, sizeof(inbuf)), ep, 0, ec);
|
||||
TEST_CHECK(!ec);
|
||||
if (ec) std::cout << ec.message() << std::endl;
|
||||
|
||||
int ret = lazy_bdecode(inbuf, inbuf + size, *reply);
|
||||
TEST_CHECK(ret == 0);
|
||||
}
|
||||
|
||||
int test_main()
|
||||
{
|
||||
using namespace libtorrent;
|
||||
|
||||
int dht_port = 48199;
|
||||
session ses(fingerprint("LT", 0, 1, 0, 0), std::make_pair(dht_port, 49000));
|
||||
|
||||
// DHT should be running on port 48199 now
|
||||
|
@ -51,37 +81,54 @@ int test_main()
|
|||
TEST_CHECK(!ec);
|
||||
if (ec) std::cout << ec.message() << std::endl;
|
||||
|
||||
char const ping_msg[] = "d1:ad2:id20:00000000000000000001e1:q4:ping1:t2:101:y1:qe";
|
||||
lazy_entry response;
|
||||
lazy_entry const* parsed[5];
|
||||
char error_string[200];
|
||||
bool ret;
|
||||
|
||||
// ping
|
||||
sock.send_to(asio::buffer(ping_msg, sizeof(ping_msg) - 1)
|
||||
, udp::endpoint(address::from_string("127.0.0.1"), dht_port), 0, ec);
|
||||
TEST_CHECK(!ec);
|
||||
if (ec) std::cout << ec.message() << std::endl;
|
||||
// ====== ping ======
|
||||
|
||||
char inbuf[1600];
|
||||
udp::endpoint ep;
|
||||
int size = sock.receive_from(asio::buffer(inbuf, sizeof(inbuf)), ep, 0, ec);
|
||||
TEST_CHECK(!ec);
|
||||
if (ec) std::cout << ec.message() << std::endl;
|
||||
send_dht_msg(sock, "ping", &response, "10");
|
||||
|
||||
lazy_entry pong;
|
||||
int ret = lazy_bdecode(inbuf, inbuf + size, pong);
|
||||
TEST_CHECK(ret == 0);
|
||||
dht::key_desc_t pong_desc[] = {
|
||||
{"y", lazy_entry::string_t, 1, 0},
|
||||
{"t", lazy_entry::string_t, 2, 0},
|
||||
};
|
||||
|
||||
if (ret != 0) return 1;
|
||||
ret = dht::verify_message(&response, pong_desc, parsed, 2, 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.type() == lazy_entry::dict_t);
|
||||
// ====== invalid message ======
|
||||
|
||||
if (pong.type() != lazy_entry::dict_t) return 1;
|
||||
send_dht_msg(sock, "find_node", &response, "10");
|
||||
|
||||
lazy_entry const* t = pong.dict_find_string("t");
|
||||
TEST_CHECK(t);
|
||||
if (t) TEST_CHECK(t->string_value() == "10");
|
||||
dht::key_desc_t err_desc[] = {
|
||||
{"y", lazy_entry::string_t, 1, 0},
|
||||
{"e", lazy_entry::list_t, 0, 0},
|
||||
};
|
||||
|
||||
lazy_entry const* y = pong.dict_find_string("y");
|
||||
TEST_CHECK(y);
|
||||
if (y) TEST_CHECK(y->string_value() == "r");
|
||||
ret = dht::verify_message(&response, err_desc, parsed, 2, error_string, sizeof(error_string));
|
||||
TEST_CHECK(ret);
|
||||
if (ret)
|
||||
{
|
||||
TEST_CHECK(parsed[0]->string_value() == "e");
|
||||
TEST_CHECK(parsed[1]->list_size() >= 2);
|
||||
if (parsed[1]->list_size() >= 2
|
||||
&& parsed[1]->list_at(0)->type() == lazy_entry::int_t
|
||||
&& parsed[1]->list_at(1)->type() == lazy_entry::string_t)
|
||||
{
|
||||
TEST_CHECK(parsed[1]->list_at(1)->string_value() == "missing 'target' key");
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_ERROR("invalid error response");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue