static Iface_DEFUN receiveMessage(struct Message* msg, struct Iface* addrIface) { struct Context* ctx = Identity_containerOf(addrIface, struct Context, addrIface); struct Sockaddr_storage source; Message_pop(msg, &source, ctx->targetAddr->addrLen, NULL); if (Bits_memcmp(&source, ctx->targetAddr, ctx->targetAddr->addrLen)) { Log_info(ctx->logger, "Got spurious message from [%s], expecting messages from [%s]", Sockaddr_print(&source.addr, msg->alloc), Sockaddr_print(ctx->targetAddr, msg->alloc)); return NULL; } // we don't yet know with which message this data belongs, // the message alloc lives the length of the message reception. struct Allocator* alloc = Allocator_child(msg->alloc); int origLen = msg->length; Dict* d = NULL; char* err = BencMessageReader_readNoExcept(msg, alloc, &d); if (err) { return NULL; } Message_shift(msg, origLen, NULL); String* txid = Dict_getString(d, String_CONST("txid")); if (!txid || txid->len != 8) { return NULL; } // look up the result uint32_t handle = ~0u; Hex_decode((uint8_t*)&handle, 4, txid->bytes, 8); int idx = Map_OfRequestByHandle_indexForHandle(handle, &ctx->outstandingRequests); if (idx < 0) { return NULL; } struct Request* req = ctx->outstandingRequests.values[idx]; // now this data will outlive the life of the message. Allocator_adopt(req->promise->alloc, alloc); req->res.responseDict = d; int len = (msg->length > AdminClient_MAX_MESSAGE_SIZE) ? AdminClient_MAX_MESSAGE_SIZE : msg->length; Bits_memset(req->res.messageBytes, 0, AdminClient_MAX_MESSAGE_SIZE); Bits_memcpy(req->res.messageBytes, msg->bytes, len); done(req, AdminClient_Error_NONE); return NULL; }
static void receiveMessage2(struct Message* msg, struct Hermes* hermes, struct Allocator* tempAlloc) { #ifdef Log_KEYS char lastChr = msg->bytes[msg->length - 1]; msg->bytes[msg->length - 1] = '\0'; Log_keys(hermes->logger, "Got message from angel [%s%c]", msg->bytes, lastChr); msg->bytes[msg->length - 1] = lastChr; #else Log_debug(hermes->logger, "Got message from angel"); #endif Dict* d = NULL; char* err = BencMessageReader_readNoExcept(msg, tempAlloc, &d); if (err) { Log_warn(hermes->logger, "Failed to parse message from angel [%s]", err); return; } String* txid = Dict_getString(d, String_CONST("txid")); uint32_t handle; if (!txid || txid->len != 8 || 4 != Hex_decode((uint8_t*)&handle, 4, (uint8_t*)txid->bytes, 8)) { Log_warn(hermes->logger, "Message from angel; txid missing or unrecognized"); return; } int index = Map_RequestSet_indexForHandle(handle, &hermes->requestSet); if (index < 0) { Log_warn(hermes->logger, "Message from angel references nonexistant request"); return; } struct Request* req = Identity_check((struct Request*) hermes->requestSet.values[index]); req->onResponse(d, req->onResponseContext); Allocator_free(req->alloc); }
static Iface_DEFUN incoming(struct Message* msg, struct Iface* interRouterIf) { struct MsgCore_pvt* mcp = Identity_containerOf(interRouterIf, struct MsgCore_pvt, pub.interRouterIf); struct Address addr = { .padding = 0 }; struct RouteHeader* hdr = (struct RouteHeader*) msg->bytes; Message_shift(msg, -(RouteHeader_SIZE + DataHeader_SIZE), NULL); Bits_memcpy(addr.ip6.bytes, hdr->ip6, 16); Bits_memcpy(addr.key, hdr->publicKey, 32); addr.protocolVersion = Endian_bigEndianToHost32(hdr->version_be); addr.path = Endian_bigEndianToHost64(hdr->sh.label_be); Dict* content = NULL; uint8_t* msgBytes = msg->bytes; int length = msg->length; //Log_debug(mcp->log, "Receive msg [%s] from [%s]", // Escape_getEscaped(msg->bytes, msg->length, msg->alloc), // Address_toString(&addr, msg->alloc)->bytes); // BencMessageReader_readNoExcept(msg, msg->alloc, &content); if (!content) { char* esc = Escape_getEscaped(msgBytes, length, msg->alloc); Log_debug(mcp->log, "DROP Malformed message [%s]", esc); return NULL; } int64_t* verP = Dict_getIntC(content, "p"); if (!verP) { Log_debug(mcp->log, "DROP Message without version"); return NULL; } addr.protocolVersion = *verP; String* q = Dict_getStringC(content, "q"); if (!Defined(SUBNODE)) { String* txid = Dict_getStringC(content, "txid"); Assert_true(txid); if (q) { if (txid->bytes[0] == '0') { Log_debug(mcp->log, "DROP query which begins with 0 and is for old pathfinder"); return NULL; } } else { if (txid->bytes[0] != '1') { Log_debug(mcp->log, "DROP reply which does not begin with 1"); return NULL; } String* newTxid = String_newBinary(NULL, txid->len - 1, msg->alloc); Bits_memcpy(newTxid->bytes, &txid->bytes[1], txid->len - 1); Dict_putStringC(content, "txid", newTxid, msg->alloc); txid = newTxid; } } if (q) { return queryMsg(mcp, content, &addr, msg); } else { return replyMsg(mcp, content, &addr, msg); } } struct MsgCore* MsgCore_new(struct EventBase* base, struct Random* rand, struct Allocator* allocator, struct Log* log, struct EncodingScheme* scheme) { struct Allocator* alloc = Allocator_child(allocator); struct MsgCore_pvt* mcp = Allocator_calloc(alloc, sizeof(struct MsgCore_pvt), 1); Identity_set(mcp); mcp->pub.interRouterIf.send = incoming; mcp->qh = ArrayList_OfQueryHandlers_new(alloc); mcp->pinger = Pinger_new(base, rand, log, alloc); mcp->log = log; mcp->scheme = scheme; mcp->schemeDefinition = EncodingScheme_serialize(scheme, alloc); return &mcp->pub; }