next up previous contents
Next: Demultiplexing Incoming Messages Up: Example Protocol Previous: Initialization

Opening Connections

When a high level protocol wishes to establish an ASP channel to a remote host, it will call xOpen, which causes aspOpen to be called. This function extracts the local and remote ASP ports from the participant list passed down by the high level protocol, and passes the resulting participant list, via another xOpen call, down to IP. A new ASP session ( asp_s) is then created to handle messages sent and received on this channel. If a high level protocol attempts to re-open a channel---i.e., one that is found in the active map---the open fails; otherwise, the newly created session is returned to the calling protocol.

Notice that aspOpen uses the x-kernel operation partPop to extract address information from the participant list; there is also a partPush operation that is used to attach addressing information to the participant list. Briefly, the participant list is an array of addresses, where by convention, the first element of this array identifies the remote participant and the second element identifies the local participant. Each element in the array is, in turn, represented by a stack of addresses; hence ``push'' and ``pop'' in the operation names. It is a stack rather than a flat structure because a given participant might be identified with a multi-component address, for example, a host address and a port number. In this example, aspOpen extracts the port number from each stack, but leaves the host number on the stack for some lower level protocol (e.g., IP) to process.

static Sessn
aspOpen(self, hlp, hlpType, p)
Protl self, hlp, hlpType;
Part  *p;
{
    ActiveId   key;
    Sessn      asp_s, lls;
    ProtlState *pstate = (ProtlState *)self->state;

    bzero((char *)&key, sizeof(key));

    /* high level protocol must specify both local and remote ASP port */
    key.remoteport = *((ASPport *)partPop(p[0]));
    key.localport  = *((ASPport *)partPop(p[1]));

    /* attempt to open session on protocol below this one */
    lls = xOpen(self, self, xGetProtlDown(self, 0), p);
    if (lls != ERR_SESSN) {
        key.lls = lls;
        /* check for this session in the active map */
        if (mapResolve(pstate->activemap, &key, (void **)&asp_s) == XK_FAILURE){
            /* session wasn't already in map, so initialize it */
            asp_s = aspCreateSessn(self, hlp, hlpType, &key);
            if (asp_s != ERR_SESSN)    /* A successful open! */
                return asp_s;
        }
        /* if control makes it this far, an error has occurred */
        xClose(lls);
    }
    return ERR_SESSN;
}

Note that the real work of initializing the session is performed by asp_init_session, presented below. Before we get into the details of that routine, however, we'll take a look at aspOpenEnable. This is the routine that is called indirectly through xOpenEnable by a high level protocol that wants to do a passive open on ASP. The high level protocol specifies its willingness to receive messages on a specific ASP port, and aspOpenEnable records this fact in its passive map. Note that the x-kernel defines an Enable object that is used by aspOpenEnable to record the necessary information about the passive open, including a reference count ( rcnt) of how many times that particular port has been enabled. Also, keep in mind that a session object is not created at this time; it will be created in aspDemux when a message arrives addressed to that port.

static XkReturn
aspOpenEnable(Protl self, Protl hlp, Protl hlpType, Part *p)
{
    PassiveId  key;
    ProtlState *pstate = (ProtlState *)self->state;
    Enable     *e;

    key = *((ASPport *)partPop(*p));

    /* check if this port has already been openenabled */
    if (mapResolve(pstate->passivemap, &key, (void **)&e) != XK_FAILURE) {
        if (e->hlp == hlp) {
           /* this port was openenabled previously by the same hlp */
            e->rcnt++;
            return XK_SUCCESS;
        }
        /* this port was openenabled previously by a different hlp - error */
        return XK_FAILURE;
    }

    /* this will be a new enabling, so create and initialize Enable object, */
    /* and enter the binding of port/enable object in the passive map */
    e = X_NEW(Enable);
    e->hlp     = hlp;
    e->hlpType = hlpType;
    e->rcnt    = 1;
    e->binding = mapBind(pstate->passivemap, &key, e);
    if (e->binding == ERR_BIND) {
        xFree((char *)e);
        return XK_FAILURE;
    }
    return XK_SUCCESS;
}

Finally, the actual work of initializing an ASP session is performed in the subroutine aspCreateSessn given below. This subroutine calls an x-kernel operation--- xCreateSessn---to allocate a new session object and connect it to other protocol and session objects in the appropriate way; e.g., the new session points to the high level protocol that created it ( hlp) and the low-level session that it will use to send and receive messages ( lls). In addition, the new session object will need to know where to find the routines that implement the various operations it supports, such as xPush and xPop. getproc_sessn (presented below) is the routine that fills in the ASP-specific function pointers for these operations; it is called by xCreateSessn.

Note that aspCreateSessn is not only called from aspOpen, but also from aspDemux (given below) when it needs to create a new session as a result of an earlier passive open. Also notice that in the case of aspCreateSessn, the only protocol-specific initialization required is to set up a header template asph that can later be prepended to the front of outgoing messages.

static Sessn
aspCreateSessn(Protl self, Protl hlp, Protl hlpType, ActiveId *key)
{
    Sessn      s;
    ProtlState *pstate = (ProtlState *)self->state;
    SessnState *sstate;
    ASPhdr     *asph;

    /* create the session object and initialize it */
    s = xCreateSessn(getproc_sessn, hlp, hlpType, self, 1, &key->lls);
    s->binding = mapBind(pstate->activemap, key, s);
    sstate = X_NEW(SessnState);
    s->state = (char *)sstate;

    /* create an ASP header */
    asph = &(sstate->hdr);
    asph->sport = key->localport;
    asph->dport = key->remoteport;
    asph->ulen  = 0;

    return s;
}

static void
getproc_sessn(Sessn s)
{
    /* fill in the function pointers to implement session operations */
    s->push            = aspPush;
    s->pop             = aspPop;
    s->controlsessn    = aspControlSessn;
    s->getparticipants = aspGetParticipants;
    s->close           = aspClose;
}



next up previous contents
Next: Demultiplexing Incoming Messages Up: Example Protocol Previous: Initialization



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