SCTPReceiveStream.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2008 Irene Ruengeler
00003 // Copyright (C) 2010 Thomas Dreibholz
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 #include "SCTPReceiveStream.h"
00020 #include "SCTPAssociation.h"
00021 
00022 
00023 SCTPReceiveStream::SCTPReceiveStream()
00024 {
00025     streamId                    = 0;
00026     expectedStreamSeqNum = 0;
00027     deliveryQ               = new SCTPQueue();
00028     orderedQ                    = new SCTPQueue();
00029     unorderedQ              = new SCTPQueue();
00030 }
00031 
00032 SCTPReceiveStream::~SCTPReceiveStream()
00033 {
00034     delete deliveryQ;
00035     delete orderedQ;
00036     delete unorderedQ;
00037 }
00038 
00039 uint32 SCTPReceiveStream::reassemble(SCTPQueue* queue, uint32 tsn)
00040 {
00041     uint32 begintsn = tsn, endtsn = 0;
00042 
00043     sctpEV3 << "Trying to reassemble message..." << endl;
00044 
00045     /* test if we have all fragments down to the first */
00046     while (orderedQ->getChunk(begintsn) && !(orderedQ->getChunk(begintsn))->bbit)
00047         begintsn--;
00048 
00049     if (orderedQ->getChunk(begintsn))
00050     {
00051         endtsn = begintsn;
00052 
00053         /* test if we have all fragments up to the end */
00054         while (orderedQ->getChunk(endtsn) && !(orderedQ->getChunk(endtsn))->ebit)
00055             endtsn++;
00056 
00057         if (orderedQ->getChunk(endtsn))
00058         {
00059             sctpEV3 << "All fragments found, now reassembling..." << endl;
00060 
00061             SCTPDataVariables *firstVar = orderedQ->getChunk(begintsn), *processVar;
00062             SCTPSimpleMessage* firstSimple=check_and_cast<SCTPSimpleMessage*>(firstVar->userData);
00063 
00064             sctpEV3 << "First fragment has " << firstVar->len / 8 << " bytes." << endl;
00065 
00066             while (++begintsn <= endtsn)
00067             {
00068                 processVar = orderedQ->getAndExtractChunk(begintsn);
00069                 SCTPSimpleMessage* processSimple=check_and_cast<SCTPSimpleMessage*>(processVar->userData);
00070 
00071                 sctpEV3 << "Adding fragment with " << processVar->len / 8 << " bytes." << endl;
00072 
00073                 firstSimple->setDataArraySize(firstSimple->getDataArraySize() + processSimple->getDataArraySize());
00074                 firstSimple->setDataLen(firstSimple->getDataLen() + processSimple->getDataLen());
00075                 firstSimple->setByteLength(firstSimple->getByteLength() + processSimple->getByteLength());
00076                 /* copy data */
00077                 for (uint32 i = 0; i < (processVar->len / 8); i++)
00078                     firstSimple->setData(i + (firstVar->len / 8), processSimple->getData(i));
00079 
00080                 firstVar->len += processVar->len;
00081 
00082                 delete processVar->userData;
00083                 delete processVar;
00084             }
00085 
00086             firstVar->ebit = 1;
00087 
00088             sctpEV3 << "Reassembly done. Length=" << firstVar->len<<"\n";
00089             return firstVar->tsn;
00090         }
00091     }
00092     return tsn;
00093 }
00094 
00095 
00096 uint32 SCTPReceiveStream::enqueueNewDataChunk(SCTPDataVariables* dchunk)
00097 {
00098     uint32 delivery = 0;      //0:orderedQ=false && deliveryQ=false; 1:orderedQ=true && deliveryQ=false; 2:oderedQ=true && deliveryQ=true; 3:fragment
00099 
00100     SCTPDataVariables* chunk;
00101     //sctpEV3 << "Enqueueing NEW data chunk (TSN="<<dchunk->tsn<<") for Stream ID "<<dchunk->sid<<"\n";
00102     /* append to the respective queue */
00103     if (!dchunk->ordered)
00104     {
00105         if (dchunk->bbit && dchunk->ebit)
00106         {
00107             /* put message into deliveryQ */
00108             if (deliveryQ->checkAndInsertChunk(dchunk->tsn, dchunk))
00109             {
00110                 delivery = 2;
00111             }
00112         } else {
00113             unorderedQ->checkAndInsertChunk(dchunk->tsn, dchunk);
00114             delivery = 3;
00115 
00116             /* try to reassemble here */
00117             uint32 reassembled = reassemble(unorderedQ, dchunk->tsn);
00118 
00119             if ((unorderedQ->getChunk(reassembled))->bbit && (unorderedQ->getChunk(reassembled))->bbit)
00120             {
00121                 /* put message into deliveryQ */
00122                 if (deliveryQ->checkAndInsertChunk(reassembled, unorderedQ->getAndExtractChunk(reassembled)))
00123                 {
00124                     delivery = 2;
00125                 }
00126             }
00127         }
00128     }
00129     else if (dchunk->ordered)
00130     {
00131         /* put message into streams ->reassembyQ */
00132         if (orderedQ->checkAndInsertChunk(dchunk->tsn, dchunk))
00133             delivery = 1;
00134 
00135         if (!dchunk->bbit || !dchunk->ebit)
00136         {
00137             delivery = 3;
00138             /* try to reassemble */
00139             reassemble(orderedQ, dchunk->tsn);
00140         }
00141 
00142         if (orderedQ->getQueueSize()>0)
00143         {
00144             /* dequeue first from orderedQ */
00145             chunk = orderedQ->dequeueChunkBySSN(expectedStreamSeqNum);
00146             if (chunk)
00147             {
00148                 if (deliveryQ->checkAndInsertChunk(chunk->tsn, chunk))
00149                 {
00150                     ++expectedStreamSeqNum;
00151                     if (expectedStreamSeqNum > 65535)
00152                         expectedStreamSeqNum = 0;
00153                     delivery = 2;
00154                 }
00155             }
00156         }
00157     }
00158 
00159     return delivery;
00160 }