Import dht-0.16.
This commit is contained in:
parent
abcd56c034
commit
3d25f2dc7e
|
@ -1,3 +1,7 @@
|
||||||
|
23 December 2010: dht-0.16:
|
||||||
|
|
||||||
|
* Change the interface to allow sharing of the UDP socket e.g. with uTP.
|
||||||
|
|
||||||
1 July 2010: dht-0.15
|
1 July 2010: dht-0.15
|
||||||
|
|
||||||
* Port to Windows, for the needs of Transmission.
|
* Port to Windows, for the needs of Transmission.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2009 by Juliusz Chroboczek
|
Copyright (c) 2009, 2010 by Juliusz Chroboczek
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -86,9 +86,8 @@ dht_periodic should be called if no data is available is returned in the
|
||||||
parameter tosleep. (You do not need to be particularly accurate; actually,
|
parameter tosleep. (You do not need to be particularly accurate; actually,
|
||||||
it is a good idea to be late by a random value.)
|
it is a good idea to be late by a random value.)
|
||||||
|
|
||||||
The parameter available indicates whether any data is available on the
|
The parameters buf, buflen, from and fromlen optionally carry a received
|
||||||
socket. If it is 0, dht_periodic will not try to read data; if it is 1, it
|
message. If buflen is 0, then no message was received.
|
||||||
will.
|
|
||||||
|
|
||||||
Dht_periodic also takes a callback, which will be called whenever something
|
Dht_periodic also takes a callback, which will be called whenever something
|
||||||
interesting happens (see below).
|
interesting happens (see below).
|
||||||
|
|
|
@ -88,6 +88,8 @@ callback(void *closure,
|
||||||
printf("Received %d values.\n", (int)(data_len / 6));
|
printf("Received %d values.\n", (int)(data_len / 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned char buf[4096];
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -101,6 +103,8 @@ main(int argc, char **argv)
|
||||||
int quiet = 0, ipv4 = 1, ipv6 = 1;
|
int quiet = 0, ipv4 = 1, ipv6 = 1;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
struct sockaddr_in6 sin6;
|
struct sockaddr_in6 sin6;
|
||||||
|
struct sockaddr_storage from;
|
||||||
|
socklen_t fromlen;
|
||||||
|
|
||||||
memset(&sin, 0, sizeof(sin));
|
memset(&sin, 0, sizeof(sin));
|
||||||
sin.sin_family = AF_INET;
|
sin.sin_family = AF_INET;
|
||||||
|
@ -338,7 +342,25 @@ main(int argc, char **argv)
|
||||||
if(exiting)
|
if(exiting)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
rc = dht_periodic(rc > 0, &tosleep, callback, NULL);
|
if(rc > 0) {
|
||||||
|
fromlen = sizeof(from);
|
||||||
|
if(s >= 0 && FD_ISSET(s, &readfds))
|
||||||
|
rc = recvfrom(s, buf, sizeof(buf) - 1, 0,
|
||||||
|
(struct sockaddr*)&from, &fromlen);
|
||||||
|
else if(s6 >= 0 && FD_ISSET(s6, &readfds))
|
||||||
|
rc = recvfrom(s6, buf, sizeof(buf) - 1, 0,
|
||||||
|
(struct sockaddr*)&from, &fromlen);
|
||||||
|
else
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rc > 0) {
|
||||||
|
buf[rc] = '\0';
|
||||||
|
rc = dht_periodic(buf, rc, (struct sockaddr*)&from, fromlen,
|
||||||
|
&tosleep, callback, NULL);
|
||||||
|
} else {
|
||||||
|
rc = dht_periodic(NULL, 0, NULL, 0, &tosleep, callback, NULL);
|
||||||
|
}
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
if(errno == EINTR) {
|
if(errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2010 by Juliusz Chroboczek
|
Copyright (c) 2009, 2010 by Juliusz Chroboczek
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -66,7 +66,6 @@ THE SOFTWARE.
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
||||||
#define EAFNOSUPPORT WSAEAFNOSUPPORT
|
#define EAFNOSUPPORT WSAEAFNOSUPPORT
|
||||||
#define EAGAIN WSAEWOULDBLOCK
|
|
||||||
static int
|
static int
|
||||||
set_nonblocking(int fd, int nonblocking)
|
set_nonblocking(int fd, int nonblocking)
|
||||||
{
|
{
|
||||||
|
@ -213,34 +212,34 @@ struct storage {
|
||||||
struct storage *next;
|
struct storage *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int send_ping(struct sockaddr *sa, int salen,
|
static int send_ping(const struct sockaddr *sa, int salen,
|
||||||
const unsigned char *tid, int tid_len);
|
const unsigned char *tid, int tid_len);
|
||||||
static int send_pong(struct sockaddr *sa, int salen,
|
static int send_pong(const struct sockaddr *sa, int salen,
|
||||||
const unsigned char *tid, int tid_len);
|
const unsigned char *tid, int tid_len);
|
||||||
static int send_find_node(struct sockaddr *sa, int salen,
|
static int send_find_node(const struct sockaddr *sa, int salen,
|
||||||
const unsigned char *tid, int tid_len,
|
const unsigned char *tid, int tid_len,
|
||||||
const unsigned char *target, int want, int confirm);
|
const unsigned char *target, int want, int confirm);
|
||||||
static int send_nodes_peers(struct sockaddr *sa, int salen,
|
static int send_nodes_peers(const struct sockaddr *sa, int salen,
|
||||||
const unsigned char *tid, int tid_len,
|
const unsigned char *tid, int tid_len,
|
||||||
const unsigned char *nodes, int nodes_len,
|
const unsigned char *nodes, int nodes_len,
|
||||||
const unsigned char *nodes6, int nodes6_len,
|
const unsigned char *nodes6, int nodes6_len,
|
||||||
int af, struct storage *st,
|
int af, struct storage *st,
|
||||||
const unsigned char *token, int token_len);
|
const unsigned char *token, int token_len);
|
||||||
static int send_closest_nodes(struct sockaddr *sa, int salen,
|
static int send_closest_nodes(const struct sockaddr *sa, int salen,
|
||||||
const unsigned char *tid, int tid_len,
|
const unsigned char *tid, int tid_len,
|
||||||
const unsigned char *id, int want,
|
const unsigned char *id, int want,
|
||||||
int af, struct storage *st,
|
int af, struct storage *st,
|
||||||
const unsigned char *token, int token_len);
|
const unsigned char *token, int token_len);
|
||||||
static int send_get_peers(struct sockaddr *sa, int salen,
|
static int send_get_peers(const struct sockaddr *sa, int salen,
|
||||||
unsigned char *tid, int tid_len,
|
unsigned char *tid, int tid_len,
|
||||||
unsigned char *infohash, int want, int confirm);
|
unsigned char *infohash, int want, int confirm);
|
||||||
static int send_announce_peer(struct sockaddr *sa, int salen,
|
static int send_announce_peer(const struct sockaddr *sa, int salen,
|
||||||
unsigned char *tid, int tid_len,
|
unsigned char *tid, int tid_len,
|
||||||
unsigned char *infohas, unsigned short port,
|
unsigned char *infohas, unsigned short port,
|
||||||
unsigned char *token, int token_len, int confirm);
|
unsigned char *token, int token_len, int confirm);
|
||||||
static int send_peer_announced(struct sockaddr *sa, int salen,
|
static int send_peer_announced(const struct sockaddr *sa, int salen,
|
||||||
unsigned char *tid, int tid_len);
|
unsigned char *tid, int tid_len);
|
||||||
static int send_error(struct sockaddr *sa, int salen,
|
static int send_error(const struct sockaddr *sa, int salen,
|
||||||
unsigned char *tid, int tid_len,
|
unsigned char *tid, int tid_len,
|
||||||
int code, const char *message);
|
int code, const char *message);
|
||||||
|
|
||||||
|
@ -350,7 +349,7 @@ print_hex(FILE *f, const unsigned char *buf, int buflen)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
is_martian(struct sockaddr *sa)
|
is_martian(const struct sockaddr *sa)
|
||||||
{
|
{
|
||||||
switch(sa->sa_family) {
|
switch(sa->sa_family) {
|
||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
|
@ -688,7 +687,8 @@ pinged(struct node *n, struct bucket *b)
|
||||||
/* We just learnt about a node, not necessarily a new one. Confirm is 1 if
|
/* We just learnt about a node, not necessarily a new one. Confirm is 1 if
|
||||||
the node sent a message, 2 if it sent us a reply. */
|
the node sent a message, 2 if it sent us a reply. */
|
||||||
static struct node *
|
static struct node *
|
||||||
new_node(const unsigned char *id, struct sockaddr *sa, int salen, int confirm)
|
new_node(const unsigned char *id, const struct sockaddr *sa, int salen,
|
||||||
|
int confirm)
|
||||||
{
|
{
|
||||||
struct bucket *b = find_bucket(id, sa->sa_family);
|
struct bucket *b = find_bucket(id, sa->sa_family);
|
||||||
struct node *n;
|
struct node *n;
|
||||||
|
@ -790,7 +790,7 @@ new_node(const unsigned char *id, struct sockaddr *sa, int salen, int confirm)
|
||||||
|
|
||||||
if(split) {
|
if(split) {
|
||||||
debugf("Splitting.\n");
|
debugf("Splitting.\n");
|
||||||
split_bucket(b);
|
b = split_bucket(b);
|
||||||
return new_node(id, sa, salen, confirm);
|
return new_node(id, sa, salen, confirm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,7 +880,7 @@ find_search(unsigned short tid, int af)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
insert_search_node(unsigned char *id,
|
insert_search_node(unsigned char *id,
|
||||||
struct sockaddr *sa, int salen,
|
const struct sockaddr *sa, int salen,
|
||||||
struct search *sr, int replied,
|
struct search *sr, int replied,
|
||||||
unsigned char *token, int token_len)
|
unsigned char *token, int token_len)
|
||||||
{
|
{
|
||||||
|
@ -1221,7 +1221,7 @@ find_storage(const unsigned char *id)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
storage_store(const unsigned char *id, struct sockaddr *sa)
|
storage_store(const unsigned char *id, const struct sockaddr *sa)
|
||||||
{
|
{
|
||||||
int i, len;
|
int i, len;
|
||||||
struct storage *st;
|
struct storage *st;
|
||||||
|
@ -1332,7 +1332,7 @@ expire_storage(void)
|
||||||
|
|
||||||
/* We've just found out that a node is buggy. */
|
/* We've just found out that a node is buggy. */
|
||||||
static void
|
static void
|
||||||
broken_node(const unsigned char *id, struct sockaddr *sa, int salen)
|
broken_node(const unsigned char *id, const struct sockaddr *sa, int salen)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -1382,7 +1382,7 @@ rotate_secrets(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
make_token(struct sockaddr *sa, int old, unsigned char *token_return)
|
make_token(const struct sockaddr *sa, int old, unsigned char *token_return)
|
||||||
{
|
{
|
||||||
void *ip;
|
void *ip;
|
||||||
int iplen;
|
int iplen;
|
||||||
|
@ -1407,7 +1407,8 @@ make_token(struct sockaddr *sa, int old, unsigned char *token_return)
|
||||||
ip, iplen, (unsigned char*)&port, 2);
|
ip, iplen, (unsigned char*)&port, 2);
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
token_match(unsigned char *token, int token_len, struct sockaddr *sa)
|
token_match(const unsigned char *token, int token_len,
|
||||||
|
const struct sockaddr *sa)
|
||||||
{
|
{
|
||||||
unsigned char t[TOKEN_SIZE];
|
unsigned char t[TOKEN_SIZE];
|
||||||
if(token_len != TOKEN_SIZE)
|
if(token_len != TOKEN_SIZE)
|
||||||
|
@ -1831,68 +1832,46 @@ bucket_maintenance(int af)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dht_periodic(int available, time_t *tosleep,
|
dht_periodic(const void *buf, size_t buflen,
|
||||||
|
const struct sockaddr *from, int fromlen,
|
||||||
|
time_t *tosleep,
|
||||||
dht_callback *callback, void *closure)
|
dht_callback *callback, void *closure)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
|
|
||||||
if(available) {
|
if(buflen > 0) {
|
||||||
int rc, message;
|
int message;
|
||||||
unsigned char tid[16], id[20], info_hash[20], target[20];
|
unsigned char tid[16], id[20], info_hash[20], target[20];
|
||||||
unsigned char buf[1536], nodes[256], nodes6[1024], token[128];
|
unsigned char nodes[256], nodes6[1024], token[128];
|
||||||
int tid_len = 16, token_len = 128;
|
int tid_len = 16, token_len = 128;
|
||||||
int nodes_len = 256, nodes6_len = 1024;
|
int nodes_len = 256, nodes6_len = 1024;
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
unsigned char values[2048], values6[2048];
|
unsigned char values[2048], values6[2048];
|
||||||
int values_len = 2048, values6_len = 2048;
|
int values_len = 2048, values6_len = 2048;
|
||||||
int want;
|
int want;
|
||||||
struct sockaddr_storage source_storage;
|
|
||||||
struct sockaddr *source = (struct sockaddr*)&source_storage;
|
|
||||||
socklen_t sourcelen = sizeof(source_storage);
|
|
||||||
unsigned short ttid;
|
unsigned short ttid;
|
||||||
|
|
||||||
rc = -1;
|
if(is_martian(from))
|
||||||
if(dht_socket >= 0) {
|
|
||||||
rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
|
|
||||||
if(rc < 0 && errno != EAGAIN) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(dht_socket6 >= 0 && rc < 0) {
|
|
||||||
rc = recvfrom(dht_socket6, buf, 1536, 0,
|
|
||||||
source, &sourcelen);
|
|
||||||
if(rc < 0 && errno != EAGAIN) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
|
|
||||||
goto dontread;
|
|
||||||
|
|
||||||
if(is_martian(source))
|
|
||||||
goto dontread;
|
goto dontread;
|
||||||
|
|
||||||
for(i = 0; i < DHT_MAX_BLACKLISTED; i++) {
|
for(i = 0; i < DHT_MAX_BLACKLISTED; i++) {
|
||||||
if(memcmp(&blacklist[i], source, sourcelen) == 0) {
|
if(memcmp(&blacklist[i], from, fromlen) == 0) {
|
||||||
debugf("Received packet from blacklisted node.\n");
|
debugf("Received packet from blacklisted node.\n");
|
||||||
goto dontread;
|
goto dontread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There's a bug in parse_message -- it will happily overflow the
|
/* See parse_message. */
|
||||||
buffer if it's not NUL-terminated. For now, put a NUL at the
|
|
||||||
end of buffers. */
|
|
||||||
|
|
||||||
if(rc < 1536) {
|
if(((char*)buf)[buflen] != '\0') {
|
||||||
buf[rc] = '\0';
|
debugf("Unterminated message.\n");
|
||||||
} else {
|
errno = EINVAL;
|
||||||
debugf("Overlong message.\n");
|
return -1;
|
||||||
goto dontread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message = parse_message(buf, rc, tid, &tid_len, id, info_hash,
|
message = parse_message(buf, buflen, tid, &tid_len, id, info_hash,
|
||||||
target, &port, token, &token_len,
|
target, &port, token, &token_len,
|
||||||
nodes, &nodes_len, nodes6, &nodes6_len,
|
nodes, &nodes_len, nodes6, &nodes6_len,
|
||||||
values, &values_len, values6, &values6_len,
|
values, &values_len, values6, &values6_len,
|
||||||
|
@ -1900,7 +1879,7 @@ dht_periodic(int available, time_t *tosleep,
|
||||||
|
|
||||||
if(message < 0 || message == ERROR || id_cmp(id, zeroes) == 0) {
|
if(message < 0 || message == ERROR || id_cmp(id, zeroes) == 0) {
|
||||||
debugf("Unparseable message: ");
|
debugf("Unparseable message: ");
|
||||||
debug_printable(buf, rc);
|
debug_printable(buf, buflen);
|
||||||
debugf("\n");
|
debugf("\n");
|
||||||
goto dontread;
|
goto dontread;
|
||||||
}
|
}
|
||||||
|
@ -1922,36 +1901,36 @@ dht_periodic(int available, time_t *tosleep,
|
||||||
case REPLY:
|
case REPLY:
|
||||||
if(tid_len != 4) {
|
if(tid_len != 4) {
|
||||||
debugf("Broken node truncates transaction ids: ");
|
debugf("Broken node truncates transaction ids: ");
|
||||||
debug_printable(buf, rc);
|
debug_printable(buf, buflen);
|
||||||
debugf("\n");
|
debugf("\n");
|
||||||
/* This is really annoying, as it means that we will
|
/* This is really annoying, as it means that we will
|
||||||
time-out all our searches that go through this node.
|
time-out all our searches that go through this node.
|
||||||
Kill it. */
|
Kill it. */
|
||||||
broken_node(id, source, sourcelen);
|
broken_node(id, from, fromlen);
|
||||||
goto dontread;
|
goto dontread;
|
||||||
}
|
}
|
||||||
if(tid_match(tid, "pn", NULL)) {
|
if(tid_match(tid, "pn", NULL)) {
|
||||||
debugf("Pong!\n");
|
debugf("Pong!\n");
|
||||||
new_node(id, source, sourcelen, 2);
|
new_node(id, from, fromlen, 2);
|
||||||
} else if(tid_match(tid, "fn", NULL) ||
|
} else if(tid_match(tid, "fn", NULL) ||
|
||||||
tid_match(tid, "gp", NULL)) {
|
tid_match(tid, "gp", NULL)) {
|
||||||
int gp = 0;
|
int gp = 0;
|
||||||
struct search *sr = NULL;
|
struct search *sr = NULL;
|
||||||
if(tid_match(tid, "gp", &ttid)) {
|
if(tid_match(tid, "gp", &ttid)) {
|
||||||
gp = 1;
|
gp = 1;
|
||||||
sr = find_search(ttid, source->sa_family);
|
sr = find_search(ttid, from->sa_family);
|
||||||
}
|
}
|
||||||
debugf("Nodes found (%d+%d)%s!\n", nodes_len/26, nodes6_len/38,
|
debugf("Nodes found (%d+%d)%s!\n", nodes_len/26, nodes6_len/38,
|
||||||
gp ? " for get_peers" : "");
|
gp ? " for get_peers" : "");
|
||||||
if(nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
|
if(nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
|
||||||
debugf("Unexpected length for node info!\n");
|
debugf("Unexpected length for node info!\n");
|
||||||
broken_node(id, source, sourcelen);
|
broken_node(id, from, fromlen);
|
||||||
} else if(gp && sr == NULL) {
|
} else if(gp && sr == NULL) {
|
||||||
debugf("Unknown search!\n");
|
debugf("Unknown search!\n");
|
||||||
new_node(id, source, sourcelen, 1);
|
new_node(id, from, fromlen, 1);
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
new_node(id, source, sourcelen, 2);
|
new_node(id, from, fromlen, 2);
|
||||||
for(i = 0; i < nodes_len / 26; i++) {
|
for(i = 0; i < nodes_len / 26; i++) {
|
||||||
unsigned char *ni = nodes + i * 26;
|
unsigned char *ni = nodes + i * 26;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
|
@ -1993,7 +1972,7 @@ dht_periodic(int available, time_t *tosleep,
|
||||||
search_send_get_peers(sr, NULL);
|
search_send_get_peers(sr, NULL);
|
||||||
}
|
}
|
||||||
if(sr) {
|
if(sr) {
|
||||||
insert_search_node(id, source, sourcelen, sr,
|
insert_search_node(id, from, fromlen, sr,
|
||||||
1, token, token_len);
|
1, token, token_len);
|
||||||
if(values_len > 0 || values6_len > 0) {
|
if(values_len > 0 || values6_len > 0) {
|
||||||
debugf("Got values (%d+%d)!\n",
|
debugf("Got values (%d+%d)!\n",
|
||||||
|
@ -2012,13 +1991,13 @@ dht_periodic(int available, time_t *tosleep,
|
||||||
} else if(tid_match(tid, "ap", &ttid)) {
|
} else if(tid_match(tid, "ap", &ttid)) {
|
||||||
struct search *sr;
|
struct search *sr;
|
||||||
debugf("Got reply to announce_peer.\n");
|
debugf("Got reply to announce_peer.\n");
|
||||||
sr = find_search(ttid, source->sa_family);
|
sr = find_search(ttid, from->sa_family);
|
||||||
if(!sr) {
|
if(!sr) {
|
||||||
debugf("Unknown search!\n");
|
debugf("Unknown search!\n");
|
||||||
new_node(id, source, sourcelen, 1);
|
new_node(id, from, fromlen, 1);
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
new_node(id, source, sourcelen, 2);
|
new_node(id, from, fromlen, 2);
|
||||||
for(i = 0; i < sr->numnodes; i++)
|
for(i = 0; i < sr->numnodes; i++)
|
||||||
if(id_cmp(sr->nodes[i].id, id) == 0) {
|
if(id_cmp(sr->nodes[i].id, id) == 0) {
|
||||||
sr->nodes[i].request_time = 0;
|
sr->nodes[i].request_time = 0;
|
||||||
|
@ -2032,47 +2011,47 @@ dht_periodic(int available, time_t *tosleep,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debugf("Unexpected reply: ");
|
debugf("Unexpected reply: ");
|
||||||
debug_printable(buf, rc);
|
debug_printable(buf, buflen);
|
||||||
debugf("\n");
|
debugf("\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PING:
|
case PING:
|
||||||
debugf("Ping (%d)!\n", tid_len);
|
debugf("Ping (%d)!\n", tid_len);
|
||||||
new_node(id, source, sourcelen, 1);
|
new_node(id, from, fromlen, 1);
|
||||||
debugf("Sending pong.\n");
|
debugf("Sending pong.\n");
|
||||||
send_pong(source, sourcelen, tid, tid_len);
|
send_pong(from, fromlen, tid, tid_len);
|
||||||
break;
|
break;
|
||||||
case FIND_NODE:
|
case FIND_NODE:
|
||||||
debugf("Find node!\n");
|
debugf("Find node!\n");
|
||||||
new_node(id, source, sourcelen, 1);
|
new_node(id, from, fromlen, 1);
|
||||||
debugf("Sending closest nodes (%d).\n", want);
|
debugf("Sending closest nodes (%d).\n", want);
|
||||||
send_closest_nodes(source, sourcelen,
|
send_closest_nodes(from, fromlen,
|
||||||
tid, tid_len, target, want,
|
tid, tid_len, target, want,
|
||||||
0, NULL, NULL, 0);
|
0, NULL, NULL, 0);
|
||||||
break;
|
break;
|
||||||
case GET_PEERS:
|
case GET_PEERS:
|
||||||
debugf("Get_peers!\n");
|
debugf("Get_peers!\n");
|
||||||
new_node(id, source, sourcelen, 1);
|
new_node(id, from, fromlen, 1);
|
||||||
if(id_cmp(info_hash, zeroes) == 0) {
|
if(id_cmp(info_hash, zeroes) == 0) {
|
||||||
debugf("Eek! Got get_peers with no info_hash.\n");
|
debugf("Eek! Got get_peers with no info_hash.\n");
|
||||||
send_error(source, sourcelen, tid, tid_len,
|
send_error(from, fromlen, tid, tid_len,
|
||||||
203, "Get_peers with no info_hash");
|
203, "Get_peers with no info_hash");
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
struct storage *st = find_storage(info_hash);
|
struct storage *st = find_storage(info_hash);
|
||||||
unsigned char token[TOKEN_SIZE];
|
unsigned char token[TOKEN_SIZE];
|
||||||
make_token(source, 0, token);
|
make_token(from, 0, token);
|
||||||
if(st && st->numpeers > 0) {
|
if(st && st->numpeers > 0) {
|
||||||
debugf("Sending found%s peers.\n",
|
debugf("Sending found%s peers.\n",
|
||||||
source->sa_family == AF_INET6 ? " IPv6" : "");
|
from->sa_family == AF_INET6 ? " IPv6" : "");
|
||||||
send_closest_nodes(source, sourcelen,
|
send_closest_nodes(from, fromlen,
|
||||||
tid, tid_len,
|
tid, tid_len,
|
||||||
info_hash, want,
|
info_hash, want,
|
||||||
source->sa_family, st,
|
from->sa_family, st,
|
||||||
token, TOKEN_SIZE);
|
token, TOKEN_SIZE);
|
||||||
} else {
|
} else {
|
||||||
debugf("Sending nodes for get_peers.\n");
|
debugf("Sending nodes for get_peers.\n");
|
||||||
send_closest_nodes(source, sourcelen,
|
send_closest_nodes(from, fromlen,
|
||||||
tid, tid_len, info_hash, want,
|
tid, tid_len, info_hash, want,
|
||||||
0, NULL, token, TOKEN_SIZE);
|
0, NULL, token, TOKEN_SIZE);
|
||||||
}
|
}
|
||||||
|
@ -2080,31 +2059,31 @@ dht_periodic(int available, time_t *tosleep,
|
||||||
break;
|
break;
|
||||||
case ANNOUNCE_PEER:
|
case ANNOUNCE_PEER:
|
||||||
debugf("Announce peer!\n");
|
debugf("Announce peer!\n");
|
||||||
new_node(id, source, sourcelen, 1);
|
new_node(id, from, fromlen, 1);
|
||||||
if(id_cmp(info_hash, zeroes) == 0) {
|
if(id_cmp(info_hash, zeroes) == 0) {
|
||||||
debugf("Announce_peer with no info_hash.\n");
|
debugf("Announce_peer with no info_hash.\n");
|
||||||
send_error(source, sourcelen, tid, tid_len,
|
send_error(from, fromlen, tid, tid_len,
|
||||||
203, "Announce_peer with no info_hash");
|
203, "Announce_peer with no info_hash");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!token_match(token, token_len, source)) {
|
if(!token_match(token, token_len, from)) {
|
||||||
debugf("Incorrect token for announce_peer.\n");
|
debugf("Incorrect token for announce_peer.\n");
|
||||||
send_error(source, sourcelen, tid, tid_len,
|
send_error(from, fromlen, tid, tid_len,
|
||||||
203, "Announce_peer with wrong token");
|
203, "Announce_peer with wrong token");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(port == 0) {
|
if(port == 0) {
|
||||||
debugf("Announce_peer with forbidden port %d.\n", port);
|
debugf("Announce_peer with forbidden port %d.\n", port);
|
||||||
send_error(source, sourcelen, tid, tid_len,
|
send_error(from, fromlen, tid, tid_len,
|
||||||
203, "Announce_peer with forbidden port number");
|
203, "Announce_peer with forbidden port number");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
storage_store(info_hash, source);
|
storage_store(info_hash, from);
|
||||||
/* Note that if storage_store failed, we lie to the requestor.
|
/* Note that if storage_store failed, we lie to the requestor.
|
||||||
This is to prevent them from backtracking, and hence
|
This is to prevent them from backtracking, and hence
|
||||||
polluting the DHT. */
|
polluting the DHT. */
|
||||||
debugf("Sending peer announced.\n");
|
debugf("Sending peer announced.\n");
|
||||||
send_peer_announced(source, sourcelen, tid, tid_len);
|
send_peer_announced(from, fromlen, tid, tid_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2328,7 +2307,7 @@ dht_send(const void *buf, size_t len, int flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
send_ping(struct sockaddr *sa, int salen,
|
send_ping(const struct sockaddr *sa, int salen,
|
||||||
const unsigned char *tid, int tid_len)
|
const unsigned char *tid, int tid_len)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[512];
|
||||||
|
@ -2348,7 +2327,7 @@ send_ping(struct sockaddr *sa, int salen,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
send_pong(struct sockaddr *sa, int salen,
|
send_pong(const struct sockaddr *sa, int salen,
|
||||||
const unsigned char *tid, int tid_len)
|
const unsigned char *tid, int tid_len)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[512];
|
||||||
|
@ -2367,7 +2346,7 @@ send_pong(struct sockaddr *sa, int salen,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
send_find_node(struct sockaddr *sa, int salen,
|
send_find_node(const struct sockaddr *sa, int salen,
|
||||||
const unsigned char *tid, int tid_len,
|
const unsigned char *tid, int tid_len,
|
||||||
const unsigned char *target, int want, int confirm)
|
const unsigned char *target, int want, int confirm)
|
||||||
{
|
{
|
||||||
|
@ -2396,7 +2375,7 @@ send_find_node(struct sockaddr *sa, int salen,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
send_nodes_peers(struct sockaddr *sa, int salen,
|
send_nodes_peers(const struct sockaddr *sa, int salen,
|
||||||
const unsigned char *tid, int tid_len,
|
const unsigned char *tid, int tid_len,
|
||||||
const unsigned char *nodes, int nodes_len,
|
const unsigned char *nodes, int nodes_len,
|
||||||
const unsigned char *nodes6, int nodes6_len,
|
const unsigned char *nodes6, int nodes6_len,
|
||||||
|
@ -2523,7 +2502,7 @@ buffer_closest_nodes(unsigned char *nodes, int numnodes,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
send_closest_nodes(struct sockaddr *sa, int salen,
|
send_closest_nodes(const struct sockaddr *sa, int salen,
|
||||||
const unsigned char *tid, int tid_len,
|
const unsigned char *tid, int tid_len,
|
||||||
const unsigned char *id, int want,
|
const unsigned char *id, int want,
|
||||||
int af, struct storage *st,
|
int af, struct storage *st,
|
||||||
|
@ -2570,7 +2549,7 @@ send_closest_nodes(struct sockaddr *sa, int salen,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
send_get_peers(struct sockaddr *sa, int salen,
|
send_get_peers(const struct sockaddr *sa, int salen,
|
||||||
unsigned char *tid, int tid_len, unsigned char *infohash,
|
unsigned char *tid, int tid_len, unsigned char *infohash,
|
||||||
int want, int confirm)
|
int want, int confirm)
|
||||||
{
|
{
|
||||||
|
@ -2600,7 +2579,7 @@ send_get_peers(struct sockaddr *sa, int salen,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
send_announce_peer(struct sockaddr *sa, int salen,
|
send_announce_peer(const struct sockaddr *sa, int salen,
|
||||||
unsigned char *tid, int tid_len,
|
unsigned char *tid, int tid_len,
|
||||||
unsigned char *infohash, unsigned short port,
|
unsigned char *infohash, unsigned short port,
|
||||||
unsigned char *token, int token_len, int confirm)
|
unsigned char *token, int token_len, int confirm)
|
||||||
|
@ -2630,7 +2609,7 @@ send_announce_peer(struct sockaddr *sa, int salen,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
send_peer_announced(struct sockaddr *sa, int salen,
|
send_peer_announced(const struct sockaddr *sa, int salen,
|
||||||
unsigned char *tid, int tid_len)
|
unsigned char *tid, int tid_len)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[512];
|
||||||
|
@ -2651,7 +2630,7 @@ send_peer_announced(struct sockaddr *sa, int salen,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
send_error(struct sockaddr *sa, int salen,
|
send_error(const struct sockaddr *sa, int salen,
|
||||||
unsigned char *tid, int tid_len,
|
unsigned char *tid, int tid_len,
|
||||||
int code, const char *message)
|
int code, const char *message)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2009 by Juliusz Chroboczek
|
Copyright (c) 2009, 2010 by Juliusz Chroboczek
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -36,8 +36,9 @@ extern FILE *dht_debug;
|
||||||
int dht_init(int s, int s6, const unsigned char *id, const unsigned char *v);
|
int dht_init(int s, int s6, const unsigned char *id, const unsigned char *v);
|
||||||
int dht_insert_node(const unsigned char *id, struct sockaddr *sa, int salen);
|
int dht_insert_node(const unsigned char *id, struct sockaddr *sa, int salen);
|
||||||
int dht_ping_node(struct sockaddr *sa, int salen);
|
int dht_ping_node(struct sockaddr *sa, int salen);
|
||||||
int dht_periodic(int available, time_t *tosleep,
|
int dht_periodic(const void *buf, size_t buflen,
|
||||||
dht_callback *callback, void *closure);
|
const struct sockaddr *from, int fromlen,
|
||||||
|
time_t *tosleep, dht_callback *callback, void *closure);
|
||||||
int dht_search(const unsigned char *id, int port, int af,
|
int dht_search(const unsigned char *id, int port, int af,
|
||||||
dht_callback *callback, void *closure);
|
dht_callback *callback, void *closure);
|
||||||
int dht_nodes(int af,
|
int dht_nodes(int af,
|
||||||
|
|
Loading…
Reference in New Issue