#include <TCPVirtualDataRcvQueue.h>
Inheritance diagram for TCPVirtualDataRcvQueue:
Public Member Functions | |
TCPVirtualDataRcvQueue () | |
virtual | ~TCPVirtualDataRcvQueue () |
virtual void | init (uint32 startSeq) |
virtual std::string | info () const |
virtual uint32 | insertBytesFromSegment (TCPSegment *tcpseg) |
virtual cMessage * | 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 |
Classes | |
struct | Region |
typedef std::list<Region> TCPVirtualDataRcvQueue::RegionList [protected] |
TCPVirtualDataRcvQueue::TCPVirtualDataRcvQueue | ( | ) |
cMessage * 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.
00130 { 00131 ulong numBytes = extractTo(seq); 00132 if (numBytes==0) 00133 return NULL; 00134 00135 cMessage *msg = new cMessage("data"); 00136 msg->setByteLength(numBytes); 00137 return msg; 00138 }
00141 { 00142 ASSERT(seqLE(seq,rcv_nxt)); 00143 00144 RegionList::iterator i = regionList.begin(); 00145 if (i==regionList.end()) 00146 return 0; 00147 00148 ASSERT(i->begin<i->end); // empty regions cannot exist 00149 00150 // seq below 1st region 00151 if (seqLE(seq,i->begin)) 00152 return 0; 00153 00154 if (seqLess(seq,i->end)) 00155 { 00156 // part of 1st region 00157 ulong octets = seq - i->begin; 00158 i->begin = seq; 00159 return octets; 00160 } 00161 else 00162 { 00163 // full 1st region 00164 ulong octets = i->end - i->begin; 00165 regionList.erase(i); 00166 return octets; 00167 } 00168 }
std::string TCPVirtualDataRcvQueue::info | ( | ) | const [virtual] |
Returns a string with region stored.
Reimplemented in TCPMsgBasedRcvQueue.
00040 { 00041 std::string res; 00042 char buf[32]; 00043 sprintf(buf, "rcv_nxt=%u ", rcv_nxt); 00044 res = buf; 00045 00046 for (RegionList::const_iterator i=regionList.begin(); i!=regionList.end(); ++i) 00047 { 00048 sprintf(buf, "[%u..%u) ", i->begin, i->end); 00049 res+=buf; 00050 } 00051 return res; 00052 }
void TCPVirtualDataRcvQueue::init | ( | uint32 | startSeq | ) | [virtual] |
Set initial receive sequence number.
Implements TCPReceiveQueue.
Reimplemented in TCPMsgBasedRcvQueue.
00035 { 00036 rcv_nxt = startSeq; 00037 }
uint32 TCPVirtualDataRcvQueue::insertBytesFromSegment | ( | TCPSegment * | tcpseg | ) | [virtual] |
Called when a TCP segment arrives. Returns sequence number for ACK.
Implements TCPReceiveQueue.
Reimplemented in TCPMsgBasedRcvQueue.
00055 { 00056 merge(tcpseg->sequenceNo(), tcpseg->sequenceNo()+tcpseg->payloadLength()); 00057 if (seqGE(rcv_nxt, regionList.begin()->begin)) 00058 rcv_nxt = regionList.begin()->end; 00059 return rcv_nxt; 00060 }
00063 { 00064 // Here we have to update our existing regions with the octet range 00065 // tcpseg represents. We either have to insert tcpseg as a separate region 00066 // somewhere, or (if it overlaps with an existing region) extend 00067 // existing regions; we also may have to merge existing regions if 00068 // they become overlapping (or touching) after adding tcpseg. 00069 00070 Region seg; 00071 seg.begin = segmentBegin; 00072 seg.end = segmentEnd; 00073 00074 RegionList::iterator i = regionList.begin(); 00075 if (i==regionList.end()) 00076 { 00077 // insert as first and only region 00078 regionList.insert(regionList.begin(), seg); 00079 return; 00080 } 00081 00082 // skip regions which fall entirely before seg (no overlap or touching) 00083 while (i!=regionList.end() && seqLess(i->end,seg.begin)) 00084 { 00085 ++i; 00086 } 00087 00088 if (i==regionList.end()) 00089 { 00090 // seg is entirely past last region: insert as separate region at end 00091 regionList.insert(regionList.end(), seg); 00092 return; 00093 } 00094 00095 if (seqLess(seg.end,i->begin)) 00096 { 00097 // segment entirely before region "i": insert as separate region before "i" 00098 regionList.insert(i, seg); 00099 return; 00100 } 00101 00102 if (seqLess(seg.begin,i->begin)) 00103 { 00104 // segment starts before region "i": extend region 00105 i->begin = seg.begin; 00106 } 00107 00108 if (seqLess(i->end,seg.end)) 00109 { 00110 // segment ends past end of region "i": extend region 00111 i->end = seg.end; 00112 00113 // maybe we have to merge region "i" with next one(s) 00114 RegionList::iterator j = i; 00115 ++j; 00116 while (j!=regionList.end() && seqGE(i->end,j->begin)) // while there's overlap 00117 { 00118 // if "j" is longer: extend "i" 00119 if (seqLess(i->end,j->end)) 00120 i->end = j->end; 00121 00122 // erase "j" (it was merged into "i") 00123 RegionList::iterator oldj = j++; 00124 regionList.erase(oldj); 00125 } 00126 } 00127 }
uint32 TCPVirtualDataRcvQueue::rcv_nxt [protected] |
RegionList TCPVirtualDataRcvQueue::regionList [protected] |