next up previous contents
Next: Sending and Receiving Up: Example Protocol Previous: Opening Connections

Demultiplexing Incoming Messages

 

Function aspDemux is called indirectly through xDemux by an IP session to pass an incoming message up to ASP. (More generally, it could be called by any low level protocol configured below ASP, but this will usually be IP.) This function extracts the header information from the message, and then demultiplexes the message to the appropriate session as follows. First, aspDemux consults the protocol's active map to see if an existing session exists for the ASP channel to which the message belongs. If such a session exists, the message is passed to that session via the xPop operation. If it does not exist, aspDemux then checks the passive map to see if the message is addressed to a port on which a high level session has performed an xOpenEnable. If the port is found in the passive map, a new session is created---by invoking aspCreateSessn---and the message is dispatched to that session. If an appropriate entry is not found in either the active or passive maps, the message is discarded.

static XkReturn
aspDemux(Protl self, Sessn lls, Msg *dg)
{
    char       *buf;
    ASPhdr     h;
    ActiveId   activeid;
    ProtlState *pstate = (ProtlState *)self->state;
    Sessn      s;
    PassiveId  passiveid;
    Enable     *e;

    /* extract the header from the message */
    buf = msgPop(dg, HLEN);
    if (buf == NULL)
        return XK_FAILURE;
    aspHdrLoad(&h, buf, HLEN);

    /* construct a demux key from the header */
    bzero((char *)&activeid, sizeof(activeid));
    activeid.lls        = lls;
    activeid.localport  = h.dport;
    activeid.remoteport = h.sport;

    /* see if demux key is in the active map */
    if (mapResolve(pstate->activemap, &activeid, (void **)&s) == XK_FAILURE) {
        /* didn't find an active session, so check passive map */
        passiveid = h.dport;
        if (mapResolve(pstate->passivemap, &passiveid, (void **)&e) ==
                XK_FAILURE) {
            /* drop the message */
            return XK_SUCCESS;
        }

        /* port was enabled, so create a new session and inform hlp */
        s = aspCreateSessn(self, e->hlp, e->hlpType, &activeid);
        if (s == ERR_SESSN)
            return XK_SUCCESS;
        xDuplicate(lls);
        xOpenDone(e->hlp, self, s);
    }

    /* found (or created) an appropriate session, so pop to it */
    return xPop(s, lls, dg, &h);
}

The call to xDuplicate near the end of aspDemux is necessary to increment the reference count on the newly created session. More on reference counts in Section 8.

Subroutine aspHdrLoad is responsible for converting the fields in the ASP header from network byte order into the local host's byte order. It uses the library routine ntohs, which stand for network-to-host-short. A counterpart routine--- aspHdrStore---performs the opposite conversion; it translates host byte order to network byte order. This latter routine is used when preparing a message for transmission, as discussed in the next subsection. Notice that both routines simultaneously swap bytes and copy the header between the message and the template.

static long
aspHdrLoad(ASPhdr *hdr, char *src, long len)
{
    /* copy from src to hdr, then convert network byte order to hsot order */
    bcopy(src, (char *)hdr, HLEN);
    hdr->ulen  = ntohs(hdr->ulen);
    hdr->sport = ntohs(hdr->sport);
    hdr->dport = ntohs(hdr->dport);
    return HLEN;
}

static void
aspHdrStore(ASPhdr *hdr, char *dst, long len)
{
    /* convert host byte order to network order, then copy from hdr to dst */
    /* (note: argument 'hdr' is changed by the following code) */
    hdr->ulen  = htons(hdr->ulen);
    hdr->sport = htons(hdr->sport);
    hdr->dport = htons(hdr->dport);
    bcopy((char *)hdr, dst, HLEN);
}



Larry Peterson
Wed Feb 21 13:58:06 MST 1996