INET Framework for OMNeT++/OMNEST
TCPVirtualDataRcvQueue Class Reference

#include <TCPVirtualDataRcvQueue.h>

Inheritance diagram for TCPVirtualDataRcvQueue:
TCPReceiveQueue TCPMsgBasedRcvQueue

List of all members.

Classes

struct  Region

Public Member Functions

 TCPVirtualDataRcvQueue ()
virtual ~TCPVirtualDataRcvQueue ()
virtual void init (uint32 startSeq)
virtual std::string info () const
virtual uint32 insertBytesFromSegment (TCPSegment *tcpseg)
virtual cPacket * extractBytesUpTo (uint32 seq)
virtual uint32 getAmountOfBufferedBytes ()
virtual uint32 getAmountOfFreeBytes (uint32 maxRcvBuffer)
virtual uint32 getQueueLength ()
virtual void getQueueStatus ()
virtual uint32 getLE (uint32 fromSeqNum)
virtual uint32 getRE (uint32 toSeqNum)

Protected Types

typedef std::list< RegionRegionList

Protected Member Functions

void merge (uint32 segmentBegin, uint32 segmentEnd)
ulong extractTo (uint32 toSeq)

Protected Attributes

uint32 rcv_nxt
RegionList regionList

Detailed Description

Receive queue that manages "virtual bytes", that is, byte counts only.

See also:
TCPVirtualDataSendQueue

Member Typedef Documentation

typedef std::list<Region> TCPVirtualDataRcvQueue::RegionList [protected]

Constructor & Destructor Documentation

TCPVirtualDataRcvQueue::TCPVirtualDataRcvQueue ( )

Ctor.

                                               : TCPReceiveQueue()
{
}
TCPVirtualDataRcvQueue::~TCPVirtualDataRcvQueue ( ) [virtual]

Virtual dtor.

{
}

Member Function Documentation

cPacket * TCPVirtualDataRcvQueue::extractBytesUpTo ( uint32  seq) [virtual]

Should create a packet to be passed up to the app, up to (but NOT including) the given sequence no (usually rcv_nxt). It should return NULL if there's no more data to be passed up -- this method is called several times until it returns NULL.

Implements TCPReceiveQueue.

Reimplemented in TCPMsgBasedRcvQueue.

{
    ulong numBytes = extractTo(seq);
    if (numBytes==0)
        return NULL;

    cPacket *msg = new cPacket("data");
    msg->setByteLength(numBytes);
    return msg;
}
ulong TCPVirtualDataRcvQueue::extractTo ( uint32  toSeq) [protected]

Referenced by extractBytesUpTo(), and TCPMsgBasedRcvQueue::extractBytesUpTo().

{
    ASSERT(seqLE(seq,rcv_nxt));

    RegionList::iterator i = regionList.begin();
    if (i==regionList.end())
        return 0;

    ASSERT(seqLess(i->begin,i->end)); // empty regions cannot exist

    // seq below 1st region
    if (seqLE(seq,i->begin))
        return 0;

    if (seqLess(seq,i->end))
    {
        // part of 1st region
        ulong octets = seq - i->begin;
        i->begin = seq;
        return octets;
    }
    else
    {
        // full 1st region
        ulong octets = i->end - i->begin;
        regionList.erase(i);
        return octets;
    }
}
uint32 TCPVirtualDataRcvQueue::getAmountOfBufferedBytes ( ) [virtual]

Returns the number of bytes (out-of-order-segments) currently buffered in queue.

Implements TCPReceiveQueue.

Referenced by getAmountOfFreeBytes().

{
    uint32 bytes=0;

    RegionList::iterator i = regionList.begin();
    if (i==regionList.end()) // is queue empty?
        return 0;

    while (i!=regionList.end())
    {
        bytes = bytes + (i->end - i->begin);
        i++;
    }
    return bytes;
}
uint32 TCPVirtualDataRcvQueue::getAmountOfFreeBytes ( uint32  maxRcvBuffer) [virtual]

Returns the number of bytes currently free (=available) in queue. freeRcvBuffer = maxRcvBuffer - usedRcvBuffer

Implements TCPReceiveQueue.

{
    uint32 usedRcvBuffer = getAmountOfBufferedBytes();
    uint32 freeRcvBuffer = maxRcvBuffer - usedRcvBuffer;
    return freeRcvBuffer;
}
uint32 TCPVirtualDataRcvQueue::getLE ( uint32  fromSeqNum) [virtual]

Returns left edge of enqueued region.

Implements TCPReceiveQueue.

