struct EncodingScheme* EncodingScheme_fromList(List* scheme, struct Allocator* alloc) { struct EncodingScheme* list = Allocator_malloc(alloc, sizeof(struct EncodingScheme)); list->count = List_size(scheme); list->forms = Allocator_malloc(alloc, sizeof(struct EncodingScheme_Form) * list->count); for (int i = 0; i < (int)list->count; i++) { Dict* form = List_getDict(scheme, i); uint64_t* prefixLen = Dict_getInt(form, String_CONST("prefixLen")); uint64_t* bitCount = Dict_getInt(form, String_CONST("bitCount")); String* prefixStr = Dict_getString(form, String_CONST("prefix")); if (!prefixLen || !bitCount || !prefixStr || prefixStr->len != 8) { return NULL; } uint32_t prefix_be; if (Hex_decode((uint8_t*)&prefix_be, 4, prefixStr->bytes, 8) != 4) { return NULL; } list->forms[i].prefixLen = *prefixLen; list->forms[i].bitCount = *bitCount; list->forms[i].prefix = Endian_bigEndianToHost32(prefix_be); } if (!EncodingScheme_isSane(list)) { return NULL; } return list; }
struct TAPDevice* TAPDevice_find(const char* preferredName, struct Except* eh, struct Allocator* alloc) { #define BUFF_SZ 0x100 char guid[BUFF_SZ] = {0}; char buff[BUFF_SZ] = {0}; if (preferredName != NULL) { snprintf(buff, sizeof(buff), "%s", preferredName); } if (get_device_guid(guid, sizeof(guid), buff, sizeof(buff), eh)) { return NULL; } struct TAPDevice* out = Allocator_malloc(alloc, sizeof(struct TAPDevice)); out->name = Allocator_malloc(alloc, CString_strlen(buff)+1); Bits_memcpy(out->name, buff, CString_strlen(buff)+1); snprintf(buff, sizeof(buff), USERMODEDEVICEDIR "%s" TAPSUFFIX, guid); out->path = Allocator_malloc(alloc, CString_strlen(buff)+1); Bits_memcpy(out->path, buff, CString_strlen(buff)+1); return out; }
static struct EncodingScheme* randomScheme(struct Random* rand, struct Allocator* alloc) { struct EncodingScheme* out = Allocator_malloc(alloc, sizeof(struct EncodingScheme)); do { out->count = Random_uint32(rand) % 32; } while (out->count < 2); out->forms = Allocator_malloc(alloc, sizeof(struct EncodingScheme_Form) * out->count); for (int i = 0; i < (int)out->count; i++) { randomForm(&out->forms[i], rand); for (int j = 0; j < i; j++) { if (out->forms[i].bitCount == out->forms[j].bitCount) { i--; break; } int minPfx = (out->forms[i].prefixLen < out->forms[j].prefixLen) ? out->forms[i].prefixLen : out->forms[j].prefixLen; if (((out->forms[j].prefix ^ out->forms[i].prefix) & ((1<<minPfx)-1)) == 0) { // collision, destroy both entries and try again. if (j != i-1) { Bits_memcpyConst(&out->forms[j], &out->forms[i-1], sizeof(struct EncodingScheme_Form)); } i -= 2; break; } } } Order_OfEncodingForms_qsort(out->forms, out->count); return out; }
/** @see BencSerializer.h */ static int32_t parseString(const struct Reader* reader, const struct Allocator* allocator, String** output) { #define OUT_OF_CONTENT_TO_READ -2 #define UNPARSABLE -3 /* Strings longer than 1*10^21-1 represent numbers definitly larger than uint64. */ #define NUMBER_MAXLENGTH 21 char number[32]; char nextChar; int ret; /* Parse the size of the string. */ size_t i = 0; for (i = 0; ; i++) { ret = reader->read(&nextChar, 1, reader); if (ret != 0) { return OUT_OF_CONTENT_TO_READ; } if (nextChar == ':') { /* Found the separator. */ break; } if (nextChar < '0' || nextChar > '9') { /* Invalid character. */ return UNPARSABLE; } if (i >= NUMBER_MAXLENGTH) { /* Massive huge number. */ return UNPARSABLE; } number[i] = nextChar; } number[i] = '\0'; size_t length = strtoul(number, NULL, 10); char* bytes = Allocator_malloc(allocator, length + 1); String* string = Allocator_malloc(allocator, sizeof(String)); /* Put a null terminator after the end so it can be treated as a normal string. */ bytes[length] = '\0'; if (reader->read(bytes, length, reader) != 0) { return OUT_OF_CONTENT_TO_READ; } string->bytes = bytes; string->len = length; *output = string; return 0; #undef OUT_OF_CONTENT_TO_READ #undef UNPARSABLE #undef NUMBER_MAXLENGTH }
static Dict* makeLogMessage(struct Subscription* subscription, struct AdminLog* logger, enum Log_Level logLevel, const char* fullFilePath, uint32_t line, const char* format, va_list vaArgs, struct Allocator* alloc) { time_t now; time(&now); Dict* out = Dict_new(alloc); char* buff = Allocator_malloc(alloc, 20); Hex_encode((uint8_t*)buff, 20, subscription->streamId, 8); Dict_putString(out, String_new("streamId", alloc), String_new(buff, alloc), alloc); Dict_putInt(out, String_new("time", alloc), now, alloc); Dict_putString(out, String_new("level", alloc), String_new(Log_nameForLevel(logLevel), alloc), alloc); const char* shortName = getShortName(fullFilePath); Dict_putString(out, String_new("file", alloc), String_new((char*)shortName, alloc), alloc); Dict_putInt(out, String_new("line", alloc), line, alloc); String* message = String_vprintf(alloc, format, vaArgs); // Strip all of the annoying \n marks in the log entries. if (message->len > 0 && message->bytes[message->len - 1] == '\n') { message->len--; } Dict_putString(out, String_new("message", alloc), message, alloc); return out; }
struct InterfaceController* InterfaceController_new(struct CryptoAuth* ca, struct SwitchCore* switchCore, struct Log* logger, struct EventBase* eventBase, struct SwitchPinger* switchPinger, struct Random* rand, struct Allocator* allocator, struct EventEmitter* ee) { struct Allocator* alloc = Allocator_child(allocator); struct InterfaceController_pvt* out = Allocator_malloc(alloc, sizeof(struct InterfaceController_pvt)); Bits_memcpy(out, (&(struct InterfaceController_pvt) { .alloc = alloc, .ca = ca, .rand = rand, .switchCore = switchCore, .logger = logger, .eventBase = eventBase, .switchPinger = switchPinger, .unresponsiveAfterMilliseconds = UNRESPONSIVE_AFTER_MILLISECONDS, .pingAfterMilliseconds = PING_AFTER_MILLISECONDS, .timeoutMilliseconds = TIMEOUT_MILLISECONDS, .forgetAfterMilliseconds = FORGET_AFTER_MILLISECONDS, .beaconInterval = BEACON_INTERVAL, .pingInterval = (switchPinger) ? Timeout_setInterval(pingCallback, out, PING_INTERVAL_MILLISECONDS, eventBase, alloc) : NULL }), sizeof(struct InterfaceController_pvt));
struct RandomSeed* RandomSeed_new(RandomSeed_Provider* providers, int providerCount, struct Log* logger, struct Allocator* alloc) { struct RandomSeed** rsList = Allocator_calloc(alloc, sizeof(struct RandomSeed), providerCount); int i = 0; for (int j = 0; j < providerCount; j++) { struct RandomSeed* rs = providers[j](alloc); if (rs) { rsList[i++] = rs; } } Assert_true(i > 0); struct RandomSeed_pvt* out = Allocator_malloc(alloc, sizeof(struct RandomSeed_pvt)); out->rsList = rsList; out->rsCount = i; out->logger = logger; out->pub.get = get; out->pub.name = "RandomSeed conglomeration of random seed providers"; Identity_set(out); return &out->pub; }
/** @see BencSerializer.h */ static int32_t parseDictionary(struct Reader* reader, struct Allocator* allocator, Dict* output) { uint8_t nextChar; readUntil('{', reader); String* key; Object* value; struct Dict_Entry* entryPointer; struct Dict_Entry* lastEntryPointer = NULL; int ret = 0; for (;;) { while (!ret) { ret = Reader_read(reader, &nextChar, 0); switch (nextChar) { case '"': break; case '}': Reader_skip(reader, 1); *output = lastEntryPointer; return 0; case '/': parseComment(reader); continue; default: Reader_skip(reader, 1); continue; } break; } if (ret) { printf("Unterminated dictionary\n"); return OUT_OF_CONTENT_TO_READ; } // Get key and value. if ((ret = parseString(reader, allocator, &key)) != 0) { return ret; } readUntil(':', reader); if ((ret = parseGeneric(reader, allocator, &value)) != 0) { return ret; } /* Allocate the entry. */ entryPointer = Allocator_malloc(allocator, sizeof(struct Dict_Entry)); entryPointer->next = lastEntryPointer; entryPointer->key = key; entryPointer->val = value; lastEntryPointer = entryPointer; } }
static inline int parseString(struct Reader* reader, struct Allocator* allocator, String** output) { #define BUFF_SZ (1<<8) #define BUFF_MAX (1<<20) int curSize = BUFF_SZ; struct Allocator* localAllocator = Allocator_child(allocator); uint8_t* buffer = Allocator_malloc(localAllocator, curSize); if (readUntil('"', reader) || Reader_read(reader, buffer, 1)) { printf("Unterminated string\n"); Allocator_free(localAllocator); return OUT_OF_CONTENT_TO_READ; } for (int i = 0; i < BUFF_MAX - 1; i++) { if (buffer[i] == '\\') { // \x01 (skip the x) Reader_skip(reader, 1); uint8_t hex[2]; if (Reader_read(reader, (char*)hex, 2)) { printf("Unexpected end of input parsing escape sequence\n"); Allocator_free(localAllocator); return OUT_OF_CONTENT_TO_READ; } int byte = Hex_decodeByte(hex[0], hex[1]); if (byte == -1) { printf("Invalid escape \"%c%c\" after \"%.*s\"\n",hex[0],hex[1],i+1,buffer); Allocator_free(localAllocator); return UNPARSABLE; } buffer[i] = (uint8_t) byte; } else if (buffer[i] == '"') { *output = String_newBinary((char*)buffer, i, allocator); Allocator_free(localAllocator); return 0; } if (i == curSize - 1) { curSize <<= 1; buffer = Allocator_realloc(localAllocator, buffer, curSize); } if (Reader_read(reader, buffer + i + 1, 1)) { if (i+1 <= 20) { printf("Unterminated string \"%.*s\"\n", i+1, buffer); } else { printf("Unterminated string starting with \"%.*s...\"\n", 20, buffer); } Allocator_free(localAllocator); return OUT_OF_CONTENT_TO_READ; } } printf("Maximum string length of %d bytes exceeded.\n",BUFF_SZ); Allocator_free(localAllocator); return UNPARSABLE; #undef BUFF_SZ #undef BUFF_MAX }
int main() { struct Allocator* alloc = MallocAllocator_new(1<<20); struct Random* rand = Random_new(alloc, NULL, NULL); // mock interface controller. struct Context ctx = { .ic = { .registerPeer = registerPeer, .getPeerState = getPeerState } }; struct Interface externalIf = { .sendMessage = sendMessage, .allocator = alloc, .senderContext = &ctx }; /*struct MultiInterface* mif = */MultiInterface_new(KEY_SIZE, &externalIf, &ctx.ic); struct Entry* entries = Allocator_malloc(alloc, sizeof(struct Entry) * ENTRY_COUNT); Random_bytes(rand, (uint8_t*)entries, ENTRY_COUNT * sizeof(struct Entry)); struct Interface** ifaces = Allocator_calloc(alloc, sizeof(char*), ENTRY_COUNT); // seed the list with some near collisions. for (int i = 0; i < 10; i++) { int rnd = (((uint32_t*)entries)[i] >> 1) % ENTRY_COUNT; ((uint32_t*) (&entries[rnd]))[0] = ((uint32_t*) (&entries[i]))[0]; } for (int i = 0; i < CYCLES; i++) { int rnd = ((uint32_t*)entries)[i] % ENTRY_COUNT; struct Entry* entry = &entries[rnd]; struct Interface* iface = ifaces[rnd]; struct Message* msg; Message_STACK(msg, 0, 128); Message_push(msg, "hello world", 12); Message_push(msg, entry, 16); externalIf.receiveMessage(msg, &externalIf); //printf("Received message for iface [%u] from [%p]\n", rnd, (void*)ctx.receivedOn); if (iface) { Assert_always(ctx.receivedOn == iface); } else { ifaces[rnd] = ctx.receivedOn; } } Allocator_free(alloc); }
/** @see BencSerializer.h */ static int32_t parseList(const struct Reader* reader, const struct Allocator* allocator, List* output) { #define OUT_OF_CONTENT_TO_READ -2 #define UNPARSABLE -3 char nextChar; if (reader->read(&nextChar, 1, reader) != 0) { return OUT_OF_CONTENT_TO_READ; } if (nextChar != 'l') { return UNPARSABLE; } Object* element; struct List_Item* thisEntry = NULL; struct List_Item** lastEntryPointer = output; int ret; if (reader->read(&nextChar, 0, reader) != 0) { return OUT_OF_CONTENT_TO_READ; } *lastEntryPointer = NULL; while (nextChar != 'e') { ret = parseGeneric(reader, allocator, &element); if (ret != 0) { return ret; } thisEntry = Allocator_malloc(allocator, sizeof(struct List_Item)); thisEntry->elem = element; /* Read backwards so that the list reads out forward. */ *lastEntryPointer = thisEntry; lastEntryPointer = &(thisEntry->next); if (reader->read(&nextChar, 0, reader) != 0) { return OUT_OF_CONTENT_TO_READ; } } if (thisEntry) { thisEntry->next = NULL; } /* move the pointer to after the 'e' at the end of the list. */ reader->skip(1, reader); return 0; #undef OUT_OF_CONTENT_TO_READ #undef UNPARSABLE }
static void handleEvent(void* vcontext) { struct UDPAddrInterface_pvt* context = (struct UDPAddrInterface_pvt*) vcontext; struct Message message = { .bytes = context->messageBuff.content, .padding = UDPAddrInterface_PADDING, .length = UDPAddrInterface_MAX_PACKET_SIZE }; struct Sockaddr_storage addrStore; int rc = Socket_recvfrom(context->socket, message.bytes, message.length, 0, &addrStore); if (rc < 0) { return; } if (addrStore.addr.addrLen != context->pub.addr->addrLen) { return; } message.length = rc; Message_push(&message, &addrStore, addrStore.addr.addrLen); if (context->pub.generic.receiveMessage) { context->pub.generic.receiveMessage(&message, &context->pub.generic); } } struct AddrInterface* UDPAddrInterface_new(struct EventBase* base, struct Sockaddr* addr, struct Allocator* allocator, struct Except* exHandler, struct Log* logger) { struct UDPAddrInterface_pvt* context = Allocator_malloc(allocator, sizeof(struct UDPAddrInterface_pvt)); Bits_memcpyConst(context, (&(struct UDPAddrInterface_pvt) { .pub = { .generic = { .sendMessage = sendMessage, .senderContext = context, .allocator = allocator }, }, .logger = logger, .socket = -1 }), sizeof(struct UDPAddrInterface_pvt));
void AuthorizedPasswords_init(struct Admin* admin, struct CryptoAuth* ca, struct Allocator* allocator) { struct Context* context = Allocator_malloc(allocator, sizeof(struct Context)); context->admin = admin; context->allocator = allocator; context->ca = ca; Admin_registerFunction("AuthorizedPasswords_add", add, context, true, ((struct Admin_FunctionArg[]){ { .name = "password", .required = 1, .type = "String" }, { .name = "user", .required = 1, .type = "String" }, { .name = "ipv6", .required = 0, .type = "String" },
int Sign_verifyMsg(uint8_t publicSigningKey[32], struct Message* msg) { if (msg->length < 64) { return -1; } struct Allocator* alloc = Allocator_child(msg->alloc); uint8_t* buff = Allocator_malloc(alloc, msg->length); unsigned long long ml = msg->length; int ret = crypto_sign_ed25519_open(buff, &ml, msg->bytes, msg->length, publicSigningKey); Allocator_free(alloc); if (ret) { return -1; } Message_pop(msg, NULL, 64, NULL); return 0; }
struct AddrInterface* AddrInterfaceAdapter_new(struct Interface* toWrap, struct Allocator* alloc) { struct AddrInterfaceAdapter_pvt* context = Allocator_malloc(alloc, sizeof(struct AddrInterfaceAdapter_pvt)); Bits_memcpyConst(context, (&(struct AddrInterfaceAdapter_pvt) { .pub = { .generic = { .sendMessage = sendMessage, .senderContext = context, .allocator = alloc } }, .wrapped = toWrap }), sizeof(struct AddrInterfaceAdapter_pvt));
static struct sock_fprog* compile(struct Filter* input, int inputLen, struct Allocator* alloc) { // compute gotos int totalOut = 0; for (int i = inputLen-1; i >= 0; i--) { struct Filter* a = &input[i]; if (a->label == 0) { // check for unresolved gotos... Assert_true(a->jt == 0 && a->jf == 0); totalOut++; continue; } int diff = 0; for (int j = i-1; j >= 0; j--) { struct Filter* b = &input[j]; if (b->label != 0) { continue; } if (b->jt == a->label) { b->sf.jt = diff; b->jt = 0; } if (b->jf == a->label) { b->sf.jf = diff; b->jf = 0; } diff++; } } // copy into output filter array... struct sock_filter* sf = Allocator_calloc(alloc, sizeof(struct sock_filter), totalOut); int outI = 0; for (int i = 0; i < inputLen; i++) { if (input[i].label == 0) { Bits_memcpyConst(&sf[outI++], &input[i].sf, sizeof(struct sock_filter)); } Assert_true(outI <= totalOut); Assert_true(i != inputLen-1 || outI == totalOut); } struct sock_fprog* out = Allocator_malloc(alloc, sizeof(struct sock_fprog)); out->len = (unsigned short) totalOut; out->filter = sf; return out; }
struct UDPInterface* UDPInterface_new(struct EventBase* base, struct Sockaddr* bindAddr, struct Allocator* allocator, struct Except* exHandler, struct Log* logger, struct InterfaceController* ic) { struct AddrInterface* udpBase = UDPAddrInterface_new(base, bindAddr, allocator, exHandler, logger); struct UDPInterface_pvt* context = Allocator_malloc(allocator, sizeof(struct UDPInterface_pvt)); Bits_memcpyConst(context, (&(struct UDPInterface_pvt) { .pub = { .addr = udpBase->addr }, .udpBase = udpBase, .logger = logger, .ic = ic }), sizeof(struct UDPInterface_pvt));
static int init(const uint8_t* privateKey, uint8_t* publicKey, const uint8_t* password) { printf("\nSetting up:\n"); struct Allocator* allocator = MallocAllocator_new(1048576); textBuff = Allocator_malloc(allocator, BUFFER_SIZE); struct Writer* logwriter = FileWriter_new(stdout, allocator); struct Log* logger = WriterLog_new(logwriter, allocator); struct Random* rand = Random_new(allocator, logger, NULL); struct EventBase* base = EventBase_new(allocator); ca1 = CryptoAuth_new(allocator, NULL, base, logger, rand); if1 = Allocator_clone(allocator, (&(struct Interface) { .sendMessage = sendMessageToIf2, .receiveMessage = recvMessageOnIf2, .allocator = allocator }));
char* ArchInfo_describe(enum ArchInfo ai, struct Allocator* alloc) { uint8_t flagBuff[archFlags_BUFF_SZ]; archFlags(ai, flagBuff); uint8_t buff[1024]; snprintf(buff, 1024, "%s %d-bit %sEndian %s", archStr(ai), ArchInfo_getBits(ai), ArchInfo_isBigEndian(ai) ? "Big" : "Little", flagBuff); int len = CString_strlen(buff); Assert_true(len < 1024); if (buff[len-1] == ' ') { buff[--len] = '\0'; } char* out = Allocator_malloc(alloc, len+1); Bits_memcpy(out, buff, len+1); return out; }
static void checkRunningInstance(struct Allocator* allocator, struct EventBase* base, String* addr, String* password, struct Log* logger, struct Except* eh) { struct Allocator* alloc = Allocator_child(allocator); struct Sockaddr_storage pingAddrStorage; if (Sockaddr_parse(addr->bytes, &pingAddrStorage)) { Except_throw(eh, "Unable to parse [%s] as an ip address port, eg: 127.0.0.1:11234", addr->bytes); } struct AdminClient* adminClient = AdminClient_new(&pingAddrStorage.addr, password, base, logger, alloc); // 100 milliseconds is plenty to wait for a process to respond on the same machine. adminClient->millisecondsToWait = 100; Dict* pingArgs = Dict_new(alloc); struct AdminClient_Promise* pingPromise = AdminClient_rpcCall(String_new("ping", alloc), pingArgs, adminClient, alloc); struct CheckRunningInstanceContext* ctx = Allocator_malloc(alloc, sizeof(struct CheckRunningInstanceContext)); ctx->base = base; ctx->alloc = alloc; ctx->res = NULL; pingPromise->callback = checkRunningInstanceCallback; pingPromise->userData = ctx; EventBase_beginLoop(base); Assert_true(ctx->res); if (ctx->res->err != AdminClient_Error_TIMEOUT) { Except_throw(eh, "Startup failed: cjdroute is already running. [%d]", ctx->res->err); } Allocator_free(alloc); }
void Core_admin_register(struct Sockaddr* ipAddr, struct Ducttape* dt, struct Log* logger, struct IpTunnel* ipTunnel, struct Allocator* alloc, struct Admin* admin, struct EventBase* eventBase) { struct Core_Context* ctx = Allocator_malloc(alloc, sizeof(struct Core_Context)); ctx->ipAddr = ipAddr; ctx->ducttape = dt; ctx->logger = logger; ctx->alloc = alloc; ctx->admin = admin; ctx->eventBase = eventBase; ctx->ipTunnel = ipTunnel; struct Admin_FunctionArg args[] = { { .name = "desiredTunName", .required = 0, .type = "String" } };
static int reconnectionNewEndpointTest(struct InterfaceController* ifController, uint8_t* pk, struct Message** fromSwitchPtr, struct Allocator* alloc, struct EventBase* eventBase, struct Log* logger, struct Interface* routerIf, struct Random* rand) { struct Message* message; struct Interface iface = { .sendMessage = messageFromInterface, .senderContext = &message, .allocator = alloc }; uint8_t* buffer = Allocator_malloc(alloc, 512); struct Message* outgoing = &(struct Message) { .length = 0, .padding = 512, .bytes = buffer + 512 }; struct CryptoAuth* externalCa = CryptoAuth_new(alloc, NULL, eventBase, logger, rand); struct Interface* wrapped = CryptoAuth_wrapInterface(&iface, pk, NULL, false, "", externalCa); CryptoAuth_setAuth(String_CONST("passwd"), 1, wrapped); struct Interface icIface = { .allocator = alloc, .sendMessage = messageFromInterface, .senderContext = &message }; InterfaceController_registerPeer(ifController, NULL, NULL, true, false, &icIface); uint8_t hexBuffer[1025]; for (int i = 0; i < 4; i++) { outgoing->length = 0; outgoing->padding = 512; outgoing->bytes = buffer + 512; Message_shift(outgoing, 12, NULL); Bits_memcpyConst(outgoing->bytes, "hello world", 12); Message_shift(outgoing, SwitchHeader_SIZE, NULL); Bits_memcpyConst(outgoing->bytes, (&(struct SwitchHeader) { .label_be = Endian_hostToBigEndian64(1), .lowBits_be = 0 }), SwitchHeader_SIZE); wrapped->sendMessage(outgoing, wrapped); *fromSwitchPtr = NULL; icIface.receiveMessage(outgoing, &icIface); message = *fromSwitchPtr; Assert_true(message); Assert_true(message->length == 24); Hex_encode(hexBuffer, 1025, message->bytes, message->length); printf("%s\n", hexBuffer); // Need to bounce the packets back when connecting after the first try. // This is needed to establish the CryptoAuth session and make the InterfaceController // merge the endpoints. if (i > 0) { // Reverse the bits to reverse the path: uint64_t path; Bits_memcpyConst(&path, message->bytes, 8); path = Bits_bitReverse64(path); Bits_memcpyConst(message->bytes, &path, 8); printf("sending back response.\n"); routerIf->receiveMessage(message, routerIf); printf("forwarding response to external cryptoAuth.\n"); iface.receiveMessage(message, &iface); printf("forwarded.\n"); } else { printf("not responding because we don't want to establish a connection yet.\n"); } } // check everything except the label Assert_true(!CString_strcmp((char*)hexBuffer+16, "0000000068656c6c6f20776f726c6400")); // check label: make sure the interface has been switched back into position 0. uint64_t label_be; Hex_decode((uint8_t*) &label_be, 8, hexBuffer, 16); uint64_t rev_label = Bits_bitReverse64(Endian_bigEndianToHost64(label_be)); // check label is decoded to 0 Assert_true(0 == NumberCompress_getDecompressed(rev_label, NumberCompress_bitsUsedForLabel(rev_label))); // check no other bits are set uint64_t out = NumberCompress_getCompressed(0, NumberCompress_bitsUsedForLabel(rev_label)); Assert_true(rev_label == out); return 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 }));
int main() { struct Allocator* mainAlloc = MallocAllocator_new(1<<20); struct Log* log = FileWriterLog_new(stdout, mainAlloc); struct Random* rand = Random_new(mainAlloc, log, NULL); struct Context* ctx = Allocator_malloc(mainAlloc, sizeof(struct Context)); Identity_set(ctx); struct Interface iface = { .sendMessage = NULL }; struct Interface* fi = FramingInterface_new(4096, &iface, mainAlloc); fi->receiveMessage = messageOut; fi->receiverContext = ctx; for (int i = 0; i < CYCLES; i++) { struct Allocator* alloc = Allocator_child(mainAlloc); // max frame size must be at least 5 so that at least 1 byte of data is sent. int maxFrameSize = ( Random_uint32(rand) % (MAX_FRAME_SZ - 1) ) + 1; int maxMessageSize = ( Random_uint32(rand) % (MAX_MSG_SZ - MIN_MSG_SZ) ) + MIN_MSG_SZ; Log_debug(log, "maxFrameSize[%d] maxMessageSize[%d]", maxFrameSize, maxMessageSize); ctx->alloc = alloc; ctx->messages = NULL; ctx->messageCount = 0; ctx->currentMessage = 0; // Create one huge message, then create lots of little frames inside of it // then split it up in random places and send the sections to the framing // interface. struct Message* msg = Message_new(WORK_BUFF_SZ, 0, alloc); Assert_true(WORK_BUFF_SZ == msg->length); Random_bytes(rand, msg->bytes, msg->length); Message_shift(msg, -WORK_BUFF_SZ, NULL); for (;;) { int len = Random_uint32(rand) % maxFrameSize; if (!len) { len++; } if (msg->padding < len + 4) { break; } Message_shift(msg, len, NULL); ctx->messageCount++; ctx->messages = Allocator_realloc(alloc, ctx->messages, ctx->messageCount * sizeof(char*)); struct Message* om = ctx->messages[ctx->messageCount-1] = Message_new(len, 0, alloc); Bits_memcpy(om->bytes, msg->bytes, len); Message_push32(msg, len, NULL); } do { int nextMessageSize = Random_uint32(rand) % maxMessageSize; if (!nextMessageSize) { nextMessageSize++; } if (nextMessageSize > msg->length) { nextMessageSize = msg->length; } struct Allocator* msgAlloc = Allocator_child(alloc); struct Message* m = Message_new(nextMessageSize, 0, msgAlloc); Message_pop(msg, m->bytes, nextMessageSize, NULL); Interface_receiveMessage(&iface, m); Allocator_free(msgAlloc); } while (msg->length); Assert_true(ctx->messageCount == ctx->currentMessage); Allocator_free(alloc); } return 0; }
/** * Parse an unknown data type. * This is not exposed to the world because it is expected that one would * know what type they are parsing to begin with. This is used by parseDictionary * and parseList to grab pieces of data which are of unknown type and parse them. * * @param reader the reader to get the stream of data from. * @param allocator the means of storing the parsed data. * @param output a pointer which will be pointed to the output. */ static int32_t parseGeneric(const struct Reader* reader, const struct Allocator* allocator, Object** output) { #define OUT_OF_CONTENT_TO_READ -2 #define UNPARSABLE -3 int ret; char firstChar; ret = reader->read(&firstChar, 0, reader); if (ret != 0) { return OUT_OF_CONTENT_TO_READ; } Object* out = Allocator_malloc(allocator, sizeof(Object)); if (firstChar <= '9' && firstChar >= '0') { /* It's a string! */ String* string = NULL; ret = parseString(reader, allocator, &string); out->type = Object_STRING; out->as.string = string; } else { switch (firstChar) { case 'i':; /* int64_t. Int is special because it is not a pointer but a int64_t. */ int64_t bint = 0; ret = parseint64_t(reader, &bint); out->type = Object_INTEGER; out->as.number = bint; break; case 'l':; /* List. */ List* list = Allocator_calloc(allocator, sizeof(List), 1); ret = parseList(reader, allocator, list); out->type = Object_LIST; out->as.list = list; break; case 'd':; /* Dictionary. */ Dict* dict = Allocator_calloc(allocator, sizeof(Dict), 1); ret = parseDictionary(reader, allocator, dict); out->type = Object_DICT; out->as.dictionary = dict; break; default: return UNPARSABLE; } } if (ret != 0) { /* Something went wrong while parsing. */ return ret; } *output = out; return 0; #undef OUT_OF_CONTENT_TO_READ #undef UNPARSABLE }
/** @see BencSerializer.h */ static int32_t parseDictionary(const struct Reader* reader, const struct Allocator* allocator, Dict* output) { #define OUT_OF_CONTENT_TO_READ -2 #define UNPARSABLE -3 char nextChar; if (reader->read(&nextChar, 1, reader) < 0) { return OUT_OF_CONTENT_TO_READ; } if (nextChar != 'd') { /* Not a dictionary. */ return UNPARSABLE; } String* key; Object* value; struct Dict_Entry* entryPointer; struct Dict_Entry* lastEntryPointer = NULL; int ret; for (;;) { /* Peek at the next char. */ if (reader->read(&nextChar, 0, reader) < 0) { /* Ran over read buffer. */ return OUT_OF_CONTENT_TO_READ; } if (nextChar == 'e') { /* Got to the end. */ break; } /* Get key and value. */ ret = parseString(reader, allocator, &key); if (ret != 0) { return ret; } ret = parseGeneric(reader, allocator, &value); if (ret != 0) { return ret; } /* Allocate the entry. */ entryPointer = Allocator_malloc(allocator, sizeof(struct Dict_Entry)); entryPointer->next = lastEntryPointer; entryPointer->key = key; entryPointer->val = value; lastEntryPointer = entryPointer; } /* We got an 'e', leave the pointer on the next char after it. */ reader->skip(1, reader); *output = lastEntryPointer; return 0; #undef OUT_OF_CONTENT_TO_READ #undef UNPARSABLE }
/** @return a string representing the address and port to connect to. */ static void initAngel(struct Pipe* asClientPipe, struct Interface* asCoreIface, char* asCorePipeName, struct EventBase* eventBase, struct Log* logger, struct Allocator* alloc, struct Random* rand) { Dict admin = Dict_CONST( String_CONST("bind"), String_OBJ(String_CONST("127.0.0.1")), Dict_CONST( String_CONST("corePipeName"), String_OBJ(String_CONST(asCorePipeName)), Dict_CONST( String_CONST("pass"), String_OBJ(String_CONST("abcd")), NULL ))); Dict message = Dict_CONST( String_CONST("admin"), Dict_OBJ(&admin), NULL ); struct Allocator* tempAlloc = Allocator_child(alloc); #define BUFFER_SZ 1023 uint8_t buff[BUFFER_SZ + 1] = {0}; struct Writer* w = ArrayWriter_new(buff, BUFFER_SZ, tempAlloc); StandardBencSerializer_get()->serializeDictionary(w, &message); struct Message* toAngel = Allocator_malloc(tempAlloc, sizeof(struct Message) + w->bytesWritten); toAngel->bytes = (uint8_t*) (&toAngel[1]); toAngel->length = toAngel->capacity = w->bytesWritten; toAngel->padding = 0; toAngel->alloc = tempAlloc; Bits_memcpy(toAngel->bytes, buff, toAngel->length); Log_info(logger, "Writing intial configuration to angel on [%s] config: [%s]", asClientPipe->name, buff); Interface_sendMessage(&asClientPipe->iface, toAngel); // This is client->angel->core data, we can throw this away. //struct Message* angelToCore = InterfaceWaiter_waitForData(asCoreIface, eventBase, tempAlloc, NULL); // unterminated string //Log_info(logger, "Init message from angel to core: [%s]", angelToCore->bytes); // Send response on behalf of core. char* coreToAngelResponse = " PADDING " "d" "5:error" "4:none" "e"; struct Message* m = &(struct Message) { .bytes = (uint8_t*) coreToAngelResponse, .length = strlen(coreToAngelResponse), .padding = 0, .capacity = strlen(coreToAngelResponse) }; Message_shift(m, -24, NULL); m = Message_clone(m, tempAlloc); Interface_sendMessage(asCoreIface, m); // This is angel->client data, it will tell us which port was bound. struct Message* angelToClient = InterfaceWaiter_waitForData(&asClientPipe->iface, eventBase, tempAlloc, NULL); printf("Response from angel to client: [%s]\n", angelToClient->bytes); Allocator_free(tempAlloc); return; }
static int32_t parseGeneric(struct Reader* reader, struct Allocator* allocator, Object** output) { int ret = 0; char firstChar; for (;;) { ret = Reader_read(reader, &firstChar, 0); switch (firstChar) { case ' ': case '\r': case '\n': case '\t': Reader_skip(reader, 1); continue; case '/':; if ((ret = parseComment(reader)) != 0) { return ret; } continue; default: break; } if (ret) { printf("Unexpected end of input\n"); return OUT_OF_CONTENT_TO_READ; } break; } Object* out = Allocator_malloc(allocator, sizeof(Object)); switch (firstChar) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':; // int64_t. Int is special because it is not a pointer but a int64_t. int64_t bint; if ((ret = parseint64_t(reader, &bint)) == UNPARSABLE) { break; } out->type = Object_INTEGER; out->as.number = bint; break; case '[':; // List. List* list = Allocator_calloc(allocator, sizeof(List), 1); ret = parseList(reader, allocator, list); out->type = Object_LIST; out->as.list = list; break; case '{':; // Dictionary Dict* dict = Allocator_calloc(allocator, sizeof(Dict), 1); ret = parseDictionary(reader, allocator, dict); out->type = Object_DICT; out->as.dictionary = dict; break; case '"':; // String String* string = NULL; ret = parseString(reader, allocator, &string); out->type = Object_STRING; out->as.string = string; break; default: printf("While looking for something to parse: " "expected one of 0 1 2 3 4 5 6 7 8 9 [ { \", found '%c'\n", firstChar); return UNPARSABLE; } if (ret != 0) { // Something went wrong while parsing. return ret; } *output = out; return 0; }
static uint8_t receiveMessage(struct Message* msg, struct Iface* iface) { struct Allocator* alloc = iface->receiverContext; if (msg->length < 20) { printf("runt\n"); return 0; } // ethernet padding. Message_shift(msg, -2, NULL); uint8_t from[13]; uint8_t to[13]; Hex_encode(from, 13, msg->bytes, 6); Message_shift(msg, -6, NULL); Hex_encode(to, 13, msg->bytes, 6); Message_shift(msg, -6, NULL); uint8_t type[5]; Hex_encode(type, 5, msg->bytes, 2); Message_shift(msg, -2, NULL); int subsubtype = -1; int subtype = -1; // int typeCode = -1; if (!Bits_memcmp(type, "86dd", 4)) { Bits_memcpy(type, "ipv6", 5); subtype = msg->bytes[6]; // typeCode = 6; if (subtype == 58) { subsubtype = msg->bytes[40]; } } else if (!Bits_memcmp(type, "0800", 4)) { return 0; Bits_memcpy(type, "ipv4", 5); subtype = msg->bytes[9]; // typeCode = 4; } else { return 0; } // 6000000000183aff0000000000000000000000000000000fff0200000000000000000001ff000018 870 //6000000000201101fd000000000000000000000000000001ff020000000000000000000000010003 eee914... //6000000000083aff00000000000000000000000000000000ff020000000000000000000000000002 85007b //6000000000203aff fd000000000000000000000000000001 ff0200000000000000000001ff000002 8700. int len = msg->length * 2 + 1; uint8_t* buff = Allocator_malloc(alloc, len + 2); Hex_encode(buff, len, msg->bytes, msg->length); /* if (typeCode == 6 && len > 86) { Bits_memmove(&buff[82], &buff[81], len - 81); Bits_memmove(&buff[49], &buff[48], len - 48); Bits_memmove(&buff[17], &buff[16], len - 16); buff[80] = buff[48] = buff[16] = ' '; }*/ if (msg->length > 45) { Bits_memcpy(buff+86, "...", 4); } printf("[%s] [%s] [%s] [%02d] [%03d] [%s]\n", to, from, type, subtype, subsubtype, buff); return 0; }
static uint8_t sendMessage(struct Message* message, struct Interface* iface) { struct PacketHeaderToUDPAddrInterface_pvt* context = Identity_check((struct PacketHeaderToUDPAddrInterface_pvt*) iface); struct Sockaddr_storage ss; Message_pop(message, &ss, context->pub.addr->addrLen, NULL); struct Sockaddr* addr = &ss.addr; struct Headers_UDPHeader udp; udp.srcPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(context->pub.addr)); udp.destPort_be = Endian_hostToBigEndian16(Sockaddr_getPort(addr)); udp.length_be = Endian_hostToBigEndian16(message->length + Headers_UDPHeader_SIZE); udp.checksum_be = 0; Message_push(message, &udp, sizeof(struct Headers_UDPHeader), NULL); struct Headers_IP6Header ip = { .nextHeader = 17, .hopLimit = 255, }; ip.payloadLength_be = Endian_hostToBigEndian16(message->length); Headers_setIpVersion(&ip); uint8_t* addrPtr = NULL; Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16); Bits_memcpyConst(ip.destinationAddr, addrPtr, 16); Assert_true(Sockaddr_getAddress(context->pub.addr, &addrPtr) == 16); Bits_memcpyConst(ip.sourceAddr, addrPtr, 16); uint16_t checksum = Checksum_udpIp6(ip.sourceAddr, message->bytes, message->length); ((struct Headers_UDPHeader*)message->bytes)->checksum_be = checksum; Message_push(message, &ip, sizeof(struct Headers_IP6Header), NULL); return Interface_sendMessage(context->wrapped, message); } static uint8_t receiveMessage(struct Message* message, struct Interface* iface) { struct PacketHeaderToUDPAddrInterface_pvt* context = Identity_check((struct PacketHeaderToUDPAddrInterface_pvt*) iface->receiverContext); if (message->length < Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE) { // runt return Error_NONE; } struct Headers_IP6Header* ip = (struct Headers_IP6Header*) message->bytes; // udp if (ip->nextHeader != 17) { return Error_NONE; } struct Allocator* alloc = Allocator_child(message->alloc); struct Sockaddr* addr = Sockaddr_clone(context->pub.addr, alloc); uint8_t* addrPtr = NULL; Assert_true(Sockaddr_getAddress(addr, &addrPtr) == 16); Bits_memcpyConst(addrPtr, ip->sourceAddr, 16); struct Headers_UDPHeader* udp = (struct Headers_UDPHeader*) (&ip[1]); Sockaddr_setPort(addr, Endian_bigEndianToHost16(udp->srcPort_be)); if (Sockaddr_getPort(context->pub.addr) != Endian_bigEndianToHost16(udp->destPort_be)) { // not the right port return Error_NONE; } Message_shift(message, -(Headers_IP6Header_SIZE + Headers_UDPHeader_SIZE), NULL); Message_push(message, addr, addr->addrLen, NULL); return Interface_receiveMessage(&context->pub.generic, message); } struct AddrInterface* PacketHeaderToUDPAddrInterface_new(struct Interface* toWrap, struct Allocator* alloc, struct Sockaddr* addr) { struct PacketHeaderToUDPAddrInterface_pvt* context = Allocator_malloc(alloc, sizeof(struct PacketHeaderToUDPAddrInterface_pvt)); Bits_memcpyConst(context, (&(struct PacketHeaderToUDPAddrInterface_pvt) { .pub = { .generic = { .sendMessage = sendMessage, .senderContext = context, .allocator = alloc } }, .wrapped = toWrap }), sizeof(struct PacketHeaderToUDPAddrInterface_pvt));