]> granicus.if.org Git - transmission/commitdiff
(trunk) #7: update to upstream dht-0.6
authorCharles Kerr <charles@transmissionbt.com>
Fri, 22 May 2009 16:45:41 +0000 (16:45 +0000)
committerCharles Kerr <charles@transmissionbt.com>
Fri, 22 May 2009 16:45:41 +0000 (16:45 +0000)
third-party/dht/CHANGES
third-party/dht/dht-example.c
third-party/dht/dht.c

index 9c07d4f0e16f9c7e441a0c9cafb22962c2e8f129..9cbff34046e6d5b2916d646e794985faddfbb977 100644 (file)
@@ -1,3 +1,10 @@
+22 May 2009: dht-0.6
+
+  * Fixed a buffer overflow (when reading) in parse_message.
+  * Fixed slightly inacurrate metric computation when searching.
+  * Removed a slightly inaccurate shortcut when responding to find_nodes.
+  * Relaxed the rate-limiting parameters to 4 requests per second.
+
 19 May 2009: dht-0.5
 
   * Made reading of /dev/urandom a function provided by the user.
index b5cf6e7f32b7dc742ce0686e2989f51ac23a2c45..f28c095eec06706c4b4922a8a1c1bf6821779337 100644 (file)
@@ -155,6 +155,8 @@ main(int argc, char **argv)
         }
 
         i++;
+        if(i >= argc)
+            goto usage;
 
         infop = info;
         while(infop) {
@@ -172,9 +174,6 @@ main(int argc, char **argv)
         i++;
     }
 
-    if(i < argc)
-        goto usage;
-
     /* If you set dht_debug to a stream, every action taken by the DHT will
        be logged. */
     dht_debug = stdout;
index 740810cbbab68c25d3ba6498d8cd8e972e177b04..efe5691eb269b50dddb410a3d19a1361cba6f7b8 100644 (file)
@@ -109,7 +109,7 @@ struct search_node {
 };
 
 /* When performing a search, we search for up to SEARCH_NODES closest nodes
-   to the destinatin, and use the additional ones to backtrack if any of
+   to the destination, and use the additional ones to backtrack if any of
    the target 8 turn out to be dead. */
 #define SEARCH_NODES 14
 
@@ -153,10 +153,10 @@ static int send_found_nodes(int s, struct sockaddr *sa, int salen,
                             const unsigned char *tid, int tid_len,
                             const unsigned char *nodes, int nodes_len,
                             const unsigned char *token, int token_len);
-static int send_bucket_nodes(int s, struct sockaddr *sa, int salen,
-                             const unsigned char *tid, int tid_len,
-                             struct bucket *b,
-                             const unsigned char *token, int token_len);
+static int send_closest_nodes(int s, struct sockaddr *sa, int salen,
+                              const unsigned char *tid, int tid_len,
+                              const unsigned char *id,
+                              const unsigned char *token, int token_len);
 static int send_get_peers(int s, struct sockaddr *sa, int salen,
                           unsigned char *tid, int tid_len,
                           unsigned char *infohash, int confirm);
@@ -319,6 +319,26 @@ common_bits(const unsigned char *id1, const unsigned char *id2)
     return 8 * i + j;
 }
 
+/* Determine whether id1 or id2 is closer to ref */
+int
+xorcmp(const unsigned char *id1, const unsigned char *id2,
+       const unsigned char *ref)
+{
+    int i;
+    for(i = 0; i < 20; i++) {
+        unsigned char xor1, xor2;
+        if(id1[i] == id2[i])
+            continue;
+        xor1 = id1[i] ^ ref[i];
+        xor2 = id2[i] ^ ref[i];
+        if(xor1 < xor2)
+            return -1;
+        else
+            return 1;
+    }
+    return 0;
+}
+
 /* We keep buckets in a sorted linked list.  A bucket b ranges from
    b->first inclusive up to b->next->first exclusive. */
 static int
