00001 // 00002 // Copyright (C) 2004-2005 Andras Varga 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU Lesser General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU Lesser General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 00019 #include <omnetpp.h> 00020 #include <stdlib.h> 00021 #include <string.h> 00022 #include "ReassemblyBuffer.h" 00023 00024 00025 ReassemblyBuffer::ReassemblyBuffer() 00026 { 00027 main.beg = main.end = 0; 00028 main.islast = false; 00029 fragments = NULL; 00030 } 00031 00032 ReassemblyBuffer::~ReassemblyBuffer() 00033 { 00034 delete fragments; 00035 } 00036 00037 bool ReassemblyBuffer::addFragment(ushort beg, ushort end, bool islast) 00038 { 00039 merge(beg, end, islast); 00040 00041 // do we have the complete datagram? 00042 return main.beg==0 && main.islast; 00043 } 00044 00045 void ReassemblyBuffer::merge(ushort beg, ushort end, bool islast) 00046 { 00047 if (main.end==beg) 00048 { 00049 // most typical case (<95%): new fragment follows last one 00050 main.end = end; 00051 if (islast) 00052 main.islast = true; 00053 if (fragments) 00054 mergeFragments(); 00055 } 00056 else if (main.beg==end) 00057 { 00058 // new fragment precedes what we already have 00059 main.beg = beg; 00060 if (fragments) 00061 mergeFragments(); 00062 } 00063 else if (main.end<beg || main.beg>end) 00064 { 00065 // disjoint fragment, store it until another fragment fills in the gap 00066 if (!fragments) 00067 fragments = new RegionVector(); 00068 Region r; 00069 r.beg = beg; 00070 r.end = end; 00071 r.islast = islast; 00072 fragments->push_back(r); 00073 } 00074 else 00075 { 00076 // overlapping is not possible; 00077 // fragment's range already contained in buffer (probably duplicate fragment) 00078 } 00079 } 00080 00081 void ReassemblyBuffer::mergeFragments() 00082 { 00083 RegionVector& frags = *fragments; 00084 00085 bool oncemore; 00086 do 00087 { 00088 oncemore = false; 00089 for (RegionVector::iterator i=frags.begin(); i!=frags.end(); ) 00090 { 00091 bool deleteit = false; 00092 Region& frag = *i; 00093 if (main.end==frag.beg) 00094 { 00095 main.end = frag.end; 00096 if (frag.islast) 00097 main.islast = true; 00098 deleteit = true; 00099 } 00100 else if (main.beg==frag.end) 00101 { 00102 main.beg = frag.beg; 00103 deleteit = true; 00104 } 00105 else if (main.beg<=frag.beg && main.end>=frag.end) 00106 { 00107 // we already have this region (duplicate fragment), delete it 00108 deleteit = true; 00109 } 00110 00111 if (deleteit) 00112 { 00113 // deletion is tricky because erase() invalidates iterator 00114 int pos = i - frags.begin(); 00115 frags.erase(i); 00116 i = frags.begin() + pos; 00117 oncemore = true; 00118 } 00119 else 00120 { 00121 ++i; 00122 } 00123 } 00124 } 00125 while (oncemore); 00126 } 00127