Example #1
0
int main(int argc, char** argv)
{
    #ifdef Log_KEYS
        fprintf(stderr, "Log_LEVEL = KEYS, EXPECT TO SEE PRIVATE KEYS IN YOUR LOGS!\n");
    #endif
    Crypto_init();
    assert(argc > 0);

    if (argc == 1) { // no arguments
        if (isatty(STDIN_FILENO)) {
            // We were started from a terminal
            // The chances an user wants to type in a configuration
            // bij hand are pretty slim so we show him the usage
            return usage(argv[0]);
        } else {
            // We assume stdin is a configuration file and that we should
            // start routing
        }
    }
    if (argc == 2) { // one argument
        if (strcmp(argv[1], "--help") == 0) {
            return usage(argv[0]);
        } else if (strcmp(argv[1], "--genconf") == 0) {
            return genconf();
        } else if (strcmp(argv[1], "--getcmds") == 0) {
            // Performed after reading the configuration
        } else if (strcmp(argv[1], "--pidfile") == 0) {
            // Performed after reading the configuration
        } else {
            fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[1]);
        fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
            return -1;
        }
    }
    if (argc >  2) { // more than one argument?
        fprintf(stderr, "%s: too many arguments\n", argv[0]);
        fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
        return -1;
    }

    struct Context context;
    memset(&context, 0, sizeof(struct Context));
    context.base = event_base_new();

    // Allow it to allocate 4MB
    context.allocator = MallocAllocator_new(1<<22);
    struct Reader* reader = FileReader_new(stdin, context.allocator);
    Dict config;
    if (JsonBencSerializer_get()->parseDictionary(reader, context.allocator, &config)) {
        fprintf(stderr, "Failed to parse configuration.\n");
        return -1;
    }

    if (argc == 2 && strcmp(argv[1], "--getcmds") == 0) {
        return getcmds(&config);
    }
    if (argc == 2 && strcmp(argv[1], "--pidfile") == 0) {
        pidfile(&config);
        return 0;
    }

    char* user = setUser(Dict_getList(&config, BSTR("security")));

    // Admin
    Dict* adminConf = Dict_getDict(&config, BSTR("admin"));
    if (adminConf) {
        admin(adminConf, user, &context);
    }

    // Logging
    struct Writer* logwriter = FileWriter_new(stdout, context.allocator);
    struct Log logger = { .writer = logwriter };
    context.logger = &logger;

    struct Address myAddr;
    uint8_t privateKey[32];
    parsePrivateKey(&config, &myAddr, privateKey);

    context.eHandler = AbortHandler_INSTANCE;
    context.switchCore = SwitchCore_new(context.logger, context.allocator);
    context.ca =
        CryptoAuth_new(&config, context.allocator, privateKey, context.base, context.logger);
    context.registry = DHTModules_new(context.allocator);
    ReplyModule_register(context.registry, context.allocator);

    // Router
    Dict* routerConf = Dict_getDict(&config, BSTR("router"));
    registerRouter(routerConf, myAddr.key, &context);

    SerializationModule_register(context.registry, context.allocator);

    // Authed passwords.
    List* authedPasswords = Dict_getList(&config, BSTR("authorizedPasswords"));
    if (authedPasswords) {
        authorizedPasswords(authedPasswords, &context);
    }

    // Interfaces.
    Dict* interfaces = Dict_getDict(&config, BSTR("interfaces"));
    Dict* udpConf = Dict_getDict(interfaces, BSTR("UDPInterface"));

    if (udpConf) {
        configureUDP(udpConf, &context);
    }

    if (udpConf == NULL) {
        fprintf(stderr, "No interfaces configured to connect to.\n");
        return -1;
    }

    // pid file
    String* pidFile = Dict_getString(&config, BSTR("pidFile"));
    if (pidFile) {
        Log_info1(context.logger, "Writing pid of process to [%s].\n", pidFile->bytes);
        FILE* pf = fopen(pidFile->bytes, "w");
        if (!pf) {
            Log_critical2(context.logger,
                          "Failed to open pid file [%s] for writing, errno=%d\n",
                          pidFile->bytes,
                          errno);
            return -1;
        }
        fprintf(pf, "%d", getpid());
        fclose(pf);
    }

    Ducttape_register(&config,
                      privateKey,
                      context.registry,
                      context.routerModule,
                      context.routerIf,
                      context.switchCore,
                      context.base,
                      context.allocator,
                      context.logger);

    uint8_t address[53];
    Base32_encode(address, 53, myAddr.key, 32);
    Log_info1(context.logger, "Your address is: %s.k\n", address);
    uint8_t myIp[40];
    Address_printIp(myIp, &myAddr);
    Log_info1(context.logger, "Your IPv6 address is: %s\n", myIp);

    // Security.
    security(Dict_getList(&config, BSTR("security")), context.logger, context.eHandler);

    event_base_loop(context.base, 0);

    // Never reached.
    return 0;
}
Example #2
0
/*
 * This process is started with 2 parameters, they must all be numeric in base 10.
 * toAngel the pipe which is used to send data back to the angel process.
 * fromAngel the pipe which is used to read incoming data from the angel.
 *
 * Upon initialization, this process will wait for an initial configuration to be sent to
 * it and then it will send an initial response.
 */