@@ -583,7 +603,7 @@ new_node(int s, const unsigned char *id, struct sockaddr_in *sin,
     /* New node.  First, try to get rid of a known-bad node. */
     n = b->nodes;
     while(n) {
-        if(n->pinged >= 3) {
+        if(n->pinged >= 3 && n->pinged_time < now.tv_sec - 15) {
             memcpy(n->id, id, 20);
             n->sin = *sin;
             n->time = confirm ? now.tv_sec : 0;
@@ -604,7 +624,8 @@ new_node(int s, const unsigned char *id, struct sockaddr_in *sin,
         while(n) {
             /* Pick the first dubious node that we haven't pinged in the
                last 15 seconds.  This gives nodes the time to reply, but
-               tends to concentrate on the same nodes. */
+               tends to concentrate on the same nodes, so that we get rid
+               of bad nodes fast. */
             if(!node_good(n)) {
                 dubious = 1;
                 if(n->pinged_time < now.tv_sec - 15) {
@@ -719,7 +740,6 @@ insert_search_node(unsigned char *id, struct sockaddr_in *sin,
                    struct search *sr, int replied,
                    unsigned char *token, int token_len)
 {
-    int bits = common_bits(id, sr->id);
     struct search_node *n;
     int i, j;
 
@@ -728,7 +748,7 @@ insert_search_node(unsigned char *id, struct sockaddr_in *sin,
             n = &sr->nodes[i];
             goto found;
         }
-        if(common_bits(sr->id, sr->nodes[i].id) < bits)
+        if(xorcmp(id, sr->nodes[i].id, sr->id) < 0)
             break;
     }
 
@@ -1557,16 +1577,9 @@ dht_periodic(int s, int available, time_t *tosleep,
         case FIND_NODE:
             debugf("Find node!\n");
             new_node(s, id, &source, 1);
-            {
-                struct bucket *b = find_bucket(target);
-                if(b) {
-                    debugf("Sending nodes from bucket.\n");
-                    send_bucket_nodes(s,
-                                      (struct sockaddr*)&source,
-                                      sizeof(source),
-                                      tid, tid_len, b, NULL, 0);
-                }
-            }
+            debugf("Sending closest nodes.\n");
+            send_closest_nodes(s, (struct sockaddr*)&source, sizeof(source),
+                               tid, tid_len, target, NULL, 0);
             break;
         case GET_PEERS:
             debugf("Get_peers!\n");
@@ -1596,18 +1609,15 @@ dht_periodic(int s, int available, time_t *tosleep,
                                      token, TOKEN_SIZE);
 
                 } else {
-                    struct bucket *b = find_bucket(info_hash);
-                    if(b) {
-                        unsigned char token[TOKEN_SIZE];
-                        make_token((unsigned char*)&source.sin_addr,
-                                   ntohs(source.sin_port),
-                                   0, token);
-                        debugf("Sending nodes for get_peers.\n");
-                        send_bucket_nodes(s, (struct sockaddr*)&source,
-                                          sizeof(source),
-                                          tid, tid_len, b,
-                                          token, TOKEN_SIZE);
-                    }
+                    unsigned char token[TOKEN_SIZE];
+                    make_token((unsigned char*)&source.sin_addr,
+                               ntohs(source.sin_port),
+                               0, token);
+                    debugf("Sending nodes for get_peers.\n");
+                    send_closest_nodes(s, (struct sockaddr*)&source,
+                                       sizeof(source),
+                                       tid, tid_len, info_hash,
+                                       token, TOKEN_SIZE);
                 }
             }
             break;
@@ -1951,34 +1961,66 @@ send_found_nodes(int s, struct sockaddr *sa, int salen,
 }
 
 static int
-buffer_bucket(unsigned char *buf, int bufsize, struct bucket *b)
+insert_closest_node(unsigned char *nodes, int numnodes,
+                    const unsigned char *id, struct node *n)
+{
+    int i;
+    for(i = 0; i< numnodes; i++) {
+        if(id_cmp(nodes + 26 * i, id) == 0)
+            return numnodes;
+        if(xorcmp(n->id, nodes + 26 * i, id) < 0)
+            break;
+    }
+
+    if(i == 8)
+        return numnodes;
+
+    if(numnodes < 8)
+        numnodes++;
+
+    if(i < numnodes - 1)
+        memmove(nodes + 26 * (i + 1), nodes + 26 * i, 26 * (numnodes - i - 1));
+
+    memcpy(nodes + 26 * i, n->id, 20);
+    memcpy(nodes + 26 * i + 20, &n->sin.sin_addr, 4);
+    memcpy(nodes + 26 * i + 24, &n->sin.sin_port, 2);
+
+    return numnodes;
+}
+
+static int
+buffer_closest_nodes(unsigned char *nodes, int numnodes,
+                     const unsigned char *id, struct bucket *b)
 {
-    int i = 0;
     struct node *n = b->nodes;
-    while(n && i < bufsize - 26) {
-        if(node_good(n)) {
-            memcpy(buf + i, n->id, 20);
-            memcpy(buf + i + 20, &n->sin.sin_addr, 4);
-            memcpy(buf + i + 24, &n->sin.sin_port, 2);
-            i += 26;
-        }
+    while(n) {
+        if(node_good(n))
+            numnodes = insert_closest_node(nodes, numnodes, id, n);
         n = n->next;
     }
-    return i;
+    return numnodes;
 }
 
 int
-send_bucket_nodes(int s, struct sockaddr *sa, int salen,
-                  const unsigned char *tid, int tid_len,
-                  struct bucket *b,
-                  const unsigned char *token, int token_len)
+send_closest_nodes(int s, struct sockaddr *sa, int salen,
+                   const unsigned char *tid, int tid_len,
+                   const unsigned char *id,
+                   const unsigned char *token, int token_len)
 {
     unsigned char nodes[8 * 26];
-    int nodeslen = 0;
+    int numnodes = 0;
+    struct bucket *b;
+
+    b = find_bucket(id);
+    numnodes = buffer_closest_nodes(nodes, numnodes, id, b);
+    if(b->next)
+        numnodes = buffer_closest_nodes(nodes, numnodes, id, b->next);
+    b = previous_bucket(b);
+    if(b)
+        numnodes = buffer_closest_nodes(nodes, numnodes, id, b);
 
-    nodeslen = buffer_bucket(nodes, 8 * 26, b);
     return send_found_nodes(s, sa, salen, tid, tid_len,
-                            nodes, nodeslen,
+                            nodes, numnodes * 26,
                             token, token_len);
 }
 
@@ -2110,6 +2152,7 @@ memmem(const void *haystack, size_t haystacklen,
     const char *n = needle;
     size_t i;
 
+    /* size_t is unsigned */
     if(needlelen > haystacklen)
         return NULL;