{
    RegionList::iterator i = regionList.begin();
    while (i!=regionList.end())
    {
        if (seqLE(i->begin, fromSeqNum) && seqLE(fromSeqNum, i->end))
        {
//            tcpEV << "Enqueued region: [" << i->begin << ".." << i->end << ")\n";
            if (seqLess(i->begin, fromSeqNum))
                return i->begin;
            return fromSeqNum;
        }
        i++;
    }
    return fromSeqNum;
}
uint32 TCPVirtualDataRcvQueue::getQueueLength ( ) [virtual]

Returns the number of blocks currently buffered in queue.

Implements TCPReceiveQueue.

{
    return regionList.size();
}
void TCPVirtualDataRcvQueue::getQueueStatus ( ) [virtual]

Shows current queue status.

Implements TCPReceiveQueue.

{
    tcpEV << "receiveQLength=" << regionList.size() << " " << info() << "\n";
}
uint32 TCPVirtualDataRcvQueue::getRE ( uint32  toSeqNum) [virtual]

Returns right edge of enqueued region.

Implements TCPReceiveQueue.

{
    RegionList::iterator i = regionList.begin();
    while (i!=regionList.end())
    {
        if (seqLE(i->begin, toSeqNum) && seqLE(toSeqNum, i->end))
        {
//            tcpEV << "Enqueued region: [" << i->begin << ".." << i->end << ")\n";
            if (seqLess(toSeqNum, i->end))
                return i->end;
            return toSeqNum;
        }
        i++;
    }
    return toSeqNum;
}
std::string TCPVirtualDataRcvQueue::info ( ) const [virtual]

Returns a string with region stored.

Reimplemented in TCPMsgBasedRcvQueue.

Referenced by getQueueStatus().

{
    std::string res;
    char buf[32];
    sprintf(buf, "rcv_nxt=%u ", rcv_nxt);
    res = buf;

    for (RegionList::const_iterator i=regionList.begin(); i!=regionList.end(); ++i)
    {
        sprintf(buf, "[%u..%u) ", i->begin, i->end);
        res+=buf;
    }
    return res;
}
void TCPVirtualDataRcvQueue::init ( uint32  startSeq) [virtual]

Set initial receive sequence number.

Implements TCPReceiveQueue.

Reimplemented in TCPMsgBasedRcvQueue.

{
    rcv_nxt = startSeq;
}
uint32 TCPVirtualDataRcvQueue::insertBytesFromSegment ( TCPSegment tcpseg) [virtual]

Called when a TCP segment arrives. Returns sequence number for ACK.

Implements TCPReceiveQueue.

Reimplemented in TCPMsgBasedRcvQueue.

{
    merge(tcpseg->getSequenceNo(), tcpseg->getSequenceNo()+tcpseg->getPayloadLength());
    if (seqGE(rcv_nxt, regionList.begin()->begin))
        rcv_nxt = regionList.begin()->end;
    return rcv_nxt;
}
void TCPVirtualDataRcvQueue::merge ( uint32  segmentBegin,
uint32  segmentEnd 
) [protected]

Referenced by insertBytesFromSegment().

{
    // Here we have to update our existing regions with the octet range
    // tcpseg represents. We either have to insert tcpseg as a separate region
    // somewhere, or (if it overlaps with an existing region) extend
    // existing regions; we also may have to merge existing regions if
    // they become overlapping (or touching) after adding tcpseg.

    Region seg;
    seg.begin = segmentBegin;
    seg.end = segmentEnd;

    RegionList::iterator i = regionList.begin();
    if (i==regionList.end())
    {
        // insert as first and only region
        regionList.insert(regionList.begin(), seg);
        return;
    }

    // skip regions which fall entirely before seg (no overlap or touching)
    while (i!=regionList.end() && seqLess(i->end,seg.begin))
    {
        ++i;
    }

    if (i==regionList.end())
    {
        // seg is entirely past last region: insert as separate region at end
        regionList.insert(regionList.end(), seg);
        return;
    }

    if (seqLess(seg.end,i->begin))
    {
        // segment entirely before region "i": insert as separate region before "i"
        regionList.insert(i, seg);
        return;
    }

    if (seqLess(seg.begin,i->begin))
    {
        // segment starts before region "i": extend region
        i->begin = seg.begin;
    }

    if (seqLess(i->end,seg.end))
    {
        // segment ends past end of region "i": extend region
        i->end = seg.end;

        // maybe we have to merge region "i" with next one(s)
        RegionList::iterator j = i;
        ++j;
        while (j!=regionList.end() && seqGE(i->end,j->begin)) // while there's overlap
        {
            // if "j" is longer: extend "i"
            if (seqLess(i->end,j->end))
                i->end = j->end;

            // erase "j" (it was merged into "i")
            RegionList::iterator oldj = j++;
            regionList.erase(oldj);
        }
    }
}

Member Data Documentation


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