int Core_main(int argc, char** argv)
{
    struct Except* eh = NULL;
    int toAngel;
    int fromAngel;
    if (argc != 4
        || !(toAngel = atoi(argv[2]))
        || !(fromAngel = atoi(argv[3])))
    {
        Except_raise(eh, -1, "This is internal to cjdns and shouldn't started manually.");
    }

    struct Allocator* alloc = MallocAllocator_new(ALLOCATOR_FAILSAFE);
    struct EventBase* eventBase = EventBase_new(alloc);
    struct Random* rand = Random_new(alloc, eh);

    // -------------------- Setup the Pre-Logger ---------------------- //
    struct Writer* logWriter = FileWriter_new(stdout, alloc);
    struct Log* preLogger = WriterLog_new(logWriter, alloc);
    struct IndirectLog* indirectLogger = IndirectLog_new(alloc);
    indirectLogger->wrappedLog = preLogger;
    struct Log* logger = &indirectLogger->pub;

    // The first read inside of getInitialConfig() will begin it waiting.
    struct PipeInterface* pi =
        PipeInterface_new(fromAngel, toAngel, eventBase, logger, alloc, rand);

    Dict* config = getInitialConfig(&pi->generic, eventBase, alloc, eh);
    String* privateKeyHex = Dict_getString(config, String_CONST("privateKey"));
    Dict* adminConf = Dict_getDict(config, String_CONST("admin"));
    String* pass = Dict_getString(adminConf, String_CONST("pass"));
    if (!pass || !privateKeyHex) {
        Except_raise(eh, -1, "Expected 'pass' and 'privateKey' in configuration.");
    }
    Log_keys(logger, "Starting core with admin password [%s]", pass->bytes);
    uint8_t privateKey[32];
    if (privateKeyHex->len != 64
        || Hex_decode(privateKey, 32, (uint8_t*) privateKeyHex->bytes, 64) != 32)
    {
        Except_raise(eh, -1, "privateKey must be 64 bytes of hex.");
    }

    struct Admin* admin = Admin_new(&pi->generic, alloc, logger, eventBase, pass);

    Dict adminResponse = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST("none")), NULL);
    Admin_sendMessageToAngel(&adminResponse, admin);

    // --------------------- Setup the Logger --------------------- //
    // the prelogger will nolonger be used.
    struct Log* adminLogger = AdminLog_registerNew(admin, alloc, rand);
    indirectLogger->wrappedLog = adminLogger;
    logger = adminLogger;


    // CryptoAuth
    struct Address addr;
    parsePrivateKey(privateKey, &addr, eh);
    struct CryptoAuth* cryptoAuth = CryptoAuth_new(alloc, privateKey, eventBase, logger, rand);

    struct SwitchCore* switchCore = SwitchCore_new(logger, alloc);
    struct DHTModuleRegistry* registry = DHTModuleRegistry_new(alloc);
    ReplyModule_register(registry, alloc);

    // Router
    struct RouterModule* router = RouterModule_register(registry,
                                                        alloc,
                                                        addr.key,
                                                        eventBase,
                                                        logger,
                                                        admin,
                                                        rand);

    SerializationModule_register(registry, logger, alloc);

    struct IpTunnel* ipTun = IpTunnel_new(logger, eventBase, alloc, rand);

    struct Ducttape* dt = Ducttape_register(privateKey,
                                            registry,
                                            router,
                                            switchCore,
                                            eventBase,
                                            alloc,
                                            logger,
                                            admin,
                                            ipTun,
                                            rand);

    struct SwitchPinger* sp =
        SwitchPinger_new(&dt->switchPingerIf, eventBase, logger, alloc);

    // Interfaces.
    struct InterfaceController* ifController =
        DefaultInterfaceController_new(cryptoAuth,
                                       switchCore,
                                       router,
                                       logger,
                                       eventBase,
                                       sp,
                                       alloc);

    // ------------------- Register RPC functions ----------------------- //
    SwitchPinger_admin_register(sp, admin, alloc);
    UDPInterface_admin_register(eventBase, alloc, logger, admin, ifController);
