INET Framework for OMNeT++/OMNEST
tcp_old::TCPVirtualDataRcvQueue Class Reference

#include <TCPVirtualDataRcvQueue_old.h>

Inheritance diagram for tcp_old::TCPVirtualDataRcvQueue:
tcp_old::TCPReceiveQueue tcp_old::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)

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> tcp_old::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 tcp_old::TCPReceiveQueue.

Reimplemented in tcp_old::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 tcp_old::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;
    }
}
std::string TCPVirtualDataRcvQueue::info ( ) const [virtual]

Returns a string with region stored.

Reimplemented in tcp_old::TCPMsgBasedRcvQueue.

{
    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 tcp_old::TCPReceiveQueue.

Reimplemented in tcp_old::TCPMsgBasedRcvQueue.

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

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

Implements tcp_old::TCPReceiveQueue.

Reimplemented in tcp_old::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: