Exemple #1
0
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;
}
Exemple #2
0
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);
    }
}