|
INET Framework for OMNeT++/OMNEST
|
#include <TCPVirtualDataRcvQueue_old.h>
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< Region > | RegionList |
Protected Member Functions | |
| void | merge (uint32 segmentBegin, uint32 segmentEnd) |
| ulong | extractTo (uint32 toSeq) |
Protected Attributes | |
| uint32 | rcv_nxt |
| RegionList | regionList |
Receive queue that manages "virtual bytes", that is, byte counts only.
typedef std::list<Region> tcp_old::TCPVirtualDataRcvQueue::RegionList [protected] |
| TCPVirtualDataRcvQueue::TCPVirtualDataRcvQueue | ( | ) |
Ctor.
: TCPReceiveQueue() { }
| TCPVirtualDataRcvQueue::~TCPVirtualDataRcvQueue | ( | ) | [virtual] |
Virtual dtor.
{
}
| 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 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);
}
}
}
uint32 tcp_old::TCPVirtualDataRcvQueue::rcv_nxt [protected] |
Referenced by extractTo(), info(), tcp_old::TCPMsgBasedRcvQueue::info(), insertBytesFromSegment(), and merge().