Initial commit: tracker and DHT protocol library
This commit is contained in:
commit
4732ca67ee
13 changed files with 4166 additions and 0 deletions
667
tests/test_tracker.c
Normal file
667
tests/test_tracker.c
Normal file
|
|
@ -0,0 +1,667 @@
|
|||
#include "tracker.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static void put32(uint8_t *p, uint32_t v)
|
||||
{
|
||||
p[0] = (uint8_t)(v >> 24);
|
||||
p[1] = (uint8_t)(v >> 16);
|
||||
p[2] = (uint8_t)(v >> 8);
|
||||
p[3] = (uint8_t)v;
|
||||
}
|
||||
|
||||
static void put64(uint8_t *p, uint64_t v)
|
||||
{
|
||||
put32(p, (uint32_t)(v >> 32));
|
||||
put32(p + 4, (uint32_t)v);
|
||||
}
|
||||
|
||||
static uint32_t get32(const uint8_t *p)
|
||||
{
|
||||
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |
|
||||
((uint32_t)p[2] << 8) | p[3];
|
||||
}
|
||||
|
||||
static void fill_announce(tracker_announce_request *req, const char *hash,
|
||||
const char *peer_id, uint16_t port, uint64_t left,
|
||||
tracker_event event)
|
||||
{
|
||||
memset(req, 0, sizeof(*req));
|
||||
memcpy(req->info_hash, hash, 20);
|
||||
memcpy(req->peer_id, peer_id, 20);
|
||||
req->port = port;
|
||||
req->left = left;
|
||||
req->numwant = -1;
|
||||
req->event = event;
|
||||
req->compact = 1;
|
||||
req->has_key = 1;
|
||||
req->key = (uint32_t)port;
|
||||
}
|
||||
|
||||
static tracker_peer ipv4_source(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
|
||||
{
|
||||
tracker_peer peer;
|
||||
memset(&peer, 0, sizeof(peer));
|
||||
peer.family = TRACKER_ADDR_IPV4;
|
||||
peer.addr[0] = a;
|
||||
peer.addr[1] = b;
|
||||
peer.addr[2] = c;
|
||||
peer.addr[3] = d;
|
||||
return peer;
|
||||
}
|
||||
|
||||
static void test_dht_queries(void)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
size_t written = 0;
|
||||
dht_message msg;
|
||||
uint8_t tx[] = {'a', 'a'};
|
||||
uint8_t id[20] = "abcdefghij0123456789";
|
||||
uint8_t target[20] = "mnopqrstuvwxyz123456";
|
||||
uint8_t token[] = "tok";
|
||||
|
||||
assert(dht_write_ping_query(tx, sizeof(tx), id, buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(dht_parse_message(buf, written, &msg) == TRACKER_OK);
|
||||
assert(msg.type == DHT_MSG_QUERY);
|
||||
assert(msg.query == DHT_QUERY_PING);
|
||||
assert(msg.transaction_len == 2);
|
||||
assert(memcmp(msg.transaction, tx, 2) == 0);
|
||||
assert(memcmp(msg.id, id, 20) == 0);
|
||||
|
||||
assert(dht_write_find_node_query(tx, sizeof(tx), id, target, 1, 1,
|
||||
buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(dht_parse_message(buf, written, &msg) == TRACKER_OK);
|
||||
assert(msg.query == DHT_QUERY_FIND_NODE);
|
||||
assert(memcmp(msg.target, target, 20) == 0);
|
||||
assert(msg.want_ipv4 == 1);
|
||||
assert(msg.want_ipv6 == 1);
|
||||
|
||||
assert(dht_write_get_peers_query(tx, sizeof(tx), id, target, 0, 1,
|
||||
buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(dht_parse_message(buf, written, &msg) == TRACKER_OK);
|
||||
assert(msg.query == DHT_QUERY_GET_PEERS);
|
||||
assert(memcmp(msg.info_hash, target, 20) == 0);
|
||||
assert(msg.want_ipv4 == 0);
|
||||
assert(msg.want_ipv6 == 1);
|
||||
|
||||
assert(dht_write_announce_peer_query(tx, sizeof(tx), id, target, 6881,
|
||||
token, sizeof(token) - 1, 1,
|
||||
buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(dht_parse_message(buf, written, &msg) == TRACKER_OK);
|
||||
assert(msg.query == DHT_QUERY_ANNOUNCE_PEER);
|
||||
assert(memcmp(msg.info_hash, target, 20) == 0);
|
||||
assert(msg.port == 6881);
|
||||
assert(msg.implied_port == 1);
|
||||
assert(msg.token_len == sizeof(token) - 1);
|
||||
assert(memcmp(msg.token, token, sizeof(token) - 1) == 0);
|
||||
}
|
||||
|
||||
static void test_dht_responses(void)
|
||||
{
|
||||
uint8_t buf[1024];
|
||||
size_t written = 0;
|
||||
dht_message msg;
|
||||
uint8_t tx[] = {'b', 'b'};
|
||||
uint8_t id[20] = "abcdefghij0123456789";
|
||||
uint8_t node_id[20] = "mnopqrstuvwxyz123456";
|
||||
uint8_t token[] = "aoeusnth";
|
||||
dht_node nodes[2];
|
||||
tracker_peer peers[2];
|
||||
|
||||
assert(dht_write_ping_response(tx, sizeof(tx), id, buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(dht_parse_message(buf, written, &msg) == TRACKER_OK);
|
||||
assert(msg.type == DHT_MSG_RESPONSE);
|
||||
assert(memcmp(msg.id, id, 20) == 0);
|
||||
|
||||
memset(nodes, 0, sizeof(nodes));
|
||||
memcpy(nodes[0].id, node_id, 20);
|
||||
nodes[0].family = TRACKER_ADDR_IPV4;
|
||||
nodes[0].addr[0] = 1;
|
||||
nodes[0].addr[1] = 2;
|
||||
nodes[0].addr[2] = 3;
|
||||
nodes[0].addr[3] = 4;
|
||||
nodes[0].port = 6881;
|
||||
memcpy(nodes[1].id, id, 20);
|
||||
nodes[1].family = TRACKER_ADDR_IPV6;
|
||||
nodes[1].addr[15] = 1;
|
||||
nodes[1].port = 6882;
|
||||
assert(dht_write_nodes_response(tx, sizeof(tx), id, token,
|
||||
sizeof(token) - 1, nodes, 2,
|
||||
buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(dht_parse_message(buf, written, &msg) == TRACKER_OK);
|
||||
assert(msg.type == DHT_MSG_RESPONSE);
|
||||
assert(msg.node_count == 2);
|
||||
assert(msg.nodes[0].family == TRACKER_ADDR_IPV4);
|
||||
assert(msg.nodes[0].port == 6881);
|
||||
assert(msg.nodes[1].family == TRACKER_ADDR_IPV6);
|
||||
assert(msg.nodes[1].port == 6882);
|
||||
assert(msg.token_len == sizeof(token) - 1);
|
||||
assert(memcmp(msg.token, token, sizeof(token) - 1) == 0);
|
||||
|
||||
memset(peers, 0, sizeof(peers));
|
||||
peers[0].family = TRACKER_ADDR_IPV4;
|
||||
peers[0].addr[0] = 8;
|
||||
peers[0].addr[1] = 8;
|
||||
peers[0].addr[2] = 8;
|
||||
peers[0].addr[3] = 8;
|
||||
peers[0].port = 51413;
|
||||
peers[1].family = TRACKER_ADDR_IPV6;
|
||||
peers[1].addr[15] = 2;
|
||||
peers[1].port = 51414;
|
||||
assert(dht_write_peers_response(tx, sizeof(tx), id, token,
|
||||
sizeof(token) - 1, peers, 2,
|
||||
buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(dht_parse_message(buf, written, &msg) == TRACKER_OK);
|
||||
assert(msg.peer_count == 2);
|
||||
assert(msg.peers[0].family == TRACKER_ADDR_IPV4);
|
||||
assert(msg.peers[0].port == 51413);
|
||||
assert(msg.peers[1].family == TRACKER_ADDR_IPV6);
|
||||
assert(msg.peers[1].port == 51414);
|
||||
}
|
||||
|
||||
static void test_dht_error(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
size_t written = 0;
|
||||
dht_message msg;
|
||||
uint8_t tx[] = {'e', 'r'};
|
||||
assert(dht_write_error(tx, sizeof(tx), DHT_ERR_PROTOCOL, "bad token",
|
||||
buf, sizeof(buf), &written) == TRACKER_OK);
|
||||
assert(dht_parse_message(buf, written, &msg) == TRACKER_OK);
|
||||
assert(msg.type == DHT_MSG_ERROR);
|
||||
assert(msg.error_code == DHT_ERR_PROTOCOL);
|
||||
assert(strcmp(msg.error_message, "bad token") == 0);
|
||||
}
|
||||
|
||||
static void test_http_announce_parse(void)
|
||||
{
|
||||
tracker_announce_request req;
|
||||
const char *q =
|
||||
"/announce?info_hash=%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13"
|
||||
"&peer_id=-TT0001-abcdefghijkl"
|
||||
"&port=6881&uploaded=10&downloaded=20&left=30&compact=1"
|
||||
"&event=started&numwant=50&key=12345&trackerid=session";
|
||||
int rc = tracker_http_parse_announce_query(q, &req);
|
||||
assert(rc == TRACKER_OK);
|
||||
assert(req.info_hash[0] == 0);
|
||||
assert(req.info_hash[19] == 0x13);
|
||||
assert(memcmp(req.peer_id, "-TT0001-abcdefghijkl", 20) == 0);
|
||||
assert(req.port == 6881);
|
||||
assert(req.uploaded == 10);
|
||||
assert(req.downloaded == 20);
|
||||
assert(req.left == 30);
|
||||
assert(req.compact == 1);
|
||||
assert(req.event == TRACKER_EVENT_STARTED);
|
||||
assert(req.numwant == 50);
|
||||
assert(req.has_key == 1 && req.key == 12345);
|
||||
assert(strcmp(req.tracker_id, "session") == 0);
|
||||
|
||||
assert(tracker_http_parse_announce_query(
|
||||
"/announce?info_hash=++++++++++++++++++++"
|
||||
"&peer_id=--------------------&port=1&uploaded=0"
|
||||
"&downloaded=0&left=0",
|
||||
&req) == TRACKER_OK);
|
||||
assert(req.info_hash[0] == '+');
|
||||
assert(req.info_hash[19] == '+');
|
||||
}
|
||||
|
||||
static void test_http_compact_response(void)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
size_t written = 0;
|
||||
tracker_peer peers[2];
|
||||
tracker_announce_response resp;
|
||||
|
||||
memset(peers, 0, sizeof(peers));
|
||||
peers[0].family = TRACKER_ADDR_IPV4;
|
||||
peers[0].addr[0] = 127;
|
||||
peers[0].addr[1] = 0;
|
||||
peers[0].addr[2] = 0;
|
||||
peers[0].addr[3] = 1;
|
||||
peers[0].port = 6881;
|
||||
peers[1].family = TRACKER_ADDR_IPV6;
|
||||
peers[1].addr[15] = 1;
|
||||
peers[1].port = 51413;
|
||||
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
resp.interval = 1800;
|
||||
resp.complete = 7;
|
||||
resp.incomplete = 3;
|
||||
resp.peers = peers;
|
||||
resp.peer_count = 2;
|
||||
resp.compact = 1;
|
||||
|
||||
assert(tracker_http_write_announce_response(&resp, buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(written > 0);
|
||||
assert(memmem(buf, written, "5:peers6:", 9) != NULL);
|
||||
assert(memmem(buf, written, "6:peers618:", 10) != NULL);
|
||||
}
|
||||
|
||||
static void test_http_scrape(void)
|
||||
{
|
||||
uint8_t hashes[2][20];
|
||||
size_t count = 0;
|
||||
tracker_scrape_file files[1];
|
||||
tracker_scrape_response resp;
|
||||
uint8_t buf[256];
|
||||
size_t written = 0;
|
||||
int rc = tracker_http_parse_scrape_query(
|
||||
"/scrape?info_hash=aaaaaaaaaaaaaaaaaaaa&info_hash=bbbbbbbbbbbbbbbbbbbb",
|
||||
hashes, 2, &count);
|
||||
assert(rc == TRACKER_OK);
|
||||
assert(count == 2);
|
||||
assert(memcmp(hashes[0], "aaaaaaaaaaaaaaaaaaaa", 20) == 0);
|
||||
assert(memcmp(hashes[1], "bbbbbbbbbbbbbbbbbbbb", 20) == 0);
|
||||
|
||||
memset(files, 0, sizeof(files));
|
||||
memcpy(files[0].info_hash, hashes[0], 20);
|
||||
files[0].complete = 11;
|
||||
files[0].downloaded = 22;
|
||||
files[0].incomplete = 33;
|
||||
resp.files = files;
|
||||
resp.file_count = 1;
|
||||
assert(tracker_http_write_scrape_response(&resp, buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(memmem(buf, written, "5:filesd20:aaaaaaaaaaaaaaaaaaaa", 31) != NULL);
|
||||
assert(memmem(buf, written, "8:completei11e", 14) != NULL);
|
||||
}
|
||||
|
||||
static void test_http_client_helpers(void)
|
||||
{
|
||||
tracker_announce_request req;
|
||||
tracker_announce_request parsed;
|
||||
tracker_announce_response resp;
|
||||
tracker_announce_response parsed_resp;
|
||||
tracker_scrape_response scrape;
|
||||
tracker_scrape_response parsed_scrape;
|
||||
tracker_scrape_file files[1];
|
||||
tracker_scrape_file parsed_files[2];
|
||||
tracker_peer peers[2];
|
||||
tracker_peer parsed_peers[4];
|
||||
uint8_t buf[512];
|
||||
char query[512];
|
||||
size_t written = 0;
|
||||
uint8_t hashes[2][20];
|
||||
size_t hash_count = 0;
|
||||
|
||||
fill_announce(&req, "abcdefghijklmnopqrst", "-TC0001-abcdefghijkl", 6881,
|
||||
12345, TRACKER_EVENT_STARTED);
|
||||
req.uploaded = 10;
|
||||
req.downloaded = 20;
|
||||
req.numwant = 25;
|
||||
assert(tracker_http_write_announce_query(&req, query, sizeof(query),
|
||||
&written) == TRACKER_OK);
|
||||
assert(written > 0);
|
||||
assert(tracker_http_parse_announce_query(query, &parsed) == TRACKER_OK);
|
||||
assert(memcmp(parsed.info_hash, req.info_hash, 20) == 0);
|
||||
assert(memcmp(parsed.peer_id, req.peer_id, 20) == 0);
|
||||
assert(parsed.port == 6881);
|
||||
assert(parsed.left == 12345);
|
||||
assert(parsed.event == TRACKER_EVENT_STARTED);
|
||||
assert(parsed.numwant == 25);
|
||||
|
||||
memset(peers, 0, sizeof(peers));
|
||||
peers[0].family = TRACKER_ADDR_IPV4;
|
||||
peers[0].addr[0] = 1;
|
||||
peers[0].addr[1] = 2;
|
||||
peers[0].addr[2] = 3;
|
||||
peers[0].addr[3] = 4;
|
||||
peers[0].port = 6000;
|
||||
peers[1].family = TRACKER_ADDR_IPV6;
|
||||
peers[1].addr[15] = 1;
|
||||
peers[1].port = 6001;
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
resp.interval = 1800;
|
||||
resp.min_interval = 60;
|
||||
resp.complete = 3;
|
||||
resp.incomplete = 4;
|
||||
resp.peers = peers;
|
||||
resp.peer_count = 2;
|
||||
resp.compact = 1;
|
||||
assert(tracker_http_write_announce_response(&resp, buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(tracker_http_parse_announce_response(buf, written, parsed_peers, 4,
|
||||
&parsed_resp) == TRACKER_OK);
|
||||
assert(parsed_resp.interval == 1800);
|
||||
assert(parsed_resp.min_interval == 60);
|
||||
assert(parsed_resp.complete == 3);
|
||||
assert(parsed_resp.incomplete == 4);
|
||||
assert(parsed_resp.peer_count == 2);
|
||||
assert(parsed_peers[0].family == TRACKER_ADDR_IPV4);
|
||||
assert(parsed_peers[0].port == 6000);
|
||||
assert(parsed_peers[1].family == TRACKER_ADDR_IPV6);
|
||||
assert(parsed_peers[1].port == 6001);
|
||||
|
||||
memcpy(hashes[0], "aaaaaaaaaaaaaaaaaaaa", 20);
|
||||
memcpy(hashes[1], "bbbbbbbbbbbbbbbbbbbb", 20);
|
||||
assert(tracker_http_write_scrape_query(hashes, 2, query, sizeof(query),
|
||||
&written) == TRACKER_OK);
|
||||
assert(tracker_http_parse_scrape_query(query, hashes, 2,
|
||||
&hash_count) == TRACKER_OK);
|
||||
assert(hash_count == 2);
|
||||
|
||||
memset(files, 0, sizeof(files));
|
||||
memcpy(files[0].info_hash, "aaaaaaaaaaaaaaaaaaaa", 20);
|
||||
files[0].complete = 9;
|
||||
files[0].downloaded = 8;
|
||||
files[0].incomplete = 7;
|
||||
scrape.files = files;
|
||||
scrape.file_count = 1;
|
||||
assert(tracker_http_write_scrape_response(&scrape, buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(tracker_http_parse_scrape_response(buf, written, parsed_files, 2,
|
||||
&parsed_scrape) == TRACKER_OK);
|
||||
assert(parsed_scrape.file_count == 1);
|
||||
assert(memcmp(parsed_files[0].info_hash, files[0].info_hash, 20) == 0);
|
||||
assert(parsed_files[0].complete == 9);
|
||||
assert(parsed_files[0].downloaded == 8);
|
||||
assert(parsed_files[0].incomplete == 7);
|
||||
}
|
||||
|
||||
static void test_udp_announce_parse(void)
|
||||
{
|
||||
uint8_t pkt[128];
|
||||
tracker_udp_request req;
|
||||
memset(pkt, 0, sizeof(pkt));
|
||||
put64(pkt, 0x0102030405060708ULL);
|
||||
put32(pkt + 8, TRACKER_UDP_ANNOUNCE);
|
||||
put32(pkt + 12, 0x11223344);
|
||||
memcpy(pkt + 16, "aaaaaaaaaaaaaaaaaaaa", 20);
|
||||
memcpy(pkt + 36, "bbbbbbbbbbbbbbbbbbbb", 20);
|
||||
put64(pkt + 56, 100);
|
||||
put64(pkt + 64, 200);
|
||||
put64(pkt + 72, 300);
|
||||
put32(pkt + 80, TRACKER_EVENT_COMPLETED);
|
||||
put32(pkt + 88, 0xaabbccdd);
|
||||
put32(pkt + 92, 25);
|
||||
pkt[96] = 0x1a;
|
||||
pkt[97] = 0xe1;
|
||||
pkt[98] = 0x02;
|
||||
pkt[99] = 12;
|
||||
memcpy(pkt + 100, "/dir?a=b&c=d", 12);
|
||||
pkt[112] = 0x00;
|
||||
|
||||
assert(tracker_udp_parse_request(pkt, 113, TRACKER_ADDR_IPV4,
|
||||
&req) == TRACKER_OK);
|
||||
assert(req.action == TRACKER_UDP_ANNOUNCE);
|
||||
assert(req.transaction_id == 0x11223344);
|
||||
assert(req.connection_id == 0x0102030405060708ULL);
|
||||
assert(memcmp(req.announce.info_hash, "aaaaaaaaaaaaaaaaaaaa", 20) == 0);
|
||||
assert(memcmp(req.announce.peer_id, "bbbbbbbbbbbbbbbbbbbb", 20) == 0);
|
||||
assert(req.announce.downloaded == 100);
|
||||
assert(req.announce.left == 200);
|
||||
assert(req.announce.uploaded == 300);
|
||||
assert(req.announce.event == TRACKER_EVENT_COMPLETED);
|
||||
assert(req.announce.key == 0xaabbccdd);
|
||||
assert(req.announce.numwant == 25);
|
||||
assert(req.announce.port == 6881);
|
||||
assert(strcmp(req.announce.url_data, "/dir?a=b&c=d") == 0);
|
||||
}
|
||||
|
||||
static void test_udp_responses(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
size_t written = 0;
|
||||
tracker_peer peer;
|
||||
tracker_announce_response announce;
|
||||
tracker_scrape_file file;
|
||||
tracker_scrape_response scrape;
|
||||
|
||||
assert(tracker_udp_write_connect_response(0x1234, 0x0102030405060708ULL,
|
||||
buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(written == 16);
|
||||
assert(get32(buf) == TRACKER_UDP_CONNECT);
|
||||
assert(get32(buf + 4) == 0x1234);
|
||||
|
||||
memset(&peer, 0, sizeof(peer));
|
||||
peer.family = TRACKER_ADDR_IPV4;
|
||||
peer.addr[0] = 10;
|
||||
peer.addr[3] = 5;
|
||||
peer.port = 6000;
|
||||
memset(&announce, 0, sizeof(announce));
|
||||
announce.interval = 900;
|
||||
announce.complete = 2;
|
||||
announce.incomplete = 4;
|
||||
announce.peers = &peer;
|
||||
announce.peer_count = 1;
|
||||
assert(tracker_udp_write_announce_response(0x99, TRACKER_ADDR_IPV4,
|
||||
&announce, buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(written == 26);
|
||||
assert(get32(buf) == TRACKER_UDP_ANNOUNCE);
|
||||
assert(get32(buf + 8) == 900);
|
||||
assert(get32(buf + 12) == 4);
|
||||
assert(get32(buf + 16) == 2);
|
||||
assert(buf[20] == 10 && buf[23] == 5);
|
||||
|
||||
memset(&file, 0, sizeof(file));
|
||||
file.complete = 8;
|
||||
file.downloaded = 9;
|
||||
file.incomplete = 10;
|
||||
scrape.files = &file;
|
||||
scrape.file_count = 1;
|
||||
assert(tracker_udp_write_scrape_response(0x77, &scrape, buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(written == 20);
|
||||
assert(get32(buf) == TRACKER_UDP_SCRAPE);
|
||||
assert(get32(buf + 8) == 8);
|
||||
assert(get32(buf + 12) == 9);
|
||||
assert(get32(buf + 16) == 10);
|
||||
}
|
||||
|
||||
static void test_udp_client_helpers(void)
|
||||
{
|
||||
uint8_t buf[512];
|
||||
uint8_t response_buf[512];
|
||||
size_t written = 0;
|
||||
size_t response_written = 0;
|
||||
tracker_udp_request parsed_req;
|
||||
tracker_announce_request req;
|
||||
tracker_announce_response resp;
|
||||
tracker_announce_response parsed_resp;
|
||||
tracker_scrape_response scrape;
|
||||
tracker_scrape_response parsed_scrape;
|
||||
tracker_scrape_file file;
|
||||
tracker_scrape_file parsed_files[2];
|
||||
tracker_peer peer;
|
||||
tracker_peer parsed_peers[2];
|
||||
uint8_t hashes[1][20];
|
||||
uint64_t connection_id = 0;
|
||||
|
||||
assert(tracker_udp_write_connect_request(0x5555, buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(tracker_udp_parse_request(buf, written, TRACKER_ADDR_IPV4,
|
||||
&parsed_req) == TRACKER_OK);
|
||||
assert(parsed_req.action == TRACKER_UDP_CONNECT);
|
||||
assert(parsed_req.transaction_id == 0x5555);
|
||||
assert(tracker_udp_write_connect_response(0x5555, 0x0102030405060708ULL,
|
||||
response_buf, sizeof(response_buf),
|
||||
&response_written) == TRACKER_OK);
|
||||
assert(tracker_udp_parse_connect_response(response_buf, response_written,
|
||||
0x5555,
|
||||
&connection_id) == TRACKER_OK);
|
||||
assert(connection_id == 0x0102030405060708ULL);
|
||||
|
||||
fill_announce(&req, "abcdefghijklmnopqrst", "-UC0001-abcdefghijkl", 7000,
|
||||
42, TRACKER_EVENT_STARTED);
|
||||
req.downloaded = 5;
|
||||
req.uploaded = 6;
|
||||
req.numwant = 10;
|
||||
strcpy(req.url_data, "/announce?token=abc");
|
||||
assert(tracker_udp_write_announce_request(connection_id, 0x6666, &req,
|
||||
buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(tracker_udp_parse_request(buf, written, TRACKER_ADDR_IPV4,
|
||||
&parsed_req) == TRACKER_OK);
|
||||
assert(parsed_req.action == TRACKER_UDP_ANNOUNCE);
|
||||
assert(parsed_req.transaction_id == 0x6666);
|
||||
assert(parsed_req.connection_id == connection_id);
|
||||
assert(parsed_req.announce.port == 7000);
|
||||
assert(parsed_req.announce.left == 42);
|
||||
assert(strcmp(parsed_req.announce.url_data, "/announce?token=abc") == 0);
|
||||
|
||||
memset(&peer, 0, sizeof(peer));
|
||||
peer.family = TRACKER_ADDR_IPV4;
|
||||
peer.addr[0] = 8;
|
||||
peer.addr[1] = 8;
|
||||
peer.addr[2] = 4;
|
||||
peer.addr[3] = 4;
|
||||
peer.port = 51413;
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
resp.interval = 900;
|
||||
resp.complete = 11;
|
||||
resp.incomplete = 12;
|
||||
resp.peers = &peer;
|
||||
resp.peer_count = 1;
|
||||
assert(tracker_udp_write_announce_response(0x6666, TRACKER_ADDR_IPV4,
|
||||
&resp, response_buf,
|
||||
sizeof(response_buf),
|
||||
&response_written) == TRACKER_OK);
|
||||
assert(tracker_udp_parse_announce_response(response_buf, response_written,
|
||||
0x6666, TRACKER_ADDR_IPV4,
|
||||
parsed_peers, 2,
|
||||
&parsed_resp) == TRACKER_OK);
|
||||
assert(parsed_resp.interval == 900);
|
||||
assert(parsed_resp.complete == 11);
|
||||
assert(parsed_resp.incomplete == 12);
|
||||
assert(parsed_resp.peer_count == 1);
|
||||
assert(parsed_peers[0].addr[0] == 8);
|
||||
assert(parsed_peers[0].port == 51413);
|
||||
|
||||
memcpy(hashes[0], "aaaaaaaaaaaaaaaaaaaa", 20);
|
||||
assert(tracker_udp_write_scrape_request(connection_id, 0x7777, hashes, 1,
|
||||
buf, sizeof(buf),
|
||||
&written) == TRACKER_OK);
|
||||
assert(tracker_udp_parse_request(buf, written, TRACKER_ADDR_IPV4,
|
||||
&parsed_req) == TRACKER_OK);
|
||||
assert(parsed_req.action == TRACKER_UDP_SCRAPE);
|
||||
assert(parsed_req.scrape_count == 1);
|
||||
assert(memcmp(parsed_req.scrape_hashes[0], hashes[0], 20) == 0);
|
||||
|
||||
memset(&file, 0, sizeof(file));
|
||||
file.complete = 1;
|
||||
file.downloaded = 2;
|
||||
file.incomplete = 3;
|
||||
scrape.files = &file;
|
||||
scrape.file_count = 1;
|
||||
assert(tracker_udp_write_scrape_response(0x7777, &scrape, response_buf,
|
||||
sizeof(response_buf),
|
||||
&response_written) == TRACKER_OK);
|
||||
assert(tracker_udp_parse_scrape_response(response_buf, response_written,
|
||||
0x7777, parsed_files, 2,
|
||||
&parsed_scrape) == TRACKER_OK);
|
||||
assert(parsed_scrape.file_count == 1);
|
||||
assert(parsed_files[0].complete == 1);
|
||||
assert(parsed_files[0].downloaded == 2);
|
||||
assert(parsed_files[0].incomplete == 3);
|
||||
}
|
||||
|
||||
static void test_store_announce_scrape_stop_and_prune(void)
|
||||
{
|
||||
tracker_store_config cfg;
|
||||
tracker_store *store;
|
||||
tracker_announce_request req1;
|
||||
tracker_announce_request req2;
|
||||
tracker_announce_response resp;
|
||||
tracker_scrape_response scrape;
|
||||
tracker_scrape_file files[1];
|
||||
tracker_peer source1 = ipv4_source(10, 0, 0, 1);
|
||||
tracker_peer source2 = ipv4_source(10, 0, 0, 2);
|
||||
tracker_peer out[8];
|
||||
uint8_t hashes[1][20];
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.interval = 1200;
|
||||
cfg.min_interval = 60;
|
||||
cfg.peer_timeout = 10;
|
||||
cfg.default_numwant = 50;
|
||||
cfg.max_numwant = 50;
|
||||
cfg.random_seed = 1;
|
||||
store = tracker_store_create(&cfg);
|
||||
assert(store != NULL);
|
||||
|
||||
fill_announce(&req1, "aaaaaaaaaaaaaaaaaaaa", "peer-000000000000001", 6001,
|
||||
100, TRACKER_EVENT_STARTED);
|
||||
assert(tracker_store_announce(store, &req1, &source1, 100, out, 8,
|
||||
&resp) == TRACKER_OK);
|
||||
assert(resp.interval == 1200);
|
||||
assert(resp.min_interval == 60);
|
||||
assert(resp.complete == 0);
|
||||
assert(resp.incomplete == 1);
|
||||
assert(resp.peer_count == 0);
|
||||
assert(tracker_store_peer_count(store) == 1);
|
||||
|
||||
fill_announce(&req2, "aaaaaaaaaaaaaaaaaaaa", "peer-000000000000002", 6002,
|
||||
0, TRACKER_EVENT_STARTED);
|
||||
assert(tracker_store_announce(store, &req2, &source2, 101, out, 8,
|
||||
&resp) == TRACKER_OK);
|
||||
assert(resp.complete == 1);
|
||||
assert(resp.incomplete == 1);
|
||||
assert(resp.peer_count == 1);
|
||||
assert(out[0].port == 6001);
|
||||
assert(out[0].addr[3] == 1);
|
||||
|
||||
req1.left = 0;
|
||||
req1.event = TRACKER_EVENT_COMPLETED;
|
||||
assert(tracker_store_announce(store, &req1, &source1, 102, out, 8,
|
||||
&resp) == TRACKER_OK);
|
||||
assert(resp.complete == 2);
|
||||
assert(resp.incomplete == 0);
|
||||
assert(resp.peer_count == 1);
|
||||
assert(out[0].port == 6002);
|
||||
|
||||
memcpy(hashes[0], "aaaaaaaaaaaaaaaaaaaa", 20);
|
||||
assert(tracker_store_scrape(store, hashes, 1, files, 1,
|
||||
&scrape) == TRACKER_OK);
|
||||
assert(scrape.file_count == 1);
|
||||
assert(files[0].complete == 2);
|
||||
assert(files[0].incomplete == 0);
|
||||
assert(files[0].downloaded == 1);
|
||||
|
||||
req2.event = TRACKER_EVENT_STOPPED;
|
||||
assert(tracker_store_announce(store, &req2, &source2, 103, out, 8,
|
||||
&resp) == TRACKER_OK);
|
||||
assert(resp.complete == 1);
|
||||
assert(resp.incomplete == 0);
|
||||
assert(resp.peer_count == 0);
|
||||
assert(tracker_store_peer_count(store) == 1);
|
||||
|
||||
assert(tracker_store_prune(store, 200) == 1);
|
||||
assert(tracker_store_peer_count(store) == 0);
|
||||
assert(tracker_store_scrape(store, hashes, 1, files, 1,
|
||||
&scrape) == TRACKER_OK);
|
||||
assert(files[0].complete == 0);
|
||||
assert(files[0].incomplete == 0);
|
||||
assert(files[0].downloaded == 1);
|
||||
|
||||
tracker_store_destroy(store);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_http_announce_parse();
|
||||
test_http_compact_response();
|
||||
test_http_scrape();
|
||||
test_http_client_helpers();
|
||||
test_dht_queries();
|
||||
test_dht_responses();
|
||||
test_dht_error();
|
||||
test_udp_announce_parse();
|
||||
test_udp_responses();
|
||||
test_udp_client_helpers();
|
||||
test_store_announce_scrape_stop_and_prune();
|
||||
puts("tracker protocol tests passed");
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue