struct RumorMill* RumorMill_new(struct Allocator* allocator, struct Address* selfAddr, int capacity, struct Log* log, const char* name) { struct Allocator* alloc = Allocator_child(allocator); Address_getPrefix(selfAddr); struct RumorMill_pvt* rm = Allocator_calloc(alloc, sizeof(struct RumorMill_pvt), 1); rm->pub.addresses = Allocator_calloc(alloc, sizeof(struct Address), capacity); rm->capacity = capacity; rm->selfAddr = Allocator_clone(alloc, selfAddr); rm->log = log; rm->pub.name = name; Identity_set(rm); return &rm->pub; }
static struct Address* getNode(String* pathStr, struct Context* ctx, char** errOut, struct Allocator* alloc) { struct Address addr = {.path=0}; if (pathStr->len == 19 && !AddrTools_parsePath(&addr.path, pathStr->bytes)) { struct Node_Link* nl = Router_linkForPath(ctx->router, addr.path); if (!nl) { *errOut = "not_found"; return NULL; } else { Bits_memcpyConst(&addr, &nl->child->address, sizeof(struct Address)); } } else if (pathStr->len == 39 && !AddrTools_parseIp(addr.ip6.bytes, pathStr->bytes)) { struct Node_Two* n = Router_lookup(ctx->router, addr.ip6.bytes); if (!n || Bits_memcmp(addr.ip6.bytes, n->address.ip6.bytes, 16)) { *errOut = "not_found"; return NULL; } else { Bits_memcpyConst(&addr, &n->address, sizeof(struct Address)); } } else { struct Address* a = Address_fromString(pathStr, alloc); if (a) { return a; } *errOut = "parse_path"; return NULL; } return Allocator_clone(alloc, &addr); } static void pingNode(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc) { struct Context* ctx = Identity_check((struct Context*) vctx); String* pathStr = Dict_getString(args, String_CONST("path")); int64_t* timeoutPtr = Dict_getInt(args, String_CONST("timeout")); uint32_t timeout = (timeoutPtr && *timeoutPtr > 0) ? *timeoutPtr : 0; char* err = NULL; struct Address* addr = getNode(pathStr, ctx, &err, requestAlloc); if (err) { Dict errDict = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST(err)), NULL); Admin_sendMessage(&errDict, txid, ctx->admin); return; } struct RouterModule_Promise* rp = RouterModule_pingNode(addr, timeout, ctx->module, ctx->allocator); struct Ping* ping = Allocator_calloc(rp->alloc, sizeof(struct Ping), 1); Identity_set(ping); ping->txid = String_clone(txid, rp->alloc); ping->rp = rp; ping->ctx = ctx; rp->userData = ping; rp->callback = pingResponse; } static void getPeers(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc) { struct Context* ctx = Identity_check((struct Context*) vctx); String* nearbyLabelStr = Dict_getString(args, String_CONST("nearbyPath")); String* pathStr = Dict_getString(args, String_CONST("path")); int64_t* timeoutPtr = Dict_getInt(args, String_CONST("timeout")); uint32_t timeout = (timeoutPtr && *timeoutPtr > 0) ? *timeoutPtr : 0; char* err = NULL; struct Address* addr = getNode(pathStr, ctx, &err, requestAlloc); uint64_t nearbyLabel = 0; if (!err && nearbyLabelStr) { if (nearbyLabelStr->len != 19 || AddrTools_parsePath(&nearbyLabel, nearbyLabelStr->bytes)) { err = "parse_nearbyLabel"; } } if (err) { Dict errDict = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST(err)), NULL); Admin_sendMessage(&errDict, txid, ctx->admin); return; } struct RouterModule_Promise* rp = RouterModule_getPeers(addr, nearbyLabel, timeout, ctx->module, ctx->allocator); struct Ping* ping = Allocator_calloc(rp->alloc, sizeof(struct Ping), 1); Identity_set(ping); ping->txid = String_clone(txid, rp->alloc); ping->rp = rp; ping->ctx = ctx; rp->userData = ping; rp->callback = getPeersResponse; } static void findNode(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc) { struct Context* ctx = Identity_check((struct Context*) vctx); String* nodeToQueryStr = Dict_getString(args, String_CONST("nodeToQuery")); String* targetStr = Dict_getString(args, String_CONST("target")); int64_t* timeoutPtr = Dict_getInt(args, String_CONST("timeout")); uint32_t timeout = (timeoutPtr && *timeoutPtr > 0) ? *timeoutPtr : 0; char* err = NULL; struct Address* nodeToQuery = getNode(nodeToQueryStr, ctx, &err, requestAlloc); uint8_t target[16]; if (!err) { if (targetStr->len != 39 || AddrTools_parseIp(target, targetStr->bytes)) { err = "parse_target"; } } if (err) { Dict errDict = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST(err)), NULL); Admin_sendMessage(&errDict, txid, ctx->admin); return; } struct RouterModule_Promise* rp = RouterModule_findNode(nodeToQuery, target, timeout, ctx->module, ctx->allocator); struct Ping* ping = Allocator_calloc(rp->alloc, sizeof(struct Ping), 1); Identity_set(ping); ping->txid = String_clone(txid, rp->alloc); ping->rp = rp; ping->ctx = ctx; rp->userData = ping; rp->callback = findNodeResponse; } void RouterModule_admin_register(struct RouterModule* module, struct Router* router, struct Admin* admin, struct Allocator* alloc) { // for improved reporting alloc = Allocator_child(alloc); struct Context* ctx = Allocator_clone(alloc, (&(struct Context) { .admin = admin, .allocator = alloc, .module = module, .router = router }));
static struct Address* createAddress(int mostSignificantAddressSpaceByte, int* hops) { uint64_t path = getPath(hops); struct Address address = { .path = 0 }; if (!genKeys) { if ((int)(sizeof(KEYS) / sizeof(*KEYS)) < (nextKey + 1)) { missingKey(); } Bits_memcpyConst(address.key, KEYS[nextKey], 32); if (AddressCalc_addressForPublicKey(address.ip6.bytes, address.key) && (mostSignificantAddressSpaceByte == -1 || address.ip6.bytes[8] == mostSignificantAddressSpaceByte)) { nextKey++; uint8_t publicKeyHex[65]; Hex_encode(publicKeyHex, 65, address.key, 32); printf("created new key: [%s]\n", publicKeyHex); address.path = path; return Allocator_clone(alloc, &address); } else { uint8_t publicKeyHex[65]; Hex_encode(publicKeyHex, 65, address.key, 32); printf("bad key: [%s]\n", publicKeyHex); if (address.ip6.ints.three) { uint8_t printedAddr[40]; AddrTools_printIp(printedAddr, address.ip6.bytes); printf("addr: [%s]\n", printedAddr); } missingKey(); } } for (;;) { Random_bytes(rand, address.key, 32); // Brute force for keys until one matches FC00:/8 if (AddressCalc_addressForPublicKey(address.ip6.bytes, address.key) && (mostSignificantAddressSpaceByte == -1 || address.ip6.bytes[8] == mostSignificantAddressSpaceByte)) { uint8_t publicKeyHex[65]; Hex_encode(publicKeyHex, 65, address.key, 32); printf("created new key: [%s]\n", publicKeyHex); address.path = path; return Allocator_clone(alloc, &address); } } } static struct Address* randomIp(int* hops) { return createAddress(-1, hops); } // This creates a random address which is a peer static struct Address* randomAddress() { return randomIp((int[]){0,1}/*0x13*/); }