00001 // 00002 // Copyright (C) 2005-2009 Irene Ruengeler 00003 // Copyright (C) 2009-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 00020 #include "SCTPQueue.h" 00021 #include "SCTPAssociation.h" 00022 00023 Register_Class(SCTPQueue); 00024 00025 00026 SCTPQueue::SCTPQueue() 00027 { 00028 assoc = NULL; 00029 } 00030 00031 SCTPQueue::~SCTPQueue() 00032 { 00033 for (PayloadQueue::iterator iterator = payloadQueue.begin(); 00034 iterator != payloadQueue.end(); iterator++) { 00035 SCTPDataVariables* chunk = iterator->second; 00036 delete chunk->userData; 00037 } 00038 if (!payloadQueue.empty()) { 00039 payloadQueue.clear(); 00040 } 00041 } 00042 00043 bool SCTPQueue::checkAndInsertChunk(const uint32 key, SCTPDataVariables* chunk) 00044 { 00045 PayloadQueue::iterator found = payloadQueue.find(key); 00046 if (found != payloadQueue.end()) { 00047 return false; 00048 } 00049 payloadQueue[key] = chunk; 00050 return true; 00051 } 00052 00053 uint32 SCTPQueue::getQueueSize() const 00054 { 00055 return payloadQueue.size(); 00056 } 00057 00058 SCTPDataVariables* SCTPQueue::extractMessage() 00059 { 00060 if (!payloadQueue.empty()) { 00061 PayloadQueue::iterator iterator = payloadQueue.begin(); 00062 SCTPDataVariables* chunk = iterator->second; 00063 payloadQueue.erase(iterator); 00064 return chunk; 00065 } 00066 return NULL; 00067 } 00068 00069 SCTPDataVariables* SCTPQueue::getAndExtractChunk(const uint32 tsn) 00070 { 00071 if (!payloadQueue.empty()) { 00072 PayloadQueue::iterator iterator = payloadQueue.find(tsn); 00073 SCTPDataVariables* chunk = iterator->second; 00074 payloadQueue.erase(iterator); 00075 return chunk; 00076 } 00077 return NULL; 00078 } 00079 00080 void SCTPQueue::printQueue() const 00081 { 00082 sctpEV3 << "Queue contents:\n"; 00083 for (PayloadQueue::const_iterator iterator = payloadQueue.begin(); 00084 iterator != payloadQueue.end(); ++iterator) { 00085 const uint32 key = iterator->first; 00086 const SCTPDataVariables* chunk = iterator->second; 00087 sctpEV3 << key << ":\t" 00088 << "lastDestination=" << chunk->getLastDestination() 00089 << " nextDestination=" << chunk->getNextDestination() 00090 << " hasBeenAcked=" << chunk->hasBeenAcked 00091 << " countsAsOutstanding=" << chunk->countsAsOutstanding 00092 << " numberOfRetransmissions=" << chunk->numberOfRetransmissions 00093 << endl; 00094 } 00095 sctpEV3 << endl; 00096 } 00097 00098 SCTPDataVariables* SCTPQueue::getFirstChunk() const 00099 { 00100 PayloadQueue::const_iterator iterator = payloadQueue.begin(); 00101 SCTPDataVariables* chunk = iterator->second; 00102 return chunk; 00103 } 00104 00105 cMessage* SCTPQueue::getMsg(const uint32 tsn) const 00106 { 00107 PayloadQueue::const_iterator iterator = payloadQueue.find(tsn); 00108 if (iterator != payloadQueue.end()) { 00109 SCTPDataVariables* chunk = iterator->second; 00110 cMessage* msg = check_and_cast<cMessage*>(chunk->userData); 00111 return msg; 00112 } 00113 return NULL; 00114 } 00115 00116 SCTPDataVariables* SCTPQueue::getChunk(const uint32 tsn) const 00117 { 00118 PayloadQueue::const_iterator iterator = payloadQueue.find(tsn); 00119 if (iterator != payloadQueue.end()) { 00120 SCTPDataVariables* chunk = iterator->second; 00121 return chunk; 00122 } 00123 return NULL; 00124 } 00125 00126 SCTPDataVariables* SCTPQueue::getChunkFast(const uint32 tsn, bool& firstTime) 00127 { 00128 if(!firstTime) { 00129 if(GetChunkFastIterator != payloadQueue.end()) { 00130 SCTPDataVariables* chunk = GetChunkFastIterator->second; 00131 if(chunk->tsn == tsn) { 00132 GetChunkFastIterator++; 00133 return(chunk); // Found the right TSN! 00134 } 00135 } 00136 // TSN not found -> needs regular TSN lookup. 00137 } 00138 00139 GetChunkFastIterator = payloadQueue.find(tsn); 00140 if(GetChunkFastIterator != payloadQueue.end()) { 00141 SCTPDataVariables* chunk = GetChunkFastIterator->second; 00142 GetChunkFastIterator++; 00143 firstTime = false; 00144 return(chunk); 00145 } 00146 00147 return(NULL); 00148 } 00149 00150 00151 void SCTPQueue::removeMsg(const uint32 tsn) 00152 { 00153 PayloadQueue::iterator iterator = payloadQueue.find(tsn); 00154 payloadQueue.erase(iterator); 00155 } 00156 00157 bool SCTPQueue::deleteMsg(const uint32 tsn) 00158 { 00159 PayloadQueue::iterator iterator = payloadQueue.find(tsn); 00160 if (iterator != payloadQueue.end()) 00161 { 00162 SCTPDataVariables* chunk = iterator->second; 00163 cMessage* msg = check_and_cast<cMessage*>(chunk->userData); 00164 delete msg; 00165 payloadQueue.erase(iterator); 00166 return true; 00167 } 00168 return false; 00169 } 00170 00171 int32 SCTPQueue::getNumBytes() const 00172 { 00173 int32 qb = 0; 00174 for (PayloadQueue::const_iterator iterator = payloadQueue.begin(); 00175 iterator != payloadQueue.end(); iterator++) { 00176 qb += (iterator->second->len / 8); 00177 } 00178 return qb; 00179 } 00180 00181 SCTPDataVariables* SCTPQueue::dequeueChunkBySSN(const uint16 ssn) 00182 { 00183 for (PayloadQueue::iterator iterator = payloadQueue.begin(); 00184 iterator != payloadQueue.end(); iterator++) { 00185 SCTPDataVariables* chunk = iterator->second; 00186 if ((iterator->second->ssn == ssn) && 00187 (iterator->second->bbit) && 00188 (iterator->second->ebit) ) { 00189 payloadQueue.erase(iterator); 00190 return chunk; 00191 } 00192 } 00193 return NULL; 00194 } 00195 00196