#ifdef HAS_ETH_INTERFACE
    ETHInterface_admin_register(eventBase, alloc, logger, admin, ifController);
#endif
    RouterModule_admin_register(router, admin, alloc);
    AuthorizedPasswords_init(admin, cryptoAuth, alloc);
    Admin_registerFunction("ping", adminPing, admin, false, NULL, admin);
    Admin_registerFunction("Core_exit", adminExit, logger, true, NULL, admin);
    Core_admin_register(addr.ip6.bytes, dt, logger, alloc, admin, eventBase);
    Security_admin_register(alloc, logger, admin);
    IpTunnel_admin_register(ipTun, admin, alloc);

    struct MemoryContext* mc =
        alloc->clone(sizeof(struct MemoryContext), alloc,
            &(struct MemoryContext) {
                .allocator = alloc,
                .admin = admin
            });
Example #3
0
static Iface_DEFUN connected(struct Pathfinder_pvt* pf, struct Message* msg)
{
    Log_debug(pf->log, "INIT");

    struct PFChan_Core_Connect conn;
    Message_pop(msg, &conn, PFChan_Core_Connect_SIZE, NULL);
    Assert_true(!msg->length);

    Bits_memcpy(pf->myAddr.key, conn.publicKey, 32);
    Address_getPrefix(&pf->myAddr);
    pf->myAddr.path = 1;

    // begin

    pf->registry = DHTModuleRegistry_new(pf->alloc);
    ReplyModule_register(pf->registry, pf->alloc);

    pf->rumorMill = RumorMill_new(pf->alloc, &pf->myAddr, RUMORMILL_CAPACITY, pf->log, "extern");

    pf->nodeStore = NodeStore_new(&pf->myAddr, pf->alloc, pf->base, pf->log, pf->rumorMill);

    if (pf->pub.fullVerify) {
        NodeStore_setFullVerify(pf->nodeStore, true);
    }

    pf->nodeStore->onBestPathChange = onBestPathChange;
    pf->nodeStore->onBestPathChangeCtx = pf;

    struct RouterModule* routerModule = RouterModule_register(pf->registry,
                                                              pf->alloc,
                                                              pf->myAddr.key,
                                                              pf->base,
                                                              pf->log,
                                                              pf->rand,
                                                              pf->nodeStore);

    pf->searchRunner = SearchRunner_new(pf->nodeStore,
                                        pf->log,
                                        pf->base,
                                        routerModule,
                                        pf->myAddr.ip6.bytes,
                                        pf->rumorMill,
                                        pf->alloc);

    pf->janitor = Janitor_new(routerModule,
                              pf->nodeStore,
                              pf->searchRunner,
                              pf->rumorMill,
                              pf->log,
                              pf->alloc,
                              pf->base,
                              pf->rand);

    EncodingSchemeModule_register(pf->registry, pf->log, pf->alloc);

    SerializationModule_register(pf->registry, pf->log, pf->alloc);

    DHTModuleRegistry_register(&pf->dhtModule, pf->registry);

    pf->router = Router_new(routerModule, pf->nodeStore, pf->searchRunner, pf->alloc);

    // Now the admin stuff...
    if (pf->admin) {
        NodeStore_admin_register(pf->nodeStore, pf->admin, pf->alloc);
        RouterModule_admin_register(routerModule, pf->router, pf->admin, pf->alloc);
        SearchRunner_admin_register(pf->searchRunner, pf->admin, pf->alloc);
        Janitor_admin_register(pf->janitor, pf->admin, pf->alloc);
    }

    pf->state = Pathfinder_pvt_state_RUNNING;

    return NULL;
}
Example #4
0
int main(int argc, char** argv)
{
    #ifdef Log_KEYS
        fprintf(stderr, "Log_LEVEL = KEYS, EXPECT TO SEE PRIVATE KEYS IN YOUR LOGS!\n");
    #endif
    Crypto_init();
    Assert_true(argc > 0);

    if (argc == 2) {
        // one argument
        if (strcmp(argv[1], "--help") == 0) {
            return usage(argv[0]);
        } else if (strcmp(argv[1], "--genconf") == 0) {
            return genconf();
        } else if (strcmp(argv[1], "--pidfile") == 0) {
            // Performed after reading the configuration
        } else if (strcmp(argv[1], "--reconf") == 0) {
            // Performed after reading the configuration
        } else if (strcmp(argv[1], "--bench") == 0) {
            return benchmark();
        } else if (strcmp(argv[1], "--version") == 0) {
            printf("Version ID: %s\n", RouterModule_gitVersion());
            return 0;
        } else {
            fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[1]);
            fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
            return -1;
        }
    } else if (argc >  2) {
        // more than one argument?
        fprintf(stderr, "%s: too many arguments\n", argv[0]);
        fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
        return -1;
    }

    if (isatty(STDIN_FILENO)) {
        // We were started from a terminal
        // The chances an user wants to type in a configuration
        // bij hand are pretty slim so we show him the usage
        return usage(argv[0]);
    } else {
        // We assume stdin is a configuration file and that we should
        // start routing
    }

    struct event_base* eventBase = event_base_new();

    // Allow it to allocate 4MB
    struct Allocator* allocator = MallocAllocator_new(1<<22);
    struct Reader* reader = FileReader_new(stdin, allocator);
    Dict config;
    if (JsonBencSerializer_get()->parseDictionary(reader, allocator, &config)) {
        fprintf(stderr, "Failed to parse configuration.\n");
        return -1;
    }

    // Logging.
    struct Writer* logwriter = FileWriter_new(stdout, allocator);
    struct Log* logger = &(struct Log) { .writer = logwriter };


    // pid file
    String* pidFile = Dict_getString(&config, String_CONST("pidFile"));
    if (pidFile) {
        if (argc == 2 && strcmp(argv[1], "--pidfile") == 0) {
            printf("%s", pidFile->bytes);
            return 0;
        }
        Log_info(logger, "Writing pid of process to [%s].\n", pidFile->bytes);
        FILE* pf = fopen(pidFile->bytes, "w");
        if (!pf) {
            Log_critical(logger,
                          "Failed to open pid file [%s] for writing, errno=%d\n",
                          pidFile->bytes,
                          errno);
            return -1;
        }
        fprintf(pf, "%d", (int) getpid());
        fclose(pf);
    }

    // re-configure
    if (argc == 2 && strcmp(argv[1], "--reconf") == 0) {
        reconf(eventBase, &config, logger, allocator);
        return 0;
    }

    // ca, needed for admin.
    struct Address myAddr;
    uint8_t privateKey[32];
    parsePrivateKey(&config, &myAddr, privateKey);
    struct CryptoAuth* cryptoAuth =
        CryptoAuth_new(&config, allocator, privateKey, eventBase, logger);

    // Admin
    char* user = setUser(Dict_getList(&config, String_CONST("security")));
    struct Admin* admin = newAdmin(&config, user, logger, eventBase, allocator);

    struct SwitchCore* switchCore = SwitchCore_new(logger, allocator);
    struct DHTModuleRegistry* registry = DHTModuleRegistry_new(allocator);
    ReplyModule_register(registry, allocator);

    // Router
    struct Interface* routerIf = NULL;
    Dict* routerConf = Dict_getDict(&config, String_CONST("router"));
    Dict* iface = Dict_getDict(routerConf, String_CONST("interface"));
    if (String_equals(Dict_getString(iface, String_CONST("type")), String_CONST("TUNInterface"))) {
        String* ifName = Dict_getString(iface, String_CONST("tunDevice"));

        char assignedTunName[TUNConfigurator_IFNAMSIZ];
        void* tunPtr = TUNConfigurator_initTun(((ifName) ? ifName->bytes : NULL),
                                               assignedTunName,
                                               logger,
                                               AbortHandler_INSTANCE);
        struct Jmp jmp;
        Jmp_try(jmp) {
            TUNConfigurator_setIpAddress(
                assignedTunName, myAddr.ip6.bytes, 8, logger, &jmp.handler);
        } Jmp_catch {
            Log_warn(logger, "Unable to configure ip address [%s]", jmp.message);
        }

        struct TUNInterface* tun = TUNInterface_new(tunPtr, eventBase, allocator);
        routerIf = &tun->iface;

    }
