static void traceStep(struct RouteTracer_Trace* trace, struct Node* next) { struct RouteTracer_pvt* ctx = Identity_cast((struct RouteTracer_pvt*)trace->tracer); if (!next) { // can't find a next node, stalled. Timeout_setTimeout(noPeers, trace, 0, trace->tracer->eventBase, trace->pub.alloc); return; } Assert_true(LabelSplicer_routesThrough(trace->target, next->address.path)); trace->lastNodeAsked = next->address.path; struct RouterModule_Promise* rp = RouterModule_newMessage(next, 0, ctx->router, trace->pub.alloc); Dict* message = Dict_new(rp->alloc); #ifdef Version_4_COMPAT if (next->version < 5) { // The node doesn't support the new API so try running a search for // the bitwise complement of their address to get some peers. Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_FN, rp->alloc); String* notAddr = String_newBinary((char*)next->address.ip6.bytes, 16, rp->alloc); for (int i = 0; i < 16; i++) { notAddr->bytes[i] ^= 0xff; } Dict_putString(message, CJDHTConstants_TARGET, notAddr, rp->alloc); log(ctx->logger, trace, "Sending legacy search method because getpeers is unavailable"); } else { #endif Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_GP, rp->alloc); uint64_t labelForThem = LabelSplicer_unsplice(trace->target, next->address.path); labelForThem = Endian_hostToBigEndian64(labelForThem); String* target = String_newBinary((char*)&labelForThem, 8, rp->alloc); Dict_putString(message, CJDHTConstants_TARGET, target, rp->alloc); log(ctx->logger, trace, "Sending getpeers request"); #ifdef Version_4_COMPAT } #endif rp->userData = trace; rp->callback = responseCallback; RouterModule_sendMessage(rp, message); }
/** * 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++; }
/** * 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 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 >= search->maxRequests) { // fallthrough } else if (search->numFinds > 0 && search->totalRequests >= search->maxRequestsIfFound) { // fallthrough } else if (nextSearchNode == NULL) { // fallthrough } else { break; } if (search->pub.callback) { search->pub.callback(&search->pub, 0, NULL, NULL); } Allocator_free(search->pub.alloc); return; } Bits_memcpyConst(&search->lastNodeAsked, &nextSearchNode->address, sizeof(struct Address)); struct RouterModule_Promise* rp = RouterModule_newMessage(&nextSearchNode->address, 0, ctx->router, search->pub.alloc); Dict* message = Dict_new(rp->alloc); if (!Bits_memcmp(nextSearchNode->address.ip6.bytes, search->target.ip6.bytes, 16)) { Dict_putString(message, CJDHTConstants_QUERY, CJDHTConstants_QUERY_GP, rp->alloc); } else { 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++; }