#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 |
|
|
|
|
|
Ctor. 00026 : TCPReceiveQueue() 00027 { 00028 }
|
|
|
Virtual dtor. 00031 {
00032 }
|
|
|
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 }
|
|
|
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 }
|
|
|
Set initial receive sequence number. Implements TCPReceiveQueue. Reimplemented in TCPMsgBasedRcvQueue. 00035 {
00036 rcv_nxt = startSeq;
00037 }
|
|
|
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 }
|
|
|
|
|
|
|
1.4.1