Example #5
0
/*
 * This process is started with 2 parameters, they must all be numeric in base 10.
 * toAngel the pipe which is used to send data back to the angel process.
 * fromAngel the pipe which is used to read incoming data from the angel.
 *
 * Upon initialization, this process will wait for an initial configuration to be sent to
 * it and then it will send an initial response.
 */
int Core_main(int argc, char** argv)
{
    struct Except* eh = NULL;

    if (argc != 3) {
        Except_raise(eh, -1, "This is internal to cjdns and shouldn't started manually.");
    }

    struct Allocator* alloc = MallocAllocator_new(ALLOCATOR_FAILSAFE);
    struct Log* preLogger = FileWriterLog_new(stderr, alloc);
    struct EventBase* eventBase = EventBase_new(alloc);

    // -------------------- Setup the Pre-Logger ---------------------- //
    struct Log* logger = IndirectLog_new(alloc);
    IndirectLog_set(logger, preLogger);

    // -------------------- Setup the PRNG ---------------------- //
    struct Random* rand = LibuvEntropyProvider_newDefaultRandom(eventBase, logger, eh, alloc);

    // -------------------- Change Canary Value ---------------------- //
    MallocAllocator_setCanary(alloc, (long)Random_int64(rand));
    struct Allocator* tempAlloc = Allocator_child(alloc);


    // The first read inside of getInitialConfig() will begin it waiting.
    struct Pipe* angelPipe = Pipe_named(argv[2], eventBase, eh, alloc);
    angelPipe->logger = logger;
    angelPipe->onClose = angelDied;

    struct Interface* angelIface = FramingInterface_new(65535, &angelPipe->iface, alloc);

    Dict* config = getInitialConfig(angelIface, eventBase, tempAlloc, eh);

    struct Hermes* hermes = Hermes_new(angelIface, eventBase, logger, alloc);

    String* privateKeyHex = Dict_getString(config, String_CONST("privateKey"));
    Dict* adminConf = Dict_getDict(config, String_CONST("admin"));
    String* pass = Dict_getString(adminConf, String_CONST("pass"));
    String* bind = Dict_getString(adminConf, String_CONST("bind"));
    if (!(pass && privateKeyHex && bind)) {
        if (!pass) {
            Except_raise(eh, -1, "Expected 'pass'");
        }
        if (!bind) {
            Except_raise(eh, -1, "Expected 'bind'");
        }
        if (!privateKeyHex) {
            Except_raise(eh, -1, "Expected 'privateKey'");
        }
        Except_raise(eh, -1, "Expected 'pass', 'privateKey' and 'bind' in configuration.");
    }
    Log_keys(logger, "Starting core with admin password [%s]", pass->bytes);
    uint8_t privateKey[32];
    if (privateKeyHex->len != 64
        || Hex_decode(privateKey, 32, (uint8_t*) privateKeyHex->bytes, 64) != 32)
    {
        Except_raise(eh, -1, "privateKey must be 64 bytes of hex.");
    }

    struct Sockaddr_storage bindAddr;
    if (Sockaddr_parse(bind->bytes, &bindAddr)) {
        Except_raise(eh, -1, "bind address [%s] unparsable", bind->bytes);
    }

    struct AddrInterface* udpAdmin =
        UDPAddrInterface_new(eventBase, &bindAddr.addr, alloc, eh, logger);

    struct Admin* admin = Admin_new(udpAdmin, alloc, logger, eventBase, pass);

    char* boundAddr = Sockaddr_print(udpAdmin->addr, tempAlloc);
    Dict adminResponse = Dict_CONST(
        String_CONST("bind"), String_OBJ(String_CONST(boundAddr)), NULL
    );
    Dict response = Dict_CONST(
        String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST(
        String_CONST("admin"), Dict_OBJ(&adminResponse), NULL
    ));
    // This always times out because the angel doesn't respond.
    Hermes_callAngel(&response, angelResponse, NULL, alloc, eh, hermes);

    // --------------------- Setup the Logger --------------------- //
    Dict* logging = Dict_getDict(config, String_CONST("logging"));
    String* logTo = Dict_getString(logging, String_CONST("logTo"));
    if (logTo && String_equals(logTo, String_CONST("stdout"))) {
        // do nothing, continue logging to stdout.
    } else {
        struct Log* adminLogger = AdminLog_registerNew(admin, alloc, rand);
        IndirectLog_set(logger, adminLogger);
        logger = adminLogger;
    }

    // CryptoAuth
    struct Address addr;
    parsePrivateKey(privateKey, &addr, eh);
    struct CryptoAuth* cryptoAuth = CryptoAuth_new(alloc, privateKey, eventBase, logger, rand);

    struct Sockaddr* myAddr = Sockaddr_fromBytes(addr.ip6.bytes, Sockaddr_AF_INET6, alloc);

    struct SwitchCore* switchCore = SwitchCore_new(logger, alloc);
    struct DHTModuleRegistry* registry = DHTModuleRegistry_new(alloc);
    ReplyModule_register(registry, alloc);

    // Router
    struct RouterModule* router = RouterModule_register(registry,
                                                        alloc,
                                                        addr.key,
                                                        eventBase,
                                                        logger,
                                                        admin,
                                                        rand);

    SerializationModule_register(registry, logger, alloc);

    struct IpTunnel* ipTun = IpTunnel_new(logger, eventBase, alloc, rand, hermes);

    struct Ducttape* dt = Ducttape_register(privateKey,
                                            registry,
                                            router,
                                            switchCore,
                                            eventBase,
                                            alloc,
                                            logger,
                                            admin,
                                            ipTun,
                                            rand);

    struct SwitchPinger* sp =
        SwitchPinger_new(&dt->switchPingerIf, eventBase, logger, alloc);

    // Interfaces.
    struct InterfaceController* ifController =
        DefaultInterfaceController_new(cryptoAuth,
                                       switchCore,
                                       router,
                                       logger,
                                       eventBase,
                                       sp,
                                       rand,
                                       alloc);

    // ------------------- Register RPC functions ----------------------- //
    SwitchPinger_admin_register(sp, admin, alloc);
    UDPInterface_admin_register(eventBase, alloc, logger, admin, ifController);
#ifdef HAS_ETH_INTERFACE
    ETHInterface_admin_register(eventBase, alloc, logger, admin, ifController);
#endif
    RouterModule_admin_register(router, admin, alloc);
    AuthorizedPasswords_init(admin, cryptoAuth, alloc);
    Admin_registerFunction("ping", adminPing, admin, false, NULL, admin);
    Core_admin_register(myAddr, dt, logger, ipTun, alloc, admin, eventBase);
    Security_admin_register(alloc, logger, admin);
    IpTunnel_admin_register(ipTun, admin, alloc);

    struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
        .allocator = alloc,
        .admin = admin,
        .logger = logger,
        .hermes = hermes
    }));
Example #6
0
struct TestFramework* TestFramework_setUp(char* privateKey,
        struct Allocator* allocator,
        struct Log* logger)
{
    if (!logger) {
        struct Writer* logwriter = FileWriter_new(stdout, allocator);
        logger = WriterLog_new(logwriter, allocator);
    }

    struct Random* rand = Random_new(allocator, logger, NULL);
    struct EventBase* base = EventBase_new(allocator);

    uint64_t pks[4];
    if (!privateKey) {
        Random_longs(rand, pks, 4);
        privateKey = (char*)pks;
    }

    uint8_t* publicKey = Allocator_malloc(allocator, 32);
    crypto_scalarmult_curve25519_base(publicKey, (uint8_t*)privateKey);

    struct Address* myAddress = Allocator_calloc(allocator, sizeof(struct Address), 1);
    Bits_memcpyConst(myAddress->key, publicKey, 32);
    AddressCalc_addressForPublicKey(myAddress->ip6.bytes, publicKey);

    struct SwitchCore* switchCore = SwitchCore_new(logger, allocator);
    struct CryptoAuth* ca = CryptoAuth_new(allocator, (uint8_t*)privateKey, base, logger, rand);

    struct DHTModuleRegistry* registry = DHTModuleRegistry_new(allocator);
    ReplyModule_register(registry, allocator);

