INET Framework for OMNeT++/OMNEST
SCTPReceiveStream Class Reference

#include <SCTPReceiveStream.h>

List of all members.

Public Member Functions

uint32 enqueueNewDataChunk (SCTPDataVariables *dchunk)
 SCTPReceiveStream ()
 ~SCTPReceiveStream ()
SCTPQueuegetDeliveryQ () const
SCTPQueuegetOrderedQ () const
SCTPQueuegetUnorderedQ () const
int32 getExpectedStreamSeqNum () const
int32 getStreamId () const
void setExpectedStreamSeqNum (const int32 num)
void setStreamId (const uint16 id)

Protected Member Functions

uint32 reassemble (SCTPQueue *queue, uint32 tsn)

Protected Attributes

uint16 streamId
int32 expectedStreamSeqNum
SCTPQueuedeliveryQ
SCTPQueueorderedQ
SCTPQueueunorderedQ

Constructor & Destructor Documentation

SCTPReceiveStream::SCTPReceiveStream ( )

Ctor.

SCTPReceiveStream::~SCTPReceiveStream ( )

Virtual dtor.

{
    delete deliveryQ;
    delete orderedQ;
    delete unorderedQ;
}

Member Function Documentation

uint32 SCTPReceiveStream::enqueueNewDataChunk ( SCTPDataVariables dchunk)
{
    uint32 delivery = 0;      //0:orderedQ=false && deliveryQ=false; 1:orderedQ=true && deliveryQ=false; 2:oderedQ=true && deliveryQ=true; 3:fragment

    SCTPDataVariables* chunk;
    //sctpEV3 << "Enqueueing NEW data chunk (TSN="<<dchunk->tsn<<") for Stream ID "<<dchunk->sid<<"\n";
    /* append to the respective queue */
    if (!dchunk->ordered)
    {
        if (dchunk->bbit && dchunk->ebit)
        {
            /* put message into deliveryQ */
            if (deliveryQ->checkAndInsertChunk(dchunk->tsn, dchunk))
            {
                delivery = 2;
            }
        } else {
            unorderedQ->checkAndInsertChunk(dchunk->tsn, dchunk);
            delivery = 3;

            /* try to reassemble here */
            uint32 reassembled = reassemble(unorderedQ, dchunk->tsn);

            if ((unorderedQ->getChunk(reassembled))->bbit && (unorderedQ->getChunk(reassembled))->bbit)
            {
                /* put message into deliveryQ */
                if (deliveryQ->checkAndInsertChunk(reassembled, unorderedQ->getAndExtractChunk(reassembled)))
                {
                    delivery = 2;
                }
            }
        }
    }
    else if (dchunk->ordered)
    {
        /* put message into streams ->reassembyQ */
        if (orderedQ->checkAndInsertChunk(dchunk->tsn, dchunk))
            delivery = 1;

        if (!dchunk->bbit || !dchunk->ebit)
        {
            delivery = 3;
            /* try to reassemble */
            reassemble(orderedQ, dchunk->tsn);
        }

        if (orderedQ->getQueueSize()>0)
        {
            /* dequeue first from orderedQ */
            chunk = orderedQ->dequeueChunkBySSN(expectedStreamSeqNum);
            if (chunk)
            {
                if (deliveryQ->checkAndInsertChunk(chunk->tsn, chunk))
                {
                    ++expectedStreamSeqNum;
                    if (expectedStreamSeqNum > 65535)
                        expectedStreamSeqNum = 0;
                    delivery = 2;
                }
            }
        }
    }

    return delivery;
}
SCTPQueue* SCTPReceiveStream::getDeliveryQ ( ) const [inline]
int32 SCTPReceiveStream::getExpectedStreamSeqNum ( ) const [inline]
SCTPQueue* SCTPReceiveStream::getOrderedQ ( ) const [inline]

Referenced by SCTPAssociation::putInDeliveryQ().

{ return orderedQ; };
int32 SCTPReceiveStream::getStreamId ( ) const [inline]
{ return streamId; };
SCTPQueue* SCTPReceiveStream::getUnorderedQ ( ) const [inline]
{ return unorderedQ; };
uint32 SCTPReceiveStream::reassemble ( SCTPQueue queue,
uint32  tsn 
) [protected]

Referenced by enqueueNewDataChunk().

{
    uint32 begintsn = tsn, endtsn = 0;

    sctpEV3 << "Trying to reassemble message..." << endl;

    /* test if we have all fragments down to the first */
    while (orderedQ->getChunk(begintsn) && !(orderedQ->getChunk(begintsn))->bbit)
        begintsn--;

    if (orderedQ->getChunk(begintsn))
    {
        endtsn = begintsn;

        /* test if we have all fragments up to the end */
        while (orderedQ->getChunk(endtsn) && !(orderedQ->getChunk(endtsn))->ebit)
            endtsn++;

        if (orderedQ->getChunk(endtsn))
        {
            sctpEV3 << "All fragments found, now reassembling..." << endl;

            SCTPDataVariables *firstVar = orderedQ->getChunk(begintsn), *processVar;
            SCTPSimpleMessage* firstSimple=check_and_cast<SCTPSimpleMessage*>(firstVar->userData);

            sctpEV3 << "First fragment has " << firstVar->len / 8 << " bytes." << endl;

            while (++begintsn <= endtsn)
            {
                processVar = orderedQ->getAndExtractChunk(begintsn);
                SCTPSimpleMessage* processSimple=check_and_cast<SCTPSimpleMessage*>(processVar->userData);

                sctpEV3 << "Adding fragment with " << processVar->len / 8 << " bytes." << endl;

                firstSimple->setDataArraySize(firstSimple->getDataArraySize() + processSimple->getDataArraySize());
                firstSimple->setDataLen(firstSimple->getDataLen() + processSimple->getDataLen());
                firstSimple->setByteLength(firstSimple->getByteLength() + processSimple->getByteLength());
                /* copy data */
                for (uint32 i = 0; i < (processVar->len / 8); i++)
                    firstSimple->setData(i + (firstVar->len / 8), processSimple->getData(i));

                firstVar->len += processVar->len;

                delete processVar->userData;
                delete processVar;
            }

            firstVar->ebit = 1;

            sctpEV3 << "Reassembly done. Length=" << firstVar->len<<"\n";
            return firstVar->tsn;
        }
    }
    return tsn;
}
void SCTPReceiveStream::setExpectedStreamSeqNum ( const int32  num) [inline]
void SCTPReceiveStream::setStreamId ( const uint16  id) [inline]

Referenced by SCTPAssociation::initStreams().

{ streamId = id; };

Member Data Documentation

uint16 SCTPReceiveStream::streamId [protected]

Referenced by SCTPReceiveStream().


The documentation for this class was generated from the following files: