(trunk third-party) update to dht 0.7

This commit is contained in:
Charles Kerr 2009-07-02 21:54:14 +00:00
parent 48b460c0c3
commit 6aced6393f
2 changed files with 109 additions and 51 deletions

View File

@ -1,3 +1,9 @@
24 June 2009: dht-0.7
* Removed the fixed limit on the number of concurrent searches, we now
use a linked list.
* Fixed build on FreeBSD (thanks to Humihara and Charles Kerr).
22 May 2009: dht-0.6
* Fixed a buffer overflow (when reading) in parse_message.

154
third-party/dht/dht.c vendored
View File

@ -122,6 +122,7 @@ struct search {
int done;
struct search_node nodes[SEARCH_NODES];
int numnodes;
struct search *next;
};
struct peer {
@ -135,6 +136,16 @@ struct peer {
#define DHT_MAX_PEERS 2048
#endif
/* The maximum number of searches we keep data about. */
#ifndef DHT_MAX_SEARCHES
#define DHT_MAX_SEARCHES 1024
#endif
/* The time after which we consider a search to be expirable. */
#ifndef DHT_SEARCH_EXPIRE_TIME
#define DHT_SEARCH_EXPIRE_TIME (62 * 60)
#endif
struct storage {
unsigned char id[20];
int numpeers;
@ -207,12 +218,7 @@ static unsigned char oldsecret[8];
static struct bucket *buckets = NULL;
static struct storage *storage;
/* The maximum number of concurrent searches. */
#ifndef DHT_MAX_SEARCHES
#define DHT_MAX_SEARCHES 20
#endif
static struct search searches[DHT_MAX_SEARCHES];
static struct search *searches = NULL;
static int numsearches;
static unsigned short search_id;
@ -724,10 +730,11 @@ expire_buckets(int s)
static struct search *
find_search(unsigned short tid)
{
int i;
for(i = 0; i < numsearches; i++) {
if(searches[i].tid == tid)
return &searches[i];
struct search *sr = searches;
while(sr) {
if(sr->tid == tid)
return sr;
sr = sr->next;
}
return NULL;
}
@ -798,6 +805,27 @@ flush_search_node(struct search_node *n, struct search *sr)
sr->numnodes--;
}
static void
expire_searches(void)
{
struct search *sr = searches, *previous = NULL;
while(sr) {
struct search *next = sr->next;
if(sr->step_time < now.tv_sec - DHT_SEARCH_EXPIRE_TIME) {
if(previous)
previous->next = next;
else
searches->next = next;
free(sr);
numsearches--;
} else {
previous = sr;
}
sr = next;
}
}
/* This must always return 0 or 1, never -1, not even on failure (see below). */
static int
search_send_get_peers(int s, struct search *sr, struct search_node *n)
@ -909,20 +937,36 @@ search_step(int s, struct search *sr, dht_callback *callback, void *closure)
}
static struct search *
find_free_search_slot(void)
new_search(void)
{
int i;
struct search *sr = NULL;
struct search *sr, *oldest = NULL;
if(numsearches < DHT_MAX_SEARCHES)
return &searches[numsearches++];
for(i = 0; i < numsearches; i++) {
if(searches[i].done &&
(sr == NULL || searches[i].step_time < sr->step_time))
sr = &searches[i];
/* Find the oldest done search */
sr = searches;
while(sr) {
if(sr->done &&
(oldest == NULL || oldest->step_time > sr->step_time))
oldest = sr;
sr = sr->next;
}
return sr;
/* The oldest slot is expired. */
if(oldest && oldest->step_time < now.tv_sec - DHT_SEARCH_EXPIRE_TIME)
return oldest;
/* Allocate a new slot. */
if(numsearches < DHT_MAX_SEARCHES) {
sr = calloc(1, sizeof(struct search));
if(sr != NULL) {
sr->next = searches;
searches = sr;
numsearches++;
return sr;
}
}
/* Oh, well, never mind. Reuse the oldest slot. */
return oldest;
}
/* Insert the contents of a bucket into a search structure. */
@ -945,23 +989,23 @@ dht_search(int s, const unsigned char *id, int port,
{
struct search *sr;
struct bucket *b;
int i;
for(i = 0; i < numsearches; i++) {
if(id_cmp(searches[i].id, id) == 0)
sr = searches;
while(sr) {
if(id_cmp(sr->id, id) == 0)
break;
sr = sr->next;
}
if(i < numsearches) {
if(sr) {
/* We're reusing data from an old search. Reusing the same tid
means that we can merge replies for both searches. */
int j;
sr = searches + i;
int i;
sr->done = 0;
again:
for(j = 0; j < sr->numnodes; j++) {
for(i = 0; i < sr->numnodes; i++) {
struct search_node *n;
n = &sr->nodes[j];
n = &sr->nodes[i];
/* Discard any doubtful nodes. */
if(n->pinged >= 3 || n->reply_time < now.tv_sec - 7200) {
flush_search_node(n, sr);
@ -973,14 +1017,15 @@ dht_search(int s, const unsigned char *id, int port,
n->acked = 0;
}
} else {
sr = find_free_search_slot();
sr = new_search();
if(sr == NULL) {
errno = ENOSPC;
return -1;
}
memset(sr, 0, sizeof(struct search));
sr->tid = search_id++;
sr->step_time = 0;
memcpy(sr->id, id, 20);
sr->done = 0;
sr->numnodes = 0;
}
@ -1107,24 +1152,26 @@ expire_storage(void)
static void
broken_node(int s, const unsigned char *id, struct sockaddr_in *sin)
{
int i, j;
int i;
debugf("Blacklisting broken node.\n");
if(id) {
/* Make the node easy to discard. */
struct node *n;
struct search *sr;
/* Make the node easy to discard. */
n = find_node(id);
if(n) {
n->pinged = 3;
pinged(s, n, NULL);
}
/* Discard it from any searches in progress. */
for(i = 0; i < numsearches; i++) {
for(j = 0; j < searches[i].numnodes; j++)
if(id_cmp(searches[i].nodes[j].id, id) == 0)
flush_search_node(&searches[i].nodes[j],
&searches[i]);
sr = searches;
while(sr) {
for(i = 0; i < sr->numnodes; i++)
if(id_cmp(sr->nodes[i].id, id) == 0)
flush_search_node(&sr->nodes[i], sr);
sr = sr->next;
}
}
/* And make sure we don't hear from it again. */
@ -1214,9 +1261,10 @@ dht_nodes(int *good_return, int *dubious_return, int *cached_return,
void
dht_dump_tables(FILE *f)
{
int i, j;
int i;
struct bucket *b = buckets;
struct storage *st = storage;
struct search *sr = searches;
fprintf(f, "My id ");
print_hex(f, myid, 20);
@ -1250,15 +1298,14 @@ dht_dump_tables(FILE *f)
}
b = b->next;
}
for(i = 0; i < numsearches; i++) {
struct search *sr = &searches[i];
fprintf(f, "\nSearch %d id ", i);
while(sr) {
fprintf(f, "\nSearch id ");
print_hex(f, sr->id, 20);
fprintf(f, " age %d%s\n", (int)(now.tv_sec - sr->step_time),
sr->done ? " (done)" : "");
for(j = 0; j < sr->numnodes; j++) {
struct search_node *n = &sr->nodes[j];
fprintf(f, "Node %d id ", j);
for(i = 0; i < sr->numnodes; i++) {
struct search_node *n = &sr->nodes[i];
fprintf(f, "Node %d id ", i);
print_hex(f, n->id, 20);
fprintf(f, " bits %d age ", common_bits(sr->id, n->id));
if(n->request_time)
@ -1270,6 +1317,7 @@ dht_dump_tables(FILE *f)
find_node(n->id) ? " (known)" : "",
n->replied ? " (replied)" : "");
}
sr = sr->next;
}
@ -1305,6 +1353,7 @@ dht_init(int s, const unsigned char *id, const unsigned char *v)
if(buckets == NULL)
return -1;
searches = NULL;
numsearches = 0;
storage = NULL;
@ -1654,26 +1703,29 @@ dht_periodic(int s, int available, time_t *tosleep,
if(now.tv_sec >= expire_stuff_time) {
expire_buckets(s);
expire_storage();
expire_searches();
}
if(search_time > 0 && now.tv_sec >= search_time) {
int i;
for(i = 0; i < numsearches; i++) {
struct search *sr = &searches[i];
struct search *sr;
sr = searches;
while(sr) {
if(!sr->done && sr->step_time + 5 <= now.tv_sec) {
search_step(s, sr, callback, closure);
}
sr = sr->next;
}
search_time = 0;
for(i = 0; i < numsearches; i++) {
struct search *sr = &searches[i];
sr = searches;
while(sr) {
if(!sr->done) {
time_t tm = sr->step_time + 15 + random() % 10;
if(search_time == 0 || search_time > tm)
search_time = tm;
}
sr = sr->next;
}
}