    struct NodeStore* nodeStore = NodeStore_new(myAddress, 128, allocator, logger, rand);

    struct RouterModule* routerModule =
        RouterModule_register(registry, allocator, publicKey, base, logger, rand, nodeStore);

    struct SearchRunner* searchRunner =
        SearchRunner_new(nodeStore, logger, base, routerModule, myAddress->ip6.bytes, allocator);

    SerializationModule_register(registry, logger, allocator);

    struct IpTunnel* ipTun = IpTunnel_new(logger, base, allocator, rand, NULL);

    struct Ducttape* dt =
        Ducttape_register((uint8_t*)privateKey, registry, routerModule, searchRunner,
                          switchCore, base, allocator, logger, ipTun, rand);

    struct SwitchPinger* sp = SwitchPinger_new(&dt->switchPingerIf, base, rand, logger, allocator);

    // Interfaces.
    struct InterfaceController* ifController =
        DefaultInterfaceController_new(ca,
                                       switchCore,
                                       routerModule,
                                       logger,
                                       base,
                                       sp,
                                       rand,
                                       allocator);

    struct TestFramework* tf = Allocator_clone(allocator, (&(struct TestFramework) {
        .alloc = allocator,
         .rand = rand,
          .eventBase = base,
           .logger = logger,
            .switchCore = switchCore,
             .ducttape = dt,
              .cryptoAuth = ca,
               .router = routerModule,
                .switchPinger = sp,
                 .ifController = ifController,
                  .publicKey = publicKey,
                   .ip = myAddress->ip6.bytes
    }));
void testSearch(struct DHTMessage** outMessagePtr,
                struct RouterModule* routerModule,
                struct DHTModuleRegistry* registry,
                struct Allocator* allocator)
{
    *outMessagePtr = NULL;

