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; }
/* * 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 });
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; }
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; }
/* * 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 }));
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; }