static void search(Dict* args, void* vctx, String* txid, struct Allocator* reqAlloc) { struct Context* ctx = Identity_check((struct Context*) vctx); String* addrStr = Dict_getStringC(args, "ipv6"); int maxRequests = -1; uint64_t* maxRequestsPtr = Dict_getIntC(args, "maxRequests"); if (maxRequestsPtr) { maxRequests = *maxRequestsPtr; } uint8_t addr[16]; if (AddrTools_parseIp(addr, (uint8_t*) addrStr->bytes)) { Dict* resp = Dict_new(reqAlloc); Dict_putStringCC(resp, "error", "ipv6 invalid", reqAlloc); Admin_sendMessage(resp, txid, ctx->admin); } else { struct Allocator* alloc = Allocator_child(ctx->allocator); struct Search* s = Allocator_calloc(alloc, sizeof(struct Search), 1); s->promise = SearchRunner_search(addr, maxRequests, maxRequests, ctx->runner, alloc); s->ctx = ctx; s->txid = String_clone(txid, alloc); s->alloc = alloc; Identity_set(s); if (!s->promise) { Dict* resp = Dict_new(reqAlloc); Dict_putStringCC(resp, "error", "creating search", reqAlloc); Admin_sendMessage(resp, txid, ctx->admin); Allocator_free(alloc); return; } s->promise->userData = s; s->promise->callback = searchResponse; } }
static void dumpRumorMill(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* ctx = Identity_check((struct Context*) vcontext); Dict* out = Dict_new(requestAlloc); struct RumorMill* rm = getRumorMill(ctx, Dict_getString(args, String_CONST("mill"))); if (!rm) { Dict_putString(out, String_CONST("error"), String_CONST("mill must be one of " "[externalMill,linkMill,nodeMill,dhtMill,splitMill]"), requestAlloc); Admin_sendMessage(out, txid, ctx->admin); return; } int64_t* page = Dict_getInt(args, String_CONST("page")); int ctr = (page) ? *page * ENTRIES_PER_PAGE : 0; List* table = List_new(requestAlloc); for (int i = 0; i < ENTRIES_PER_PAGE && ctr < rm->count; i++) { String* addr = Address_toString(&rm->addresses[ctr++], requestAlloc); List_addString(table, addr, requestAlloc); } Dict_putList(out, String_CONST("addresses"), table, requestAlloc); Dict_putInt(out, String_CONST("total"), rm->count, requestAlloc); Admin_sendMessage(out, txid, ctx->admin); }
static void newInterface2(struct Context* ctx, struct Sockaddr* addr, String* txid) { struct Allocator* const alloc = Allocator_child(ctx->allocator); struct UDPInterface* udpIf = NULL; struct Jmp jmp; Jmp_try(jmp) { udpIf = UDPInterface_new(ctx->eventBase, addr, alloc, &jmp.handler, ctx->logger, ctx->ic); } Jmp_catch { String* errStr = String_CONST(jmp.message); Dict out = Dict_CONST(String_CONST("error"), String_OBJ(errStr), NULL); Admin_sendMessage(&out, txid, ctx->admin); Allocator_free(alloc); } // sizeof(struct UDPInterface*) the size of a pointer. ctx->ifaces = Allocator_realloc(ctx->allocator, ctx->ifaces, sizeof(struct UDPInterface*) * (ctx->ifCount + 1)); ctx->ifaces[ctx->ifCount] = udpIf; Dict out = Dict_CONST( String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST( String_CONST("interfaceNumber"), Int_OBJ(ctx->ifCount), NULL )); Admin_sendMessage(&out, txid, ctx->admin); ctx->ifCount++; }
static void newInterface2(struct Context* ctx, struct Sockaddr* addr, String* txid, struct Allocator* requestAlloc) { struct Allocator* const alloc = Allocator_child(ctx->alloc); struct UDPAddrIface* udpIf = NULL; struct Jmp jmp; Jmp_try(jmp) { udpIf = UDPAddrIface_new(ctx->eventBase, addr, alloc, &jmp.handler, ctx->logger); } Jmp_catch { String* errStr = String_CONST(jmp.message); Dict out = Dict_CONST(String_CONST("error"), String_OBJ(errStr), NULL); Admin_sendMessage(&out, txid, ctx->admin); Allocator_free(alloc); return; } struct AddrIface* ai = ctx->udpIf = &udpIf->generic; struct InterfaceController_Iface* ici = InterfaceController_newIface(ctx->ic, String_CONST("UDP"), alloc); Iface_plumb(&ici->addrIf, &ai->iface); Dict* out = Dict_new(requestAlloc); Dict_putString(out, String_CONST("error"), String_CONST("none"), requestAlloc); Dict_putInt(out, String_CONST("interfaceNumber"), ici->ifNum, requestAlloc); char* printedAddr = Sockaddr_print(ai->addr, requestAlloc); Dict_putString(out, String_CONST("bindAddress"), String_CONST(printedAddr), requestAlloc); Admin_sendMessage(out, txid, ctx->admin); }
static void searchResponse(struct RouterModule_Promise* promise, uint32_t lag, struct Address* from, Dict* responseDict) { struct Search* search = Identity_check((struct Search*) promise->userData); struct Allocator* alloc = Allocator_child(search->alloc); Dict* resp = Dict_new(alloc); if (!from) { Dict_putStringCC(resp, "error", "none", alloc); Dict_putIntC(resp, "complete", 1, alloc); Admin_sendMessage(resp, search->txid, search->ctx->admin); Allocator_free(alloc); return; } String* fromStr = Address_toString(from, alloc); Dict_putStringC(resp, "from", fromStr, alloc); Dict_putIntC(resp, "ms", lag, alloc); struct Address_List* addrs = ReplySerializer_parse(from, responseDict, NULL, true, alloc); List* nodes = List_new(alloc); for (int i = 0; addrs && i < addrs->length; i++) { String* addr = Address_toString(&addrs->elems[i], alloc); List_addString(nodes, addr, alloc); } Dict_putListC(resp, "nodes", nodes, alloc); Admin_sendMessage(resp, search->txid, search->ctx->admin); }
static void handleRequestFromChild(struct Admin* admin, uint8_t buffer[MAX_API_REQUEST_SIZE], size_t amount, struct Allocator* allocator) { String* txid = NULL; int skip = 0; if (!memcmp(buffer, "0123", 4)) { // out of band txid txid = &(String) { .len = 4, .bytes = (char*) buffer + 4 }; skip = 8; } struct Reader* reader = ArrayReader_new(buffer + skip, amount - skip, allocator); Dict message; if (List_getStandardBencSerializer()->parseDictionary(reader, allocator, &message)) { return; } String* query = Dict_getString(&message, CJDHTConstants_QUERY); if (!query) { return; } // If they're asking for a cookie then lets give them one. String* cookie = BSTR("cookie"); if (String_equals(query, cookie)) { Dict* d = Dict_new(allocator); char bytes[32]; snprintf(bytes, 32, "%u", (uint32_t) Time_currentTimeSeconds(admin->eventBase)); String* theCookie = &(String) { .len = strlen(bytes), .bytes = bytes }; Dict_putString(d, cookie, theCookie, allocator); Admin_sendMessage(d, txid, admin); return; } // If this is a permitted query, make sure the cookie is right. String* auth = BSTR("auth"); bool authed = false; if (String_equals(query, auth)) { if (!authValid(&message, buffer + skip, reader->bytesRead(reader), admin)) { Dict* d = Dict_new(allocator); Dict_putString(d, BSTR("error"), BSTR("Auth failed."), allocator); Admin_sendMessage(d, txid, admin); return; } query = Dict_getString(&message, BSTR("aq")); authed = true; } for (int i = 0; i < admin->functionCount; i++) { if (String_equals(query, admin->functions[i].name) && (authed || !admin->functions[i].needsAuth)) { admin->functions[i].call(&message, admin->functions[i].context, txid); } } return; }
static void subscribe(Dict* args, void* vcontext, String* txid) { struct AdminLog* log = (struct AdminLog*) vcontext; String* levelName = Dict_getString(args, String_CONST("level")); enum Log_Level level = (levelName) ? Log_levelForName(levelName->bytes) : Log_Level_DEBUG; int64_t* lineNumPtr = Dict_getInt(args, String_CONST("line")); String* fileStr = Dict_getString(args, String_CONST("file")); const char* file = (fileStr && fileStr->len > 0) ? fileStr->bytes : NULL; char* error = "2+2=5"; if (level == Log_Level_INVALID) { level = Log_Level_KEYS; } if (lineNumPtr && *lineNumPtr < 0) { error = "Invalid line number, must be positive or 0 to signify any line is acceptable."; } else if (log->subscriptionCount >= MAX_SUBSCRIPTIONS) { error = "Max subscription count reached."; } else { struct Subscription* sub = &log->subscriptions[log->subscriptionCount]; sub->level = level; sub->alloc = Allocator_child(log->alloc); if (file) { int i; for (i = 0; i < FILE_NAME_COUNT; i++) { if (log->fileNames[i] && !strcmp(log->fileNames[i], file)) { file = log->fileNames[i]; sub->internalName = true; break; } } if (i == FILE_NAME_COUNT) { file = String_new(file, sub->alloc)->bytes; sub->internalName = false; } } sub->file = file; sub->lineNum = (lineNumPtr) ? *lineNumPtr : 0; sub->txid = String_clone(txid, sub->alloc); Random_bytes(log->rand, (uint8_t*) sub->streamId, 8); uint8_t streamIdHex[20]; Hex_encode(streamIdHex, 20, sub->streamId, 8); Dict response = Dict_CONST( String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST( String_CONST("streamId"), String_OBJ(String_CONST((char*)streamIdHex)), NULL )); Admin_sendMessage(&response, txid, log->admin); log->subscriptionCount++; return; } Dict response = Dict_CONST( String_CONST("error"), String_OBJ(String_CONST(error)), NULL ); Admin_sendMessage(&response, txid, log->admin); }
static void sessionStats(Dict* args, void* vcontext, String* txid, struct Allocator* alloc) { struct Context* context = Identity_check((struct Context*) vcontext); int64_t* handleP = Dict_getInt(args, String_CONST("handle")); uint32_t handle = *handleP; struct SessionManager_Session* session = SessionManager_sessionForHandle(handle, context->sm); Dict* r = Dict_new(alloc); if (!session) { Dict_putString(r, String_CONST("error"), String_CONST("no such session"), alloc); Admin_sendMessage(r, txid, context->admin); return; } uint8_t printedAddr[40]; AddrTools_printIp(printedAddr, session->caSession->herIp6); Dict_putString(r, String_CONST("ip6"), String_new(printedAddr, alloc), alloc); String* state = String_new(CryptoAuth_stateString(CryptoAuth_getState(session->caSession)), alloc); Dict_putString(r, String_CONST("state"), state, alloc); struct ReplayProtector* rp = &session->caSession->replayProtector; Dict_putInt(r, String_CONST("duplicates"), rp->duplicates, alloc); Dict_putInt(r, String_CONST("lostPackets"), rp->lostPackets, alloc); Dict_putInt(r, String_CONST("receivedOutOfRange"), rp->receivedOutOfRange, alloc); struct Address addr; Bits_memcpyConst(addr.key, session->caSession->herPublicKey, 32); addr.path = session->sendSwitchLabel; addr.protocolVersion = session->version; Dict_putString(r, String_CONST("addr"), Address_toString(&addr, alloc), alloc); Dict_putString(r, String_CONST("publicKey"), Key_stringify(session->caSession->herPublicKey, alloc), alloc); Dict_putInt(r, String_CONST("version"), session->version, alloc); Dict_putInt(r, String_CONST("handle"), session->receiveHandle, alloc); Dict_putInt(r, String_CONST("sendHandle"), session->sendHandle, alloc); Dict_putInt(r, String_CONST("timeOfLastIn"), session->timeOfLastIn, alloc); Dict_putInt(r, String_CONST("timeOfLastOut"), session->timeOfLastOut, alloc); Dict_putString(r, String_CONST("deprecation"), String_CONST("publicKey,version will soon be removed"), alloc); Admin_sendMessage(r, txid, context->admin); return; }
static void sessionStats(Dict* args, void* vcontext, String* txid, struct Allocator* alloc) { struct Context* context = vcontext; int64_t* handleP = Dict_getInt(args, String_CONST("handle")); uint32_t handle = *handleP; struct SessionManager_Session* session = SessionManager_sessionForHandle(handle, context->sm); uint8_t* ip6 = SessionManager_getIp6(handle, context->sm); Dict* r = Dict_new(alloc); if (!session) { Dict_putString(r, String_CONST("error"), String_CONST("no such session"), alloc); Admin_sendMessage(r, txid, context->admin); return; } // both or neither Assert_true(ip6); uint8_t printedAddr[40]; AddrTools_printIp(printedAddr, ip6); Dict_putString(r, String_CONST("ip6"), String_new(printedAddr, alloc), alloc); Dict_putString(r, String_CONST("state"), String_new(CryptoAuth_stateString(session->cryptoAuthState), alloc), alloc); struct ReplayProtector* rp = CryptoAuth_getReplayProtector(session->internal); Dict_putInt(r, String_CONST("duplicates"), rp->duplicates, alloc); Dict_putInt(r, String_CONST("lostPackets"), rp->lostPackets, alloc); Dict_putInt(r, String_CONST("receivedOutOfRange"), rp->receivedOutOfRange, alloc); uint8_t* key = CryptoAuth_getHerPublicKey(session->internal); Dict_putString(r, String_CONST("publicKey"), Key_stringify(key, alloc), alloc); Dict_putInt(r, String_CONST("version"), session->version, alloc); Dict_putInt(r, String_CONST("handle"), Endian_bigEndianToHost32(session->receiveHandle_be), alloc); Dict_putInt(r, String_CONST("sendHandle"), Endian_bigEndianToHost32(session->sendHandle_be), alloc); Dict_putInt(r, String_CONST("timeOfLastIn"), session->timeOfLastIn, alloc); Dict_putInt(r, String_CONST("timeOfLastOut"), session->timeOfLastOut, alloc); Admin_sendMessage(r, txid, context->admin); return; }
static void adminFunc(Dict* input, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* ctx = vcontext; ctx->called = true; Dict d = Dict_CONST(String_CONST("called!"), Int_OBJ(1), NULL); Admin_sendMessage(&d, txid, ctx->framework->admin); }
static void bytesAllocated(Dict* in, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Allocator_admin_pvt* ctx = Identity_check((struct Allocator_admin_pvt*)vcontext); Dict* d = Dict_new(requestAlloc); Dict_putIntC(d, "bytes", Allocator_bytesAllocated(ctx->alloc), requestAlloc); Admin_sendMessage(d, txid, ctx->admin); }
static void addServer(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* context = vcontext; struct Allocator* alloc = Allocator_child(context->alloc); String* addrStr = Dict_getString(args, String_CONST("addr")); int ret; struct Sockaddr_storage ss; char* err = "none"; if (Sockaddr_parse(addrStr->bytes, &ss)) { err = "could not parse address"; } else if ((ret = RainflyClient_addServer(context->rainfly, &ss.addr))) { if (ret == RainflyClient_addServer_WRONG_ADDRESS_TYPE) { err = "RainflyClient_addServer_WRONG_ADDRESS_TYPE"; } else { err = "unknown error"; } } Dict* response = Dict_new(alloc); Dict_putString(response, String_CONST("error"), String_CONST(err), alloc); Admin_sendMessage(response, txid, context->admin); Allocator_free(alloc); }
static void adminResetPeering(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* context = Identity_check((struct Context*)vcontext); String* pubkeyString = Dict_getStringC(args, "pubkey"); int error = 0; char* errorMsg = NULL; if (pubkeyString) { // parse the key uint8_t pubkey[32]; uint8_t addr[16]; error = Key_parse(pubkeyString, pubkey, addr); if (error) { errorMsg = "bad key"; } else { InterfaceController_resetPeering(context->ic, pubkey); } } else { // reset all InterfaceController_resetPeering(context->ic, NULL); } Dict* response = Dict_new(requestAlloc); Dict_putIntC(response, "success", error ? 0 : 1, requestAlloc); if (error) { Dict_putStringCC(response, "error", errorMsg, requestAlloc); } Admin_sendMessage(response, txid, context->admin); }
static void adminPingOnResponse(struct SwitchPinger_Response* resp, void* vping) { struct Allocator* pingAlloc = resp->ping->pingAlloc; struct Ping* ping = vping; Dict* rd = Dict_new(pingAlloc); if (resp->res == SwitchPinger_Result_LABEL_MISMATCH) { uint8_t path[20] = {0}; AddrTools_printPath(path, resp->label); String* pathStr = String_new(path, pingAlloc); Dict_putString(rd, String_CONST("rpath"), pathStr, pingAlloc); } Dict_putInt(rd, String_CONST("version"), resp->version, pingAlloc); Dict_putInt(rd, String_CONST("ms"), resp->milliseconds, pingAlloc); Dict_putString(rd, String_CONST("result"), SwitchPinger_resultString(resp->res), pingAlloc); Dict_putString(rd, String_CONST("path"), ping->path, pingAlloc); if (resp->data) { Dict_putString(rd, String_CONST("data"), resp->data, pingAlloc); } if (!Bits_isZero(resp->key, 32)) { Dict_putString(rd, String_CONST("key"), Key_stringify(resp->key, pingAlloc), pingAlloc); } Admin_sendMessage(rd, ping->txid, ping->context->admin); }
static void getUser(Dict* args, void* vctx, String* txid, struct Allocator* requestAlloc) { struct Context* const ctx = Identity_check((struct Context*) vctx); String* user = Dict_getStringC(args, "user"); Dict* ret = Security_getUser((user) ? user->bytes : NULL, requestAlloc); Admin_sendMessage(ret, txid, ctx->admin); }
static void adminInterfaces(Dict* args, void* vcontext, String* txid, struct Allocator* alloc) { struct Context* context = Identity_check((struct Context*)vcontext); int64_t* page = Dict_getIntC(args, "page"); int i = (page) ? *page * ENTRIES_PER_PAGE : 0; int count = InterfaceController_ifaceCount(context->ic); //int count = InterfaceController_getIface(context->ic, alloc, &stats); List* list = List_new(alloc); for (int counter = 0; i < count && counter++ < ENTRIES_PER_PAGE; i++) { struct InterfaceController_Iface* iface = InterfaceController_getIface(context->ic, i); Dict* d = Dict_new(alloc); Dict_putIntC(d, "ifNum", iface->ifNum, alloc); Dict_putStringC(d, "name", iface->name, alloc); char* bs = InterfaceController_beaconStateString(iface->beaconState); Dict_putStringCC(d, "beaconState", bs, alloc); List_addDict(list, d, alloc); } Dict* resp = Dict_new(alloc); Dict_putListC(resp, "ifaces", list, alloc); Dict_putIntC(resp, "total", count, alloc); if (i < count) { Dict_putIntC(resp, "more", 1, alloc); } Admin_sendMessage(resp, txid, context->admin); }
static void getHandles(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* context = Identity_check((struct Context*) vcontext); struct Allocator* alloc = Allocator_child(context->alloc); int64_t* page = Dict_getInt(args, String_CONST("page")); int i = (page) ? *page * ENTRIES_PER_PAGE : 0; struct SessionManager_HandleList* hList = SessionManager_getHandleList(context->sm, alloc); List* list = List_new(alloc); for (int counter = 0; i < hList->length && counter++ < ENTRIES_PER_PAGE; i++) { List_addInt(list, hList->handles[i], alloc); } Dict* r = Dict_new(alloc); Dict_putList(r, String_CONST("handles"), list, alloc); Dict_putInt(r, String_CONST("total"), hList->length, alloc); String* more = String_CONST("more"); if (i < hList->length) { Dict_putInt(r, more, 1, alloc); } Admin_sendMessage(r, txid, context->admin); Allocator_free(alloc); }
static bool checkArgs(Dict* args, struct Function* func, String* txid, struct Admin* admin) { struct Dict_Entry* entry = *func->args; String* error = NULL; uint8_t buffer[1024]; struct Allocator* alloc = BufferAllocator_new(buffer, 1024); while (entry != NULL) { String* key = (String*) entry->key; Assert_true(entry->val->type == Object_DICT); Dict* value = entry->val->as.dictionary; entry = entry->next; if (*Dict_getInt(value, String_CONST("required")) == 0) { continue; } String* type = Dict_getString(value, String_CONST("type")); if ((type == STRING && !Dict_getString(args, key)) || (type == DICT && !Dict_getDict(args, key)) || (type == INTEGER && !Dict_getInt(args, key)) || (type == LIST && !Dict_getList(args, key))) { error = String_printf(alloc, "Entry [%s] is required and must be of type [%s]", key->bytes, type->bytes); break; } } if (error) { Dict d = Dict_CONST(String_CONST("error"), String_OBJ(error), NULL); Admin_sendMessage(&d, txid, admin); } return !error; }
static void addKey(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* context = vcontext; struct Allocator* alloc = Allocator_child(context->alloc); String* identStr = Dict_getString(args, String_CONST("ident")); int ret; uint8_t key[32]; char* err = "none"; if (identStr->len < 52) { err = "too short"; } else if (Base32_decode(key, 32, identStr->bytes, 52) != 32) { err = "failed to parse"; } else if ((ret = RainflyClient_addKey(context->rainfly, key))) { if (ret == RainflyClient_addKey_TOO_MANY_KEYS) { err = "RainflyClient_addKey_TOO_MANY_KEYS"; } else { err = "unknown error"; } } Dict* response = Dict_new(alloc); Dict_putString(response, String_CONST("error"), String_CONST(err), alloc); Admin_sendMessage(response, txid, context->admin); Allocator_free(alloc); }
static void adminDisconnectPeer(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* context = Identity_check((struct Context*)vcontext); String* pubkeyString = Dict_getString(args, String_CONST("pubkey")); // parse the key uint8_t pubkey[32]; uint8_t addr[16]; int error = Key_parse(pubkeyString, pubkey, addr); char* errorMsg = NULL; if (error) { errorMsg = "bad key"; } else { // try to remove the peer if the key is valid error = InterfaceController_disconnectPeer(context->ic,pubkey); if (error) { errorMsg = "no peer found for that key"; } } Dict* response = Dict_new(requestAlloc); Dict_putInt(response, String_CONST("success"), error ? 0 : 1, requestAlloc); if (error) { Dict_putString(response, String_CONST("error"), String_CONST(errorMsg), requestAlloc); } Admin_sendMessage(response, txid, context->admin); }
static void showActiveSearch(Dict* args, void* vctx, String* txid, struct Allocator* alloc) { struct Context* ctx = Identity_check((struct Context*) vctx); int number = *(Dict_getIntC(args, "number")); struct SearchRunner_SearchData* search = SearchRunner_showActiveSearch(ctx->runner, number, alloc); Dict* dict = Dict_new(alloc); // Nothing is an error Dict_putString(dict, String_new("error", alloc), String_new("none", alloc), alloc); if (number < search->activeSearches) { uint8_t target[40]; AddrTools_printIp(target, search->target); Dict_putString(dict, String_new("target", alloc), String_new((char*)target, alloc), alloc); uint8_t lastNodeAsked[60]; Address_print(lastNodeAsked, &search->lastNodeAsked); Dict_putString(dict, String_new("lastNodeAsked", alloc), String_new((char*)lastNodeAsked, alloc), alloc); Dict_putInt(dict, String_new("totalRequests", alloc), search->totalRequests, alloc); } Dict_putInt(dict, String_new("activeSearches", alloc), search->activeSearches, alloc); Admin_sendMessage(dict, txid, ctx->admin); }
static void doLog(struct Log* genericLog, enum Log_Level logLevel, const char* fullFilePath, uint32_t line, const char* format, va_list args) { struct AdminLog* log = (struct AdminLog*) genericLog; Dict* message = NULL; #define ALLOC_BUFFER_SZ 4096 uint8_t allocBuffer[ALLOC_BUFFER_SZ]; for (int i = 0; i < (int)log->subscriptionCount; i++) { if (isMatch(&log->subscriptions[i], log, logLevel, fullFilePath, line)) { if (!message) { struct Allocator* alloc = BufferAllocator_new(allocBuffer, ALLOC_BUFFER_SZ); message = makeLogMessage(&log->subscriptions[i], log, logLevel, fullFilePath, line, format, args, alloc); } int ret = Admin_sendMessage(message, log->subscriptions[i].txid, log->admin); if (ret) { removeSubscription(log, &log->subscriptions[i]); } } } }
static void lookup(Dict* args, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* ctx = vcontext; String* addrStr = Dict_getString(args, String_CONST("address")); char* err = NULL; uint8_t addr[16]; uint8_t resultBuff[60]; char* result = (char*) resultBuff; if (addrStr->len != 39) { err = "address wrong length"; } else if (AddrTools_parseIp(addr, (uint8_t*) addrStr->bytes)) { err = "failed to parse address"; } else { struct Node_Two* n = Router_lookup(ctx->router, addr); if (!n) { result = "not found"; } else if (Bits_memcmp(addr, n->address.ip6.bytes, 16)) { Address_print(resultBuff, &n->address); } else { AddrTools_printPath(resultBuff, n->address.path); } } Dict response = Dict_CONST( String_CONST("error"), String_OBJ(String_CONST((err) ? err : "none")), Dict_CONST( String_CONST("result"), String_OBJ(String_CONST(result)), NULL )); Admin_sendMessage(&response, txid, ctx->admin); }
static void getSomething(Dict* args, struct RouteGen_admin_Ctx* ctx, String* txid, struct Allocator* requestAlloc, Dict* genRoutes) { int page = getIntVal(args, String_CONST("page")); List* routes; if (getIntVal(args, String_CONST("ip6"))) { routes = Dict_getList(genRoutes, String_CONST("ipv6")); } else { routes = Dict_getList(genRoutes, String_CONST("ipv4")); } Assert_true(routes); List* outList = List_new(requestAlloc); bool more = false; for (int i = page * ROUTES_PER_PAGE, j = 0; i < List_size(routes) && j < ROUTES_PER_PAGE; j++) { String* route = List_getString(routes, i); Assert_true(route); List_addString(outList, route, requestAlloc); if (++i >= List_size(routes)) { more = false; break; } more = true; } Dict* out = Dict_new(requestAlloc); if (more) { Dict_putInt(out, String_new("more", requestAlloc), 1, requestAlloc); } Dict_putList(out, String_new("routes", requestAlloc), outList, requestAlloc); Admin_sendMessage(out, txid, ctx->admin); }
static void genericResponse(struct RouterModule_Promise* promise, uint32_t lag, struct Address* from, Dict* responseDict, String* name) { struct Ping* ping = Identity_check((struct Ping*)promise->userData); Dict* out = Dict_new(promise->alloc); String* result = (responseDict) ? name : String_CONST("timeout"); Dict_putString(out, String_CONST("result"), result, promise->alloc); if (responseDict) { struct Address_List* addrs = ReplySerializer_parse(from, responseDict, NULL, promise->alloc); List* nodes = List_new(promise->alloc); for (int i = 0; i < addrs->length; i++) { String* addr = Address_toString(&addrs->elems[i], promise->alloc); List_addString(nodes, addr, promise->alloc); } Dict_putList(out, name, nodes, promise->alloc); } Dict_putInt(out, String_CONST("ms"), lag, promise->alloc); Dict_putString(out, String_CONST("error"), String_CONST("none"), promise->alloc); Admin_sendMessage(out, ping->txid, ping->ctx->admin); }
static void sendError(char* error, String* txid, struct Admin* admin) { Dict resp = Dict_CONST( String_CONST("error"), String_OBJ(String_CONST(error)), NULL ); Admin_sendMessage(&resp, txid, admin); }
static void showConn(struct IpTunnel_Connection* conn, String* txid, struct Admin* admin, struct Allocator* alloc) { Dict* d = Dict_new(alloc); if (!Bits_isZero(conn->connectionIp6, 16)) { struct Sockaddr* addr = Sockaddr_clone(Sockaddr_LOOPBACK6, alloc); uint8_t* address; Assert_true(16 == Sockaddr_getAddress(addr, &address)); Bits_memcpy(address, conn->connectionIp6, 16); char* printedAddr = Sockaddr_print(addr, alloc); Dict_putString(d, String_CONST("ip6Address"), String_CONST(printedAddr), alloc); Dict_putInt(d, String_CONST("ip6Prefix"), conn->connectionIp6Prefix, alloc); } if (!Bits_isZero(conn->connectionIp4, 4)) { struct Sockaddr* addr = Sockaddr_clone(Sockaddr_LOOPBACK, alloc); uint8_t* address; Assert_true(4 == Sockaddr_getAddress(addr, &address)); Bits_memcpy(address, conn->connectionIp4, 4); char* printedAddr = Sockaddr_print(addr, alloc); Dict_putString(d, String_CONST("ip4Address"), String_CONST(printedAddr), alloc); Dict_putInt(d, String_CONST("ip4Prefix"), conn->connectionIp4Prefix, alloc); } Dict_putString(d, String_CONST("key"), Key_stringify(conn->routeHeader.publicKey, alloc), alloc); Dict_putInt(d, String_CONST("outgoing"), (conn->isOutgoing) ? 1 : 0, alloc); Dict_putString(d, String_CONST("error"), String_CONST("none"), alloc); Admin_sendMessage(d, txid, admin); }
static void adminMemory(Dict* input, void* vcontext, String* txid) { struct MemoryContext* context = vcontext; Dict d = Dict_CONST( String_CONST("bytes"), Int_OBJ(MallocAllocator_bytesAllocated(context->allocator)), NULL ); Admin_sendMessage(&d, txid, context->admin); }
static void sendResponse(int conn, String* txid, struct Admin* admin) { Dict resp = Dict_CONST( String_CONST("error"), String_OBJ(String_CONST("none")), Dict_CONST( String_CONST("connection"), Int_OBJ(conn), NULL )); Admin_sendMessage(&resp, txid, admin); }
static void adminExit(Dict* input, void* vcontext, String* txid, struct Allocator* requestAlloc) { struct Context* context = Identity_check((struct Context*) vcontext); Log_info(context->logger, "Got request to exit"); Dict d = Dict_CONST(String_CONST("error"), String_OBJ(String_CONST("none")), NULL); Admin_sendMessage(&d, txid, context->admin); Timeout_setTimeout(shutdown, context, 1, context->base, context->alloc); }