static void searchReplyCallback(struct RouterModule_Promise* promise, uint32_t lagMilliseconds, struct Address* from, Dict* result) { struct SearchRunner_Search* search = Identity_check((struct SearchRunner_Search*)promise->userData); if (!Bits_memcmp(from->ip6.bytes, search->target.ip6.bytes, 16)) { search->numFinds++; } struct Address_List* nodeList = ReplySerializer_parse(from, result, search->runner->logger, true, promise->alloc); struct Address* best = NULL; for (int i = 0; nodeList && i < nodeList->length; i++) { if (isDuplicateEntry(nodeList, i)) { continue; } if (Address_closest(&search->target, &nodeList->elems[i], from) >= 0) { // Too much noise. //Log_debug(search->runner->logger, "Answer was further from the target than us.\n"); continue; } if (search->lastNodeAsked.path != from->path) { // old queries coming in late... continue; } struct Node_Two* nn = NodeStore_getBest(search->runner->nodeStore, nodeList->elems[i].ip6.bytes); if (!nn) { RumorMill_addNode(search->runner->rumorMill, &nodeList->elems[i]); } //nodeList->elems[i].path = // NodeStore_optimizePath(search->runner->nodeStore, nodeList->elems[i].path); if (!Bits_memcmp(nodeList->elems[i].ip6.bytes, search->target.ip6.bytes, 16)) { if (!best) { best = &nodeList->elems[i]; continue; } else if (nodeList->elems[i].path < best->path) { SearchStore_addNodeToSearch(best, search->search); best = &nodeList->elems[i]; continue; } } SearchStore_addNodeToSearch(&nodeList->elems[i], search->search); } if (best) { SearchStore_addNodeToSearch(best, search->search); } }
/** * Send a search request to the next node in this search. * This is called whenever a response comes in or after the global mean response time passes. */ static void searchStep(struct SearchRunner_Search* search) { struct SearchRunner_pvt* ctx = Identity_check((struct SearchRunner_pvt*)search->runner); struct Node_Two* node; struct SearchStore_Node* nextSearchNode; for (;;) { nextSearchNode = SearchStore_getNextNode(search->search); // If the number of requests sent has exceeded the max search requests, let's stop there. if (search->totalRequests >= MAX_REQUESTS_PER_SEARCH || nextSearchNode == NULL) { if (search->pub.callback) { search->pub.callback(&search->pub, 0, NULL, NULL); } Allocator_free(search->pub.alloc); return; } node = NodeStore_getBest(&nextSearchNode->address, ctx->nodeStore); if (!node) { continue; } if (node == ctx->nodeStore->selfNode) { continue; } if (Bits_memcmp(node->address.ip6.bytes, nextSearchNode->address.ip6.bytes, 16)) { continue; } break; } Assert_true(node != ctx->nodeStore->selfNode); Bits_memcpyConst(&search->lastNodeAsked, &node->address, sizeof(struct Address)); struct RouterModule_Promise* rp = RouterModule_newMessage(&node->address, 0, ctx->router, search->pub.alloc); Dict* message = Dict_new(rp->alloc); Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_FN, rp->alloc); Dict_putString(message, CJDHTConstants_TARGET, search->targetStr, rp->alloc); rp->userData = search; rp->callback = searchCallback; RouterModule_sendMessage(rp, message); search->totalRequests++; }
struct Node_Two* Router_lookup(struct Router* r, uint8_t targetAddr[16]) { struct Router_pvt* rr = Identity_check((struct Router_pvt*)r); return NodeStore_getBest(rr->nodeStore, targetAddr); }