Browse Source

We must not trigger searches for nodes which we already know a path to, but the response has to be async because reasons

Caleb James DeLisle 9 years ago
parent
commit
27d91616c2
1 changed files with 24 additions and 22 deletions
  1. 24 22
      dht/Pathfinder.c

+ 24 - 22
dht/Pathfinder.c

@@ -30,6 +30,7 @@
 #include "dht/dhtcore/Janitor.h"
 #include "dht/dhtcore/Router_new.h"
 #include "util/AddrTools.h"
+#include "util/events/Timeout.h"
 #include "wire/Error.h"
 #include "util/CString.h"
 
@@ -49,6 +50,10 @@ struct Pathfinder_pvt
     struct Admin* admin;
     struct EventEmitter* ee;
 
+    // hack
+    struct Node_Two asyncNode;
+    struct Timeout* asyncTo;
+
     #define Pathfinder_pvt_state_INITIALIZING 0
     #define Pathfinder_pvt_state_RUNNING 1
     int state;
@@ -250,6 +255,13 @@ static Iface_DEFUN switchErr(struct Message* msg, struct Pathfinder_pvt* pf)
     return NULL;
 }
 
+static void asyncRespond(void* vPathfinder)
+{
+    struct Pathfinder_pvt* pf = Identity_check((struct Pathfinder_pvt*) vPathfinder);
+    pf->asyncTo = NULL;
+    onBestPathChange(pf, &pf->asyncNode);
+}
+
 static Iface_DEFUN searchReq(struct Message* msg, struct Pathfinder_pvt* pf)
 {
     uint8_t addr[16];
@@ -259,7 +271,13 @@ static Iface_DEFUN searchReq(struct Message* msg, struct Pathfinder_pvt* pf)
     AddrTools_printIp(printedAddr, addr);
     Log_debug(pf->log, "Search req [%s]", printedAddr);
 
-    SearchRunner_search(addr, 20, 3, pf->searchRunner, pf->alloc);
+    struct Node_Two* node = NodeStore_nodeForAddr(pf->nodeStore, addr);
+    if (node && !pf->asyncTo) {
+        Bits_memcpyConst(&pf->asyncNode, node, sizeof(struct Node_Two));
+        pf->asyncTo = Timeout_setTimeout(asyncRespond, pf, 0, pf->base, pf->alloc);
+    } else {
+        SearchRunner_search(addr, 20, 3, pf->searchRunner, pf->alloc);
+    }
     return NULL;
 }
 
@@ -329,30 +347,14 @@ static Iface_DEFUN discoveredPath(struct Message* msg, struct Pathfinder_pvt* pf
     // We're somehow aware of this path (even if it's unused)
     if (NodeStore_linkForPath(pf->nodeStore, addr.path)) { return NULL; }
 
+    // If we don't already care about the destination, then don't do anything.
+    struct Node_Two* nn = NodeStore_nodeForAddr(pf->nodeStore, addr.ip6.bytes);
+    if (!nn) { return NULL; }
+
     // Our best path is "shorter" (label bits which is somewhat representitive of hop count)
     // basically this is just to dampen the flood to the RM because otherwise it prevents Janitor
     // from getting any actual work done.
-    struct Node_Two* nn = NodeStore_nodeForAddr(pf->nodeStore, addr.ip6.bytes);
-    if (nn && nn->address.path < addr.path) { return NULL; }
-
-    // In order to avoid making the janitor ping endless nodes which are of no value, we will
-    // filter out anything which has a longer path than the average of nodes in better or equal
-    // k-buckets.
-    if (!nn) {
-        int ctr = 0;
-        int totalLog2Path = 0;
-        uint32_t selfPrefix = Address_getPrefix(&pf->myAddr);
-        int ourKDistLog = Bits_log2x32(Address_getPrefix(&addr) ^ selfPrefix);
-        for (;;) {
-            nn = NodeStore_getNextNode(pf->nodeStore, nn);
-            if (!nn) { break; }
-            if (Bits_log2x32(Address_getPrefix(&nn->address) ^ selfPrefix) <= ourKDistLog) {
-                ctr++;
-                totalLog2Path += Bits_log2x64(nn->address.path);
-            }
-        }
-        if (ctr && (totalLog2Path / ctr) <= Bits_log2x64(addr.path)) { return NULL; }
-    }
+    if (nn->address.path < addr.path) { return NULL; }
 
     Log_debug(pf->log, "Discovered path [%s]", Address_toString(&addr, msg->alloc)->bytes);
     RumorMill_addNode(pf->rumorMill, &addr);