Receive side state machine

This state machine is targeted towards packet based systems such as VIA.  That
is to say that it assumes that only complete packets are handed to the state
machine.  Some alterations (likely in the form of additional states) are
required in order to support a the processing of partial packets received by
stream based model like TCP.

Tasks for this state machine:

- recv control and data packets

- potentially provide buffers to associated send CAR

- track buffers provided by associated send CAR

- notify associated send CAR of any progress made

- provide buffer availability information for flow control


This version of the state machine only handles receiving data into a user
provided buffer.  It needs to be expanded to include the forwarding cases.

CP = control packet
DP = data packet(s)

State [Await CP],[label="Await Incoming\nControl Packet"]
    Event [Pkt]
        Invoke_Action[Determine CP Type],[label="got ctrl pkt"]

Action [Determine CP Type]
    Get_Next_Packet_And_Process_Ring_Buffer()
    switch (packet type)
        case flow
	    Invoke_Action[Proc Flow CP]
        case rndv-rts
	    Invoke_Action[Proc Rndv-RTS CP]
        case rndv-cts
	    Invoke_Action[Proc Rndv-CTS CP]
        case short
	    Invoke_Action[Proc Short CP]
        case eager
	    Invoke_Action[Proc Eager CP]
        case rndv-data
	    Invoke_Action[Proc Rndv-Data CP]

Action [Proc Flow CP]
    // TODO: We need to figure out what needs to happen when we receive an
    // explicit flow control packet.  For that matter, we need to figure out
    // how to deal with flow control in general...
    Change_State([Await CP])

Action [Proc Rndv-RTS CP]
    Change_State([Await CP])

Action [Proc Rndv-CTS CP]
    Change_State([Await CP])

Action [Proc Short CP]
    Change_State([Await CP])

Action [Proc Eager CP]
    Invoke_Action([Check For Posted Request])

Action [Check For Posted Request]
    recv_incoming_foa(..., &found)
    if (found)
        Change_State([Recv Posted Data])
    else
        Invoke_Action([Proc Unexp Eager CP Data])

Action [Proc Unexp Eager CP Data],
       [label="Process Unexpected\nEager CP Data"]
    decide whether to keep the data in the packets or make a temporary copy
    // this decision might be affected by the availability of buffers to 
    // serve as replacements if we were to keep the ones we receive data in.
    if copy
        allocate temporary buffer big enough to hold all message data
        copy data from first packet
        return packet ???  // NEED AN INTERFACE FUNCTION HERE
    else
        keep handle to packet with car
        maybe allocate replacement buffers
    record in car how we decided to handle data (copy or keep in packets)
    if there are data pkts available locally
        Invoke_Action([Proc Unexp DP])
    else
        Change_State([Await Unexp DP])

State [Await Unexp DP]
    Event [Pkt]
        Invoke_Action([Proc Unexp DP])

Action [Proc Unexp DP],
       [label="Process Unexpected\nData Packet(s)"]
    while there are data pkts available locally
        Get_Next_Packet_And_Process_Ring_Buffer()
        if we are copying data
            make copy
            return packet // NEED OUR INTERFACE AGAIN
        else
            keep handle to packet with car
            maybe allocate replacement buffers
    if all data pkts have been received
        if there are more packets // the first will be a ctrl pkt
            Invoke_Action([Determine CP Type],[label="more queued CPs"])  
	    // also grabs pkt
        else
            Change_State([Await CP])
    else
        Change_State([Await Unexp DP],[label="empty incoming queue"])

Action [Proc Rndv-Data CP]
    Change_State([Recv Posted Data])

State [Recv Posted Data],[shape=polygon,sides=5]
    Event [finished]
        Change_State([Await CP])

Function Get_Next_Packet_And_Process_Ring_Buffer()
    get reference to packet so we can move it around
    if we need some more buffers in the ring
        attempt to acquire buffers
        if we got buffers
            add to receive buffer ring for VC
            post flow control update to be sent   
    return pointer to packet
