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