static Iface_DEFUN incomingMsg(struct Message* msg, struct Pathfinder_pvt* pf) { struct Address addr; 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.padding = 0; addr.path = Endian_bigEndianToHost64(hdr->sh.label_be); //Log_debug(pf->log, "Incoming DHT"); struct DHTMessage dht = { .address = &addr, .binMessage = msg, .allocator = msg->alloc }; DHTModuleRegistry_handleIncoming(&dht, pf->registry); struct Message* nodeMsg = Message_new(0, 256, msg->alloc); Iface_CALL(sendNode, nodeMsg, &addr, 0xfffffff0u, pf); if (dht.pleaseRespond) { // what a beautiful hack, see incomingFromDHT return Iface_next(&pf->pub.eventIf, msg); } return NULL; } static Iface_DEFUN incomingFromEventIf(struct Message* msg, struct Iface* eventIf) { struct Pathfinder_pvt* pf = Identity_containerOf(eventIf, struct Pathfinder_pvt, pub.eventIf); enum PFChan_Core ev = Message_pop32(msg, NULL); if (Pathfinder_pvt_state_INITIALIZING == pf->state) { Assert_true(ev == PFChan_Core_CONNECT); return connected(pf, msg); } // Let the PF send another 128 path changes again because it's basically a new tick. pf->bestPathChanges = 0; switch (ev) { case PFChan_Core_SWITCH_ERR: return switchErr(msg, pf); case PFChan_Core_SEARCH_REQ: return searchReq(msg, pf); case PFChan_Core_PEER: return peer(msg, pf); case PFChan_Core_PEER_GONE: return peerGone(msg, pf); case PFChan_Core_SESSION: return session(msg, pf); case PFChan_Core_SESSION_ENDED: return sessionEnded(msg, pf); case PFChan_Core_DISCOVERED_PATH: return discoveredPath(msg, pf); case PFChan_Core_MSG: return incomingMsg(msg, pf); case PFChan_Core_PING: return handlePing(msg, pf); case PFChan_Core_PONG: return handlePong(msg, pf); case PFChan_Core_UNSETUP_SESSION: case PFChan_Core_LINK_STATE: case PFChan_Core_CTRL_MSG: return NULL; default:; } Assert_failure("unexpected event [%d]", ev); } static void sendEvent(struct Pathfinder_pvt* pf, enum PFChan_Pathfinder ev, void* data, int size) { struct Allocator* alloc = Allocator_child(pf->alloc); struct Message* msg = Message_new(0, 512+size, alloc); Message_push(msg, data, size, NULL); Message_push32(msg, ev, NULL); Iface_send(&pf->pub.eventIf, msg); Allocator_free(alloc); } static void init(void* vpf) { struct Pathfinder_pvt* pf = Identity_check((struct Pathfinder_pvt*) vpf); struct PFChan_Pathfinder_Connect conn = { .superiority_be = Endian_hostToBigEndian32(1), .version_be = Endian_hostToBigEndian32(Version_CURRENT_PROTOCOL) }; CString_strncpy(conn.userAgent, "Cjdns internal pathfinder", 64); sendEvent(pf, PFChan_Pathfinder_CONNECT, &conn, PFChan_Pathfinder_Connect_SIZE); } struct Pathfinder* Pathfinder_register(struct Allocator* allocator, struct Log* log, struct EventBase* base, struct Random* rand, struct Admin* admin) { struct Allocator* alloc = Allocator_child(allocator); struct Pathfinder_pvt* pf = Allocator_calloc(alloc, sizeof(struct Pathfinder_pvt), 1); Identity_set(pf); pf->alloc = alloc; pf->log = log; pf->base = base; pf->rand = rand; pf->admin = admin; pf->pub.eventIf.send = incomingFromEventIf; pf->dhtModule.context = pf; pf->dhtModule.handleOutgoing = incomingFromDHT; // This needs to be done asynchronously so the pf can be plumbed to the core Timeout_setTimeout(init, pf, 0, base, alloc); return &pf->pub; }
void notify_message(struct sockaddr *from, int proto, u_char *msg, int len) { u_short *p = (u_short *) msg ; u_short msgid, flags ; MSGPTR pMsg ; #ifdef DEBUG char logbuf[256] ; #endif msgid = ntohs(p[0]) ; flags = ntohs(p[1]) ; #ifdef DEBUG if ((flags & 0x8000) == 0) { sprintf(logbuf, "Request %04x (%04x) from %s, %d bytes", msgid, flags, addrFmt(from, proto), len) ; } else { sprintf(logbuf, "Response %04x (%04x) from %s %d bytes", msgid, flags, addrFmt(from, proto), len) ; } TRACE("%s\n", logbuf) ; strcpy(logbuf, " ") ; switch ((flags & 0x7800) >> 11) { case 0 : strcat(logbuf, "QUERY ") ; break ; case 1 : strcat(logbuf, "IQUERY ") ; break ; case 2 : strcat(logbuf, "STATUS ") ; break ; default : strcat(logbuf, "UNKNOWN") ; break ; } if ((flags & 0x0400) != 0) { strcat(logbuf, ",AA") ; } if ((flags & 0x0200) != 0) { strcat(logbuf, ",TC") ; } if ((flags & 0x0100) != 0) { strcat(logbuf, ",RD") ; } if ((flags & 0x0080) != 0) { strcat(logbuf, ",RA") ; } switch (flags & 0x00f) { case 0 : strcat(logbuf, ",No Error ") ; break ; case 1 : strcat(logbuf, ",Format Error ") ; break ; case 2 : strcat(logbuf, ",Server Failure ") ; break ; case 3 : strcat(logbuf, ",Name Error ") ; break ; case 4 : strcat(logbuf, ",Not Implemented") ; break ; case 5 : strcat(logbuf, ",Refused ") ; break ; default : strcat(logbuf, ",Unknown Error ") ; break ; } TRACE("%s\n", logbuf) ; #endif if ((flags & 0x8000) == 0) { /* request from client */ if ((pMsg = searchReq(msgid, proto, from)) == NULL) { pMsg = createReq(msgid, proto, from) ; } if (pMsg == NULL) { WARN("notify_message - cannot create message record\n") ; return ; } messageForward(pMsg, msg, len) ; } else { /* response from server */ if ((pMsg = searchOrg(msgid, proto)) == NULL) { WARN("notify_message - no corresponding request\n") ; return ; } messageResponse(pMsg, msg, len) ; disposeReq(pMsg); } }