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 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 DHTModuleRegistry_register(struct DHTModule* module, struct DHTModuleRegistry* registry) { registry->members = Allocator_realloc(registry->allocator, registry->members, sizeof(char*) * (registry->memberCount + 2)); registry->members[registry->memberCount] = module; registry->memberCount++; registry->members[registry->memberCount] = NULL; return 0; }
Bool Vector_reserve(Vector *v, size_t capacity, Allocator allocator) { char *new_data; if (v->capacity >= capacity) { return True; } capacity *= 2; new_data = Allocator_realloc(allocator, v->data, capacity); if (!new_data) { return False; } v->data = new_data; v->capacity = capacity; return True; }
struct EncodingScheme* EncodingScheme_deserialize(String* data, struct Allocator* alloc) { struct EncodingScheme_Form* forms = NULL; int outCount = 0; uint64_t block = 0; int bits = 0; int dataIndex = 0; for (;;) { // load data into the block from the incoming data source while (bits < 56 && dataIndex < (int)data->len) { block |= (((uint64_t)data->bytes[dataIndex++] & 0xff) << bits); bits += 8; } struct EncodingScheme_Form next; int ret = decodeForm(&next, block); bits -= ret; if (!ret || bits < 0) { if (block || dataIndex < (int)data->len || bits < 0) { // Invalid encoding return NULL; } break; } block >>= ret; Assert_true((next.prefix >> next.prefixLen) == 0); outCount += 1; forms = Allocator_realloc(alloc, forms, outCount * sizeof(struct EncodingScheme_Form)); Bits_memcpyConst(&forms[outCount-1], &next, sizeof(struct EncodingScheme_Form)); } struct EncodingScheme* out = Allocator_clone(alloc, (&(struct EncodingScheme) { .forms = forms, .count = outCount }));
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; }