static uint8_t sendTo(struct Message* msg, struct Interface* iface) { struct TestFramework_Link* link = Identity_cast((struct TestFramework_Link*)iface->senderContext); struct Interface* dest; struct TestFramework* srcTf; if (&link->destIf == iface) { dest = &link->srcIf; srcTf = link->dest; } else if (&link->srcIf == iface) { dest = &link->destIf; srcTf = link->src; } else { Assert_always(false); } printf("Transferring message to [%p] - message length [%d]\n", (void*)dest, msg->length); // Store the original message and a copy of the original so they can be compared later. srcTf->lastMsgBackup = Message_clone(msg, srcTf->alloc); srcTf->lastMsg = msg; if (msg->alloc) { // If it's a message which was buffered inside of CryptoAuth then it will be freed // so by adopting the allocator we can hold it in memory. Allocator_adopt(srcTf->alloc, msg->alloc); } // Copy the original and send that to the other end. struct Message* sendMsg = Message_clone(msg, dest->allocator); return dest->receiveMessage(sendMsg, dest); }
static Iface_DEFUN sendTo(struct Message* msg, struct Iface* dest, struct TestFramework* srcTf, struct TestFramework* destTf) { Assert_true(!((uintptr_t)msg->bytes % 4) || !"alignment fault"); Assert_true(!(msg->capacity % 4) || !"length fault"); Assert_true(((int)msg->capacity >= msg->length) || !"length fault0"); Log_debug(srcTf->logger, "Transferring message to [%p] - message length [%d]\n", (void*)dest, msg->length); // Store the original message and a copy of the original so they can be compared later. srcTf->lastMsgBackup = Message_clone(msg, srcTf->alloc); srcTf->lastMsg = msg; if (msg->alloc) { // If it's a message which was buffered inside of CryptoAuth then it will be freed // so by adopting the allocator we can hold it in memory. Allocator_adopt(srcTf->alloc, msg->alloc); } // Copy the original and send that to the other end. // Can't use Iface_next() when not sending the original msg. struct Message* sendMsg = Message_clone(msg, destTf->alloc); Iface_send(dest, sendMsg); return 0; }
// This is directly called from SwitchCore, message is not encrypted. static uint8_t sendFromSwitch(struct Message* msg, struct Interface* switchIf) { struct InterfaceController_Peer* ep = Identity_check((struct InterfaceController_Peer*) switchIf); ep->bytesOut += msg->length; struct InterfaceController_pvt* ic = ifcontrollerForPeer(ep); uint8_t ret; uint64_t now = Time_currentTimeMilliseconds(ic->eventBase); if (now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) { // TODO(cjd): This is a hack because if the time of last message exceeds the // unresponsive time, we need to send back an error and that means // mangling the message which would otherwise be in the queue. struct Allocator* tempAlloc = Allocator_child(ic->allocator); struct Message* toSend = Message_clone(msg, tempAlloc); ret = Interface_sendMessage(ep->cryptoAuthIf, toSend); Allocator_free(tempAlloc); } else { ret = Interface_sendMessage(ep->cryptoAuthIf, msg); } // If this node is unresponsive then return an error. if (ret || now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) { return ret ? ret : Error_UNDELIVERABLE; } else { /* Way way way too much noise Log_debug(ic->logger, "Sending to neighbor, last message from this node was [%u] ms ago.", (now - ep->timeOfLastMessage)); */ } return Error_NONE; }
/** * If we don't know her key, the handshake has to be done backwards. * Reverse handshake requests are signaled by sending a non-obfuscated zero nonce. */ static uint8_t genReverseHandshake(struct Message* message, struct Wrapper* wrapper, union Headers_CryptoAuth* header) { wrapper->nextNonce = 0; Message_shift(message, -Headers_CryptoAuth_SIZE); // Buffer the packet so it can be sent ASAP if (wrapper->bufferedMessage == NULL) { Log_debug(wrapper->context->logger, "Buffered a message.\n"); wrapper->bufferedMessage = Message_clone(message, wrapper->externalInterface.allocator); assert(wrapper->nextNonce == 0); } else { Log_debug(wrapper->context->logger, "Expelled a message because a session has not yet been setup.\n"); Message_copyOver(wrapper->bufferedMessage, message, wrapper->externalInterface.allocator); assert(wrapper->nextNonce == 0); } wrapper->hasBufferedMessage = true; Message_shift(message, Headers_CryptoAuth_SIZE); header = (union Headers_CryptoAuth*) message->bytes; header->nonce = UINT32_MAX; message->length = Headers_CryptoAuth_SIZE; // sessionState must be 0, auth and 24 byte nonce are garbaged and public key is set // now garbage the authenticator and the encrypted key which are not used. randombytes((uint8_t*) &header->handshake.authenticator, 48); return wrapper->wrappedInterface->sendMessage(message, wrapper->wrappedInterface); }
/** * If we don't know her key, the handshake has to be done backwards. * Reverse handshake requests are signaled by sending a non-obfuscated zero nonce. */ static uint8_t genReverseHandshake(struct Message* message, struct CryptoAuth_Wrapper* wrapper, union Headers_CryptoAuth* header) { reset(wrapper); Message_shift(message, -Headers_CryptoAuth_SIZE, NULL); // Buffer the packet so it can be sent ASAP if (wrapper->bufferedMessage != NULL) { // Not exactly a drop but a message is not going to reach the destination. cryptoAuthDebug0(wrapper, "DROP Expelled a message because a session has not yet been setup"); Allocator_free(wrapper->bufferedMessage->alloc); } cryptoAuthDebug0(wrapper, "Buffered a message"); struct Allocator* bmalloc = Allocator_child(wrapper->externalInterface.allocator); wrapper->bufferedMessage = Message_clone(message, bmalloc); Assert_ifParanoid(wrapper->nextNonce == 0); Message_shift(message, Headers_CryptoAuth_SIZE, NULL); header = (union Headers_CryptoAuth*) message->bytes; header->nonce = UINT32_MAX; message->length = Headers_CryptoAuth_SIZE; // sessionState must be 0, auth and 24 byte nonce are garbaged and public key is set // now garbage the authenticator and the encrypted key which are not used. Random_bytes(wrapper->context->rand, (uint8_t*) &header->handshake.authenticator, 48); // This is a special packet which the user should never see. Headers_setSetupPacket(&header->handshake.auth, 1); return wrapper->wrappedInterface->sendMessage(message, wrapper->wrappedInterface); }
static void sendConfToCore(struct Interface* toCoreInterface, struct Allocator* tempAlloc, Dict* config, struct Except* eh, struct Log* logger) { #define CONFIG_BUFF_SIZE 1024 uint8_t buff[CONFIG_BUFF_SIZE + 32] = {0}; uint8_t* start = buff + 32; struct Writer* writer = ArrayWriter_new(start, CONFIG_BUFF_SIZE - 33, tempAlloc); if (StandardBencSerializer_get()->serializeDictionary(writer, config)) { Except_raise(eh, -1, "Failed to serialize pre-configuration for core."); } struct Message* m = &(struct Message) { .bytes = start, .length = writer->bytesWritten, .padding = 32 }; m = Message_clone(m, tempAlloc); Log_keys(logger, "Sent [%d] bytes to core [%s].", m->length, m->bytes); toCoreInterface->sendMessage(m, toCoreInterface); } static void setUser(char* user, struct Log* logger, struct Except* eh) { struct Jmp jmp; Jmp_try(jmp) { Security_setUser(user, logger, &jmp.handler); } Jmp_catch { if (jmp.code == Security_setUser_PERMISSION) { return; } Except_raise(eh, jmp.code, "%s", jmp.message); } } static struct Pipe* getClientPipe(int argc, char** argv, struct EventBase* base, struct Except* eh, struct Allocator* alloc) { int inFromClientNo; int outToClientNo; if (argc < 4 || (inFromClientNo = atoi(argv[2])) == 0) { inFromClientNo = STDIN_FILENO; } if (argc < 4 || (outToClientNo = atoi(argv[3])) == 0) { outToClientNo = STDOUT_FILENO; } // named pipe. if (argc > 2 && inFromClientNo == STDIN_FILENO) { return Pipe_named(argv[2], base, eh, alloc); } return Pipe_forFiles(inFromClientNo, outToClientNo, base, eh, alloc); }
static uint8_t recvMessageOnIf1(struct Message* message, struct Interface* iface) { if1Messages++; fputs("if1 got message! ", stdout); fwrite(message->bytes, 1, message->length, stdout); puts(""); if1Msg = Message_clone(message, iface->allocator)->bytes; return Error_NONE; }
static uint8_t receiveMessage(struct Message* message, struct Interface* iface) { struct Context* ctx = iface->receiverContext; ctx->message = Message_clone(message, ctx->alloc); Timeout_clearTimeout(ctx->timeout); event_base_loopbreak(ctx->eventBase); return 0; }
// This is directly called from SwitchCore, message is not encrypted. static uint8_t sendFromSwitch(struct Message* msg, struct Interface* switchIf) { struct IFCPeer* ep = Identity_cast((struct IFCPeer*) switchIf); ep->bytesOut += msg->length; // This sucks but cryptoauth trashes the content when it encrypts // and we need to be capable of sending back a coherent error message. uint8_t top[255]; uint8_t* messageBytes = msg->bytes; uint16_t padding = msg->padding; uint16_t len = (msg->length < 255) ? msg->length : 255; Bits_memcpy(top, msg->bytes, len); struct Context* ic = ifcontrollerForPeer(ep); uint8_t ret; uint64_t now = Time_currentTimeMilliseconds(ic->eventBase); if (now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) { // XXX: This is a hack because if the time of last message exceeds the // unresponsive time, we need to send back an error and that means // mangling the message which would otherwise be in the queue. struct Allocator* tempAlloc = Allocator_child(ic->allocator); struct Message* toSend = Message_clone(msg, tempAlloc); ret = Interface_sendMessage(ep->cryptoAuthIf, toSend); Allocator_free(tempAlloc); } else { ret = Interface_sendMessage(ep->cryptoAuthIf, msg); } // If this node is unresponsive then return an error. if (ret || now - ep->timeOfLastMessage > ic->unresponsiveAfterMilliseconds) { msg->bytes = messageBytes; msg->padding = padding; msg->length = len; Bits_memcpy(msg->bytes, top, len); return ret ? ret : Error_UNDELIVERABLE; } else { /* Way way way too much noise Log_debug(ic->logger, "Sending to neighbor, last message from this node was [%u] ms ago.", (now - ep->timeOfLastMessage)); */ } return Error_NONE; }
static Iface_DEFUN incomingFromPathfinder(struct Message* msg, struct Iface* iface) { struct Pathfinder* pf = Identity_containerOf(iface, struct Pathfinder, iface); struct EventEmitter_pvt* ee = Identity_check((struct EventEmitter_pvt*) pf->ee); if (msg->length < 4) { Log_debug(ee->log, "DROPPF runt"); return NULL; } enum PFChan_Pathfinder ev = Message_pop32(msg, NULL); Message_push32(msg, pf->pathfinderId, NULL); Message_push32(msg, ev, NULL); if (ev <= PFChan_Pathfinder__TOO_LOW || ev >= PFChan_Pathfinder__TOO_HIGH) { Log_debug(ee->log, "DROPPF invalid type [%d]", ev); return NULL; } if (!PFChan_Pathfinder_sizeOk(ev, msg->length)) { Log_debug(ee->log, "DROPPF incorrect length[%d] for type [%d]", msg->length, ev); return NULL; } if (pf->state == Pathfinder_state_DISCONNECTED) { if (ev != PFChan_Pathfinder_CONNECT) { Log_debug(ee->log, "DROPPF disconnected and event != CONNECT event:[%d]", ev); return NULL; } } else if (pf->state != Pathfinder_state_CONNECTED) { Log_debug(ee->log, "DROPPF error state"); return NULL; } if (handleFromPathfinder(ev, msg, ee, pf)) { return NULL; } struct ArrayList_Ifaces* handlers = getHandlers(ee, ev, false); if (!handlers) { return NULL; } for (int i = 0; i < handlers->length; i++) { struct Message* messageClone = Message_clone(msg, msg->alloc); struct Iface* iface = ArrayList_Ifaces_get(handlers, i); // We have to call this manually because we don't have an interface handy which is // actually plumbed with this one. Assert_true(iface); Assert_true(iface->send); Iface_CALL(iface->send, messageClone, iface); } return NULL; }
int main(int argc, char** argv) { struct Allocator* alloc = MallocAllocator_new(1<<20); struct EventBase* base = EventBase_new(alloc); struct Writer* logWriter = FileWriter_new(stdout, alloc); struct Log* logger = WriterLog_new(logWriter, alloc); // mock interface controller. struct InterfaceController ic = { .registerPeer = registerPeer }; struct Sockaddr_storage addr; Assert_always(!Sockaddr_parse("127.0.0.1", &addr)); struct UDPInterface* udpA = UDPInterface_new(base, &addr.addr, alloc, NULL, logger, &ic); struct UDPInterface* udpB = UDPInterface_new(base, &addr.addr, alloc, NULL, logger, &ic); struct Message* msg; Message_STACK(msg, 0, 128); Message_push(msg, "Hello World", 12, NULL); Message_push(msg, udpA->addr, udpA->addr->addrLen, NULL); struct Interface* ifA = &((struct UDPInterface_pvt*) udpA)->udpBase->generic; struct Interface* ifB = &((struct UDPInterface_pvt*) udpB)->udpBase->generic; ifA->receiveMessage = receiveMessageA; ifB->receiveMessage = receiveMessageB; ifB->receiverContext = alloc; struct Allocator* child = Allocator_child(alloc); msg = Message_clone(msg, child); ifB->sendMessage(msg, ifB); Allocator_free(child); Timeout_setTimeout(fail, NULL, 1000, base, alloc); EventBase_beginLoop(base); return 0; }
static void sendMessage(struct TwoNodes* tn, char* message, struct TestFramework* from, struct TestFramework* to) { struct Message* msg; Message_STACK(msg, 64, 512); Bits_memcpy(msg->bytes, message, CString_strlen(message) + 1); msg->length = CString_strlen(message) + 1; TestFramework_craftIPHeader(msg, from->ip, to->ip); msg = Message_clone(msg, from->alloc); struct Iface* fromIf; if (from == tn->nodeA) { fromIf = &tn->tunA; } else if (from == tn->nodeB) { fromIf = &tn->tunB; } else { Assert_true(false); } TUNMessageType_push(msg, Ethernet_TYPE_IP6, NULL); Iface_send(fromIf, msg); if (to == tn->nodeA) { Assert_true(tn->messageFrom == TUNA); } else if (to == tn->nodeB) { Assert_true(tn->messageFrom == TUNB); } else { Assert_true(false); } TestFramework_assertLastMessageUnaltered(tn->nodeA); TestFramework_assertLastMessageUnaltered(tn->nodeB); tn->messageFrom = 0; }
static Iface_DEFUN incomingFromCore(struct Message* msg, struct Iface* trickIf) { struct EventEmitter_pvt* ee = Identity_containerOf(trickIf, struct EventEmitter_pvt, trickIf); Assert_true(!((uintptr_t)msg->bytes % 4) && "alignment"); enum PFChan_Core ev = Message_pop32(msg, NULL); Assert_true(PFChan_Core_sizeOk(ev, msg->length+4)); uint32_t pathfinderNum = Message_pop32(msg, NULL); Message_push32(msg, ev, NULL); if (pathfinderNum != 0xffffffff) { struct Pathfinder* pf = ArrayList_Pathfinders_get(ee->pathfinders, pathfinderNum); Assert_true(pf && pf->state == Pathfinder_state_CONNECTED); return sendToPathfinder(msg, pf); } else { for (int i = 0; i < ee->pathfinders->length; i++) { struct Pathfinder* pf = ArrayList_Pathfinders_get(ee->pathfinders, i); if (!pf || pf->state != Pathfinder_state_CONNECTED) { continue; } struct Message* messageClone = Message_clone(msg, msg->alloc); Iface_CALL(sendToPathfinder, messageClone, pf); } } return NULL; }
/** @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; }
int main(int argc, char** argv) { #ifdef Log_KEYS fprintf(stderr, "Log_LEVEL = KEYS, EXPECT TO SEE PRIVATE KEYS IN YOUR LOGS!\n"); #endif if (isatty(STDIN_FILENO) || argc < 2) { // Fall through. } else if (!strcmp("angel", argv[1])) { return AngelInit_main(argc, argv); } else if (!strcmp("core", argv[1])) { return Core_main(argc, argv); } Assert_true(argc > 0); struct Except* eh = NULL; // Allow it to allocate 4MB struct Allocator* allocator = MallocAllocator_new(1<<22); struct Random* rand = Random_new(allocator, NULL, eh); struct EventBase* eventBase = EventBase_new(allocator); if (argc == 2) { // one argument if ((strcmp(argv[1], "--help") == 0) || (strcmp(argv[1], "-h") == 0)) { return usage(argv[0]); } else if (strcmp(argv[1], "--genconf") == 0) { return genconf(rand); } else if (strcmp(argv[1], "--pidfile") == 0) { // deprecated fprintf(stderr, "'--pidfile' option is deprecated.\n"); return 0; } 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) || (strcmp(argv[1], "-v") == 0)) { printf("Cjdns Git Version ID: %s\n", Version_gitVersion()); return 0; } else if (strcmp(argv[1], "--cleanconf") == 0) { // Performed after reading 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; } } 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]); // because of '--pidfile $filename'? if (strcmp(argv[1], "--pidfile") == 0) { fprintf(stderr, "\n'--pidfile' option is deprecated.\n"); } 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 Reader* stdinReader = FileReader_new(stdin, allocator); Dict config; if (JsonBencSerializer_get()->parseDictionary(stdinReader, allocator, &config)) { fprintf(stderr, "Failed to parse configuration.\n"); return -1; } if (argc == 2 && strcmp(argv[1], "--cleanconf") == 0) { struct Writer* stdoutWriter = FileWriter_new(stdout, allocator); JsonBencSerializer_get()->serializeDictionary(stdoutWriter, &config); printf("\n"); return 0; } struct Writer* logWriter = FileWriter_new(stdout, allocator); struct Log* logger = WriterLog_new(logWriter, allocator); // --------------------- Get Admin --------------------- // Dict* configAdmin = Dict_getDict(&config, String_CONST("admin")); String* adminPass = Dict_getString(configAdmin, String_CONST("password")); String* adminBind = Dict_getString(configAdmin, String_CONST("bind")); if (!adminPass) { adminPass = String_newBinary(NULL, 32, allocator); Random_base32(rand, (uint8_t*) adminPass->bytes, 32); adminPass->len = strlen(adminPass->bytes); } if (!adminBind) { Except_raise(eh, -1, "You must specify admin.bind in the cjdroute.conf file."); } // --------------------- Check for running instance --------------------- // Log_info(logger, "Checking for running instance..."); checkRunningInstance(allocator, eventBase, adminBind, adminPass, logger, eh); // --------------------- Setup Pipes to Angel --------------------- // char angelPipeName[64] = "client-angel-"; Random_base32(rand, (uint8_t*)angelPipeName+13, 31); Assert_true(EventBase_eventCount(eventBase) == 0); struct Pipe* angelPipe = Pipe_named(angelPipeName, eventBase, eh, allocator); Assert_true(EventBase_eventCount(eventBase) == 2); angelPipe->logger = logger; char* args[] = { "angel", angelPipeName, NULL }; // --------------------- Spawn Angel --------------------- // String* privateKey = Dict_getString(&config, String_CONST("privateKey")); char* corePath = Process_getPath(allocator); if (!corePath) { Except_raise(eh, -1, "Can't find a usable cjdns core executable, " "make sure it is in the same directory as cjdroute"); } if (!privateKey) { Except_raise(eh, -1, "Need to specify privateKey."); } Log_info(logger, "Forking angel to background."); Process_spawn(corePath, args, eventBase, allocator); // --------------------- Get user for angel to setuid() ---------------------- // String* securityUser = NULL; List* securityConf = Dict_getList(&config, String_CONST("security")); for (int i = 0; i < List_size(securityConf); i++) { securityUser = Dict_getString(List_getDict(securityConf, i), String_CONST("setuser")); if (securityUser) { int64_t* ea = Dict_getInt(List_getDict(securityConf, i), String_CONST("exemptAngel")); if (ea && *ea) { securityUser = NULL; } break; } } // --------------------- Pre-Configure Angel ------------------------- // Dict* preConf = Dict_new(allocator); Dict* adminPreConf = Dict_new(allocator); Dict_putDict(preConf, String_CONST("admin"), adminPreConf, allocator); Dict_putString(adminPreConf, String_CONST("core"), String_new(corePath, allocator), allocator); Dict_putString(preConf, String_CONST("privateKey"), privateKey, allocator); Dict_putString(adminPreConf, String_CONST("bind"), adminBind, allocator); Dict_putString(adminPreConf, String_CONST("pass"), adminPass, allocator); if (securityUser) { Dict_putString(adminPreConf, String_CONST("user"), securityUser, allocator); } Dict* logging = Dict_getDict(&config, String_CONST("logging")); if (logging) { Dict_putDict(preConf, String_CONST("logging"), logging, allocator); } #define CONFIG_BUFF_SIZE 1024 uint8_t buff[CONFIG_BUFF_SIZE] = {0}; struct Writer* toAngelWriter = ArrayWriter_new(buff, CONFIG_BUFF_SIZE - 1, allocator); if (StandardBencSerializer_get()->serializeDictionary(toAngelWriter, preConf)) { Except_raise(eh, -1, "Failed to serialize pre-configuration"); } struct Message* toAngelMsg = &(struct Message) { .bytes = buff, .length = toAngelWriter->bytesWritten }; toAngelMsg = Message_clone(toAngelMsg, allocator); Interface_sendMessage(&angelPipe->iface, toAngelMsg); Log_keys(logger, "Sent [%s] to angel process.", buff); // --------------------- Get Response from Angel --------------------- // struct Message* fromAngelMsg = InterfaceWaiter_waitForData(&angelPipe->iface, eventBase, allocator, eh); Dict responseFromAngel; struct Reader* responseFromAngelReader = ArrayReader_new(fromAngelMsg->bytes, fromAngelMsg->length, allocator); if (StandardBencSerializer_get()->parseDictionary(responseFromAngelReader, allocator, &responseFromAngel)) { Except_raise(eh, -1, "Failed to parse pre-configuration response [%s]", buff); } // --------------------- Get Admin Addr/Port/Passwd --------------------- // Dict* responseFromAngelAdmin = Dict_getDict(&responseFromAngel, String_CONST("admin")); adminBind = Dict_getString(responseFromAngelAdmin, String_CONST("bind")); if (!adminBind) { Except_raise(eh, -1, "didn't get address and port back from angel"); } struct Sockaddr_storage adminAddr; if (Sockaddr_parse(adminBind->bytes, &adminAddr)) { Except_raise(eh, -1, "Unable to parse [%s] as an ip address port, eg: 127.0.0.1:11234", adminBind->bytes); } // sanity check, Pipe_named() creates 2 events, see above. Assert_true(EventBase_eventCount(eventBase) == 2); // --------------------- Configuration ------------------------- // Configurator_config(&config, &adminAddr.addr, adminPass, eventBase, logger, allocator); // --------------------- noBackground ------------------------ // int64_t* noBackground = Dict_getInt(&config, String_CONST("noBackground")); if (noBackground && *noBackground) { EventBase_beginLoop(eventBase); } //Allocator_free(allocator); return 0; }
static int handleFromPathfinder(enum PFChan_Pathfinder ev, struct Message* msg, struct EventEmitter_pvt* ee, struct Pathfinder* pf) { switch (ev) { default: return false; case PFChan_Pathfinder_CONNECT: { struct PFChan_Pathfinder_Connect connect; Message_shift(msg, -8, NULL); Message_pop(msg, &connect, PFChan_Pathfinder_Connect_SIZE, NULL); pf->superiority = Endian_bigEndianToHost32(connect.superiority_be); pf->version = Endian_bigEndianToHost32(connect.version_be); Bits_memcpy(pf->userAgent, connect.userAgent, 64); pf->state = Pathfinder_state_CONNECTED; struct PFChan_Core_Connect resp; resp.version_be = Endian_bigEndianToHost32(Version_CURRENT_PROTOCOL); resp.pathfinderId_be = Endian_hostToBigEndian32(pf->pathfinderId); Bits_memcpy(resp.publicKey, ee->publicKey, 32); Message_push(msg, &resp, PFChan_Core_Connect_SIZE, NULL); Message_push32(msg, PFChan_Core_CONNECT, NULL); struct Message* sendMsg = Message_clone(msg, msg->alloc); Iface_CALL(sendToPathfinder, sendMsg, pf); break; } case PFChan_Pathfinder_SUPERIORITY: { Message_shift(msg, -8, NULL); pf->superiority = Message_pop32(msg, NULL); struct Message* resp = pathfinderMsg(PFChan_Core_PATHFINDER, pf, msg->alloc); Iface_CALL(incomingFromCore, resp, &ee->trickIf); break; } case PFChan_Pathfinder_PING: { struct Message* sendMsg = Message_clone(msg, msg->alloc); Iface_send(&pf->iface, sendMsg); break; } case PFChan_Pathfinder_PONG: { Message_shift(msg, -8, NULL); uint32_t cookie = Message_pop32(msg, NULL); uint32_t count = Message_pop32(msg, NULL); if (cookie != PING_MAGIC || count > pf->bytesSinceLastPing) { pf->state = Pathfinder_state_ERROR; struct Message* resp = pathfinderMsg(PFChan_Core_PATHFINDER_GONE, pf, msg->alloc); Iface_CALL(incomingFromCore, resp, &ee->trickIf); } else { pf->bytesSinceLastPing -= count; } break; } case PFChan_Pathfinder_PATHFINDERS: { for (int i = 0; i < ee->pathfinders->length; i++) { struct Pathfinder* xpf = ArrayList_Pathfinders_get(ee->pathfinders, i); if (!xpf || xpf->state != Pathfinder_state_CONNECTED) { continue; } struct Allocator* alloc = Allocator_child(msg->alloc); struct Message* resp = pathfinderMsg(PFChan_Core_PATHFINDER, pf, alloc); Iface_CALL(sendToPathfinder, resp, pf); Allocator_free(alloc); } break; } } return true; }