示例#1
0
static void test_addNode()
{
    struct Address* myAddr = randomAddress();
    struct NodeStore* store = setUp(myAddr, 2);
    // adding ourselves should be null
    Assert_true(NodeStore_addNode(store, myAddr, 1, Version_CURRENT_PROTOCOL) == NULL);

    // adding a random node with no peer should be null
    Assert_true(
        !NodeStore_addNode(store, randomIp((int[]){2,2,1}/*0x155*/), 1, Version_CURRENT_PROTOCOL)
示例#2
0
static void responseCallback(struct RouterModule_Promise* promise,
                             uint32_t lagMilliseconds,
                             struct Node* fromNode,
                             Dict* result)
{
    struct RouteTracer_Trace* trace = Identity_cast((struct RouteTracer_Trace*)promise->userData);
    struct RouteTracer_pvt* ctx = Identity_cast((struct RouteTracer_pvt*)trace->tracer);
    if (!fromNode) {
        // trace has stalled.
        log(ctx->logger, trace, "STALLED request timed out");
        noPeers(trace);
        return;
    }

    if (trace->pub.callback) {
        trace->pub.callback(&trace->pub, lagMilliseconds, fromNode, result);
    }

    String* nodes = Dict_getString(result, CJDHTConstants_NODES);

    if (nodes && (nodes->len == 0 || nodes->len % Address_SERIALIZED_SIZE != 0)) {
        log(ctx->logger, trace, "STALLED dropping unrecognized reply");
        noPeers(trace);
        return;
    }

    struct VersionList* versions = NULL;
    String* versionsStr = Dict_getString(result, CJDHTConstants_NODE_PROTOCOLS);
    if (versionsStr) {
        versions = VersionList_parse(versionsStr, promise->alloc);
        #ifdef Version_1_COMPAT
            // Version 1 lies about the versions of other nodes, assume they're all v1.
            if (fromNode->version < 2) {
                for (int i = 0; i < (int)versions->length; i++) {
                    versions->versions[i] = 1;
                }
            }
        #endif
    }

    struct Node* next = NULL;

    for (uint32_t i = 0; nodes && i < nodes->len; i += Address_SERIALIZED_SIZE) {

        struct Address addr;
        Address_parse(&addr, (uint8_t*) &nodes->bytes[i]);

        // calculate the ipv6
        Address_getPrefix(&addr);

        // We need to splice the given address on to the end of the
        // address of the node which gave it to us.
        addr.path = LabelSplicer_splice(addr.path, fromNode->address.path);

        if (addr.path == UINT64_MAX) {
            log(ctx->logger, trace, "dropping node because route could not be spliced");
            continue;
        }

        /*#ifdef Log_DEBUG
            uint8_t printedAddr[60];
            Address_print(printedAddr, &addr);
            Log_debug(ctx->logger, "discovered node [%s]", printedAddr);
        #endif*/

        if (!Bits_memcmp(ctx->myAddress, addr.ip6.bytes, 16)) {
            // Any path which loops back through us is necessarily a dead route.
            uint8_t printedAddr[60];
            Address_print(printedAddr, &addr);
            Log_debug(ctx->logger, "Loop route [%s]", printedAddr);
            NodeStore_brokenPath(addr.path, ctx->nodeStore);
            continue;
        }

        if (!AddressCalc_validAddress(addr.ip6.bytes)) {
            log(ctx->logger, trace, "was told garbage");
            // This should never happen, badnode.
            break;
        }

        // Nodes we are told about are inserted with 0 reach and assumed version 1.
        uint32_t version = (versions) ? versions->versions[i / Address_SERIALIZED_SIZE] : 1;
        struct Node* n = NodeStore_addNode(ctx->nodeStore, &addr, 0, version);

        if (!n) {
            // incompatible version, introduced to ourselves...
        } else if (!LabelSplicer_routesThrough(trace->target, n->address.path)) {
            // not on the way
        } else  if (n->address.path <= fromNode->address.path) {
            // losing ground
        } else if (next && n->address.path >= next->address.path) {
            // not better than the one we have
        } else {
            next = n;
        }
    }

    if (fromNode->address.path == trace->target) {
        log(ctx->logger, trace, "Trace completed successfully");
        noPeers(trace);
        return;
    }

    if (!nodes) {
        log(ctx->logger, trace, "No nodes in trace response");
    }

    if (!next) {
        log(ctx->logger, trace, "STALLED no suitable peers in reply");
        noPeers(trace);
        return;
    }

    if (!LabelSplicer_routesThrough(trace->target, next->address.path)) {
        log(ctx->logger, trace, "STALLED Nodestore broke the path of the best option");
        noPeers(trace);
        return;
    }

    traceStep(trace, next);
}