    #define REQUEST_HASH "\xfc\x01\x01\x01\x01\x01\x01\x01\x21\x01\x01\x01\x01\x01\x01\x01"

    struct DHTMessage* callbackMessage = NULL;

    RouterModule_beginSearch((uint8_t*) REQUEST_HASH,
                             testSearch_callback,
                             &callbackMessage,
                             routerModule);

    struct DHTMessage* outMessage = *outMessagePtr;
    assert(outMessage != NULL);

    // Need to be able to work around the fact that the string contains nulls.
    #define EXPECTED_OUTPUT(tid) \
        "d"                                     \
          "1:q" "2:fn"                          \
          "3:tar" "16:" REQUEST_HASH            \
          "4:txid" "2:" tid                     \
        "e"

    for (uint32_t i = 0; i < (uint32_t) outMessage->length; i++) {
      //printf("%.2X", (unsigned int) outMessage->bytes[i] & 0xFF);
    }
    //printf("\n%s\n", outMessage->bytes);
    //printf("\n%s\n", outMessage->peerAddress);

    assert(outMessage->length == strlen(EXPECTED_OUTPUT("xx")));
    assert(memcmp(outMessage->bytes, EXPECTED_OUTPUT("8\x00"), outMessage->length) == 0);
    //assert(strcmp(outMessage->address->networkAddress, " 00014  ") == 0);
    // In a normal DHT, 00014 is the closest node, however, 00011 has sent us a message in
    // testQuery() and thus his reach is 1 and he beats all other nodes which are 0-reach.
    // Search queries are allowed to select nodes which are further from the target than us.
    assert(strcmp((char*) &outMessage->address->networkAddress_be, " 00011  ") == 0);

    #undef EXPECTED_OUTPUT

    #define CRAFTED_REPLY(tid) \
        "d"                                                    \
          "1:n" "200:"                                         \
            "97bkjs8qpd5hc1mubj3qbfyqzmzxp3rg" " 00017  "      \
            "by1szn122nqk1vncjtm612444rlh6ztr" " 00018  "      \
            "u42wbyr0wznhkbqr1r7u627dwsvb8853" " 00019  "      \
            "97bkjs8qpd5hc1mubj3qbfyqzmzxp3rg" " 00020  "      \
            "2lr8w01hhrxqng8mm8nf3nlwh5nyxzyl" " 00021  "      \
          "4:txid" "2:" tid                                    \
        "e"

    struct Address address = {
        .key = "ponmlkjihgzyxwvutsrq           \0"
    };
    memcpy(&address.networkAddress_be, " 00011  ", 8);

    struct DHTMessage message =
    {
        .length = strlen(CRAFTED_REPLY("xx")),
        .allocator = allocator,
        .address = &address
    };
    memcpy(message.bytes, CRAFTED_REPLY("8\x00"), message.length);
   // memcpy(message.peerAddress, peerAddress, 18);

    *outMessagePtr = NULL;

    DHTModules_handleIncoming(&message, registry);

    // Make sure the callback was called.
    assert(callbackMessage != NULL);

    // Make sure the node was promoted for it's fine service :P
    struct Address addr;
    memset(&addr, 0, sizeof(struct Address));
    memcpy(&addr.key, "ponmlkjihgzyxwvutsrq           \0", 32);
    struct Node* node1 =
        NodeStore_getNode(routerModule->nodeStore, &addr);
    //printf("node reach = %d", node1->reach);
    assert(node1->reach == 1601894175);

