ReassemblyBuffer.cc

Go to the documentation of this file.
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