 /*   outMessage = *outMessagePtr;
    assert(outMessage != NULL);

    assert(strcmp("000022", outMessage->peerAddress) == 0);*/
}

int main()
{
    char buffer[1<<20];
    struct Allocator* allocator = BufferAllocator_new(buffer, 1<<20);
    struct DHTModuleRegistry* registry = DHTModules_new(allocator);

    ReplyModule_register(registry, allocator);
    struct RouterModule* routerModule =
        RouterModule_register(registry, allocator, (uint8_t*) MY_ADDRESS, event_base_new(), NULL);

    SerializationModule_register(registry, allocator);

    struct DHTMessage* outMessage;
    // dummy "network module" which just catches outgoing messages and makes them available.
    TestFramework_registerOutputCatcher(&outMessage, registry, allocator);

    struct Address addr;

    // damn this \0, was a mistake but to fix it would break all of the hashes :(
    #define ADD_NODE(address, netAddr) \
        memset(&addr, 0, sizeof(struct Address));                             \
        memcpy(&addr.networkAddress_be, netAddr "  ", 8);                     \
        memcpy(&addr.key, (uint8_t*) address "           \0", 32);            \
        RouterModule_addNode(&addr, routerModule)

//                                             most significant byte --vv
    ADD_NODE("qponmlkjihgzyxwvutsr", " 00001"); // fce8:573b:d230:ca3b 1c4e:f9d6 0632:9445
    ADD_NODE("bcdefghijklmnopqrstu", " 00002"); // fc65:9f4c:c061:84f9 2018:6e31 de3d:3bcf
    ADD_NODE("onmlkjihgzyxwvutsrqp", " 00003"); // fcbe:26ce:5c7a:9a0f 205b:358c b8f8:08bb
//                               search target --> fc01:0101:0101:0101 2101:0101 0101:0101
    ADD_NODE("mlkjihgzyxwvutsrqpon", " 00004"); // fc08:d8e6:e000:c95c 2192:d676 94f9:63a7
    ADD_NODE("lkjihgzyxwvutsrqponm", " 00005"); // fc7c:6c8d:e5ee:cf99 2f16:06c7 95ca:0c0b
    ADD_NODE("fghijklmnopqrstuvwxy", " 00006"); // fcac:3963:cbd1:6390 3e83:be89 a23f:ce66
    ADD_NODE("jihgzyxwvutsrqponmlk", " 00007"); // fc2e:3a5e:5e47:9769 4964:8f7f 3894:8c07
    ADD_NODE("kjihgzyxwvutsrqponml", " 00008"); // fc37:10aa:39ed:12bf 4a70:1507 dbe9:a054
    ADD_NODE("cdefghijklmnopqrstuv", " 00009"); // fcaa:113e:88da:d432 65f0:1c14 38d9:b656
//                                   this node --> fc39:c3ba:c711:00aa 666d:90b0 1ab6:e8c3
    ADD_NODE("rqponmlkjihgzyxwvuts", " 00010"); // fc43:41e7:2adc:d13b 78ce:1959 e4cc:c76e
    ADD_NODE("ponmlkjihgzyxwvutsrq", " 00011"); // fc83:2ab3:b65b:9ad1 7e7b:f61f e0fa:cb40
    ADD_NODE("efghijklmnopqrstuvwx", " 00012"); // fc08:0ba6:a8e2:7731 9dae:f9fd e502:767c
    ADD_NODE("abcdefghijklmnopqrst", " 00013"); // fc81:cab3:eda0:61aa 9fff:bdde 0168:f0dd
    ADD_NODE("ihgzyxwvutsrqponmlkj", " 00014"); // fc49:8fc7:7e43:981a bac1:0b5d 77fb:8818
    ADD_NODE("nmlkjihgzyxwvutsrqpo", " 00015"); // fc69:61a1:2bec:1444 bb9e:47d1 f8b3:a6a0
    ADD_NODE("defghijklmnopqrstuvw", " 00016"); // fc40:1d18:89a6:9a7e c8af:20fd 5c9f:8140
    ADD_NODE("ghijklmnopqrstuvwxyz", " 00017"); // fc74:0f2e:d77a:e5e7 cf4e:8fe9 7791:98e1


    #undef ADD_NODE

    testQuery(&outMessage, registry, allocator);
    testSearch(&outMessage, routerModule, registry, allocator);

    return 0;
}