SCTP.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2005-2010 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 "SCTP.h"
00021 #include "SCTPAssociation.h"
00022 #include "SCTPCommand_m.h"
00023 #include "IPControlInfo.h"
00024 #include "IPv6ControlInfo.h"
00025 #include "IPDatagram.h"
00026 
00027 
00028 Define_Module(SCTP);
00029 
00030 
00031 bool SCTP::testing;
00032 bool SCTP::logverbose;
00033 
00034 int32 SCTP::nextConnId = 0;
00035 
00036 
00037 void SCTP::printInfoConnMap()
00038 {
00039     SCTPAssociation* assoc;
00040     SockPair      key;
00041     sctpEV3<<"Number of Assocs: "<<sizeConnMap<<"\n";
00042     if (sizeConnMap>0)
00043     {
00044         for (SctpConnMap::iterator i = sctpConnMap.begin(); i!=sctpConnMap.end(); ++i)
00045         {
00046             assoc = i->second;
00047             key = i->first;
00048 
00049                 sctpEV3<<"assocId: "<<assoc->assocId<<"  assoc: "<<assoc<<" src: "<<IPvXAddress(key.localAddr)<<" dst: "<<IPvXAddress(key.remoteAddr)<<" lPort: "<<key.localPort<<" rPort: "<<key.remotePort<<"\n";
00050 
00051         }
00052 
00053         sctpEV3<<"\n";
00054     }
00055 
00056 }
00057 
00058 void SCTP::printVTagMap()
00059 {
00060     int32 assocId;
00061     VTagPair      key;
00062     sctpEV3<<"Number of Assocs: "<<sctpVTagMap.size()<<"\n";
00063     if (sctpVTagMap.size()>0)
00064     {
00065         for (SctpVTagMap::iterator i = sctpVTagMap.begin(); i!=sctpVTagMap.end(); ++i)
00066         {
00067             assocId = i->first;
00068             key = i->second;
00069 
00070                 sctpEV3<<"assocId: "<<assocId<<" peerVTag: "<<key.peerVTag<<
00071                 " localVTag: "<<key.localVTag<<
00072                 " localPort: "<<key.localPort<<" rPort: "<<key.remotePort<<"\n";
00073         }
00074 
00075         sctpEV3<<"\n";
00076     }
00077 }
00078 
00079 void SCTP::bindPortForUDP()
00080 {
00081     EV << "Binding to UDP port " << 9899 << endl;
00082 
00083     cMessage *msg = new cMessage("UDP_C_BIND", UDP_C_BIND);
00084     UDPControlInfo *ctrl = new UDPControlInfo();
00085     ctrl->setSrcPort(9899);
00086     ctrl->setSockId(UDPSocket::generateSocketId());
00087     msg->setControlInfo(ctrl);
00088     send(msg, "to_ip");
00089 }
00090 
00091 void SCTP::initialize()
00092 {
00093     nextEphemeralPort = (uint16)(intrand(10000) + 30000);
00094 
00095     //sctpEV3<<"SCTPMain initialize\n";
00096 
00097     cModule *netw = simulation.getSystemModule();
00098 
00099     testing = netw->hasPar("testing") && netw->par("testing").boolValue();
00100     if(testing) {
00101     }
00102     if (netw->hasPar("testTimeout"))
00103     {
00104         testTimeout = (simtime_t)netw->par("testTimeout");
00105     }
00106     numPacketsReceived = 0;
00107     numPacketsDropped    = 0;
00108     sizeConnMap          = 0;
00109     if ((bool)par("udpEncapsEnabled"))
00110         bindPortForUDP();
00111 }
00112 
00113 
00114 SCTP::~SCTP()
00115 {
00116     sctpEV3<<"delete SCTPMain\n";
00117     if (!(sctpAppConnMap.empty()))
00118     {
00119         sctpEV3<<"clear appConnMap ptr="<<&sctpAppConnMap<<"\n";
00120         sctpAppConnMap.clear();
00121     }
00122     if (!(assocStatMap.empty()))
00123     {
00124         sctpEV3<<"clear assocStatMap ptr="<<&assocStatMap<<"\n";
00125         assocStatMap.clear();
00126     }
00127     if (!(sctpVTagMap.empty()))
00128     {
00129         sctpVTagMap.clear();
00130     }
00131     sctpEV3<<"after clearing maps\n";
00132 }
00133 
00134 
00135 void SCTP::handleMessage(cMessage *msg)
00136 {
00137     IPvXAddress destAddr;
00138     IPvXAddress srcAddr;
00139     IPControlInfo *controlInfo =NULL;
00140     IPv6ControlInfo *controlInfoV6 =NULL;
00141     bool findListen = false;
00142     bool bitError = false;
00143 
00144     sctpEV3<<"\n\nSCTPMain handleMessage at "<<getFullPath()<<"\n";
00145 
00146     if (msg->isSelfMessage())
00147     {
00148 
00149         sctpEV3<<"selfMessage\n";
00150 
00151          SCTPAssociation *assoc = (SCTPAssociation *) msg->getContextPointer();
00152         bool ret = assoc->processTimer(msg);
00153 
00154         if (!ret)
00155             removeAssociation(assoc);
00156     }
00157     else if (msg->arrivedOn("from_ip") || msg->arrivedOn("from_ipv6"))
00158     {
00159         sctpEV3<<"Message from IP\n";
00160         printInfoConnMap();
00161         if (!dynamic_cast<SCTPMessage *>(msg))
00162         {
00163             sctpEV3<<"no sctp message, delete it\n";
00164             delete msg;
00165             return;
00166         }
00167         SCTPMessage *sctpmsg = check_and_cast<SCTPMessage *>(msg);
00168 
00169         numPacketsReceived++;
00170 
00171         if ((sctpmsg->hasBitError() || !(sctpmsg->getChecksumOk()))) {
00172             sctpEV3<<"Packet has bit-error. delete it\n";
00173 
00174             bitError = true;
00175             numPacketsDropped++;
00176             delete msg;
00177             return;
00178         }
00179         if (msg->arrivedOn("from_ip"))
00180         {
00181             if (par("udpEncapsEnabled"))
00182             {
00183                 std::cout<<"Laenge SCTPMSG="<<sctpmsg->getByteLength()<<"\n";
00184                 UDPControlInfo *ctrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo());
00185                 srcAddr = ctrl->getSrcAddr();
00186                 destAddr = ctrl->getDestAddr();
00187                 std::cout<<"controlInfo srcAddr="<<srcAddr<<"  destAddr="<<destAddr<<"\n";
00188                 std::cout<<"VTag="<<sctpmsg->getTag()<<"\n";
00189             }
00190             else
00191             {
00192                 controlInfo = check_and_cast<IPControlInfo *>(msg->removeControlInfo());
00193                 IPDatagram *datagram = controlInfo->removeOrigDatagram();
00194                 delete datagram;
00195                 sctpEV3<<"controlInfo srcAddr="<<controlInfo->getSrcAddr()<<"   destAddr="<<controlInfo->getDestAddr()<<"\n";
00196                 srcAddr = controlInfo->getSrcAddr();
00197                 destAddr = controlInfo->getDestAddr();
00198             }
00199         }
00200         else
00201         {
00202             controlInfoV6 = check_and_cast<IPv6ControlInfo *>(msg->removeControlInfo());
00203             srcAddr = controlInfoV6->getSrcAddr();
00204             destAddr = controlInfoV6->getDestAddr();
00205         }
00206 
00207 
00208         sctpEV3<<"srcAddr="<<srcAddr<<" destAddr="<<destAddr<<"\n";
00209         if (sctpmsg->getBitLength()>(SCTP_COMMON_HEADER*8))
00210         {
00211             if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT || ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT_ACK )
00212                 findListen = true;
00213 
00214             SCTPAssociation *assoc = findAssocForMessage(srcAddr, destAddr, sctpmsg->getSrcPort(),sctpmsg->getDestPort(), findListen);
00215             if (!assoc && sctpConnMap.size()>0)
00216                 assoc = findAssocWithVTag(sctpmsg->getTag(),sctpmsg->getSrcPort(), sctpmsg->getDestPort());
00217             if (!assoc)
00218             {
00219                 sctpEV3<<"no assoc found msg="<<sctpmsg->getName()<<"\n";
00220                 if (bitError)
00221                 {
00222                     delete sctpmsg;
00223                     return;
00224                 }
00225                 if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==SHUTDOWN_ACK)
00226                     sendShutdownCompleteFromMain(sctpmsg, destAddr, srcAddr);
00227                 else if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()!=ABORT  &&
00228                     ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()!=SHUTDOWN_COMPLETE)
00229                 {
00230                     sendAbortFromMain(sctpmsg, destAddr, srcAddr);
00231                 }
00232                 delete sctpmsg;
00233             }
00234             else
00235             {
00236                 bool ret = assoc->processSCTPMessage(sctpmsg, srcAddr, destAddr);
00237                 if (!ret)
00238                 {
00239                     sctpEV3<<"SCTPMain:: removeAssociation \n";
00240                     removeAssociation(assoc);
00241                     delete sctpmsg;
00242                 }
00243                 else
00244                 {
00245                     delete sctpmsg;
00246                 }
00247             }
00248         }
00249         else
00250         {
00251             delete sctpmsg;
00252         }
00253     }
00254     else // must be from app
00255     {
00256         sctpEV3<<"must be from app\n";
00257         SCTPCommand *controlInfo = check_and_cast<SCTPCommand *>(msg->getControlInfo());
00258 
00259         int32 appGateIndex;
00260         if (controlInfo->getGate()!=-1)
00261             appGateIndex = controlInfo->getGate();
00262         else
00263             appGateIndex = msg->getArrivalGate()->getIndex();
00264         int32 assocId = controlInfo->getAssocId();
00265         sctpEV3<<"msg arrived from app for assoc "<<assocId<<"\n";
00266         SCTPAssociation *assoc = findAssocForApp(appGateIndex, assocId);
00267 
00268         if (!assoc)
00269         {
00270             sctpEV3 << "no assoc found. msg="<<msg->getName()<<" number of assocs = "<<assocList.size()<<"\n";
00271 
00272             if (strcmp(msg->getName(),"PassiveOPEN")==0 || strcmp(msg->getName(),"Associate")==0)
00273             {
00274                 if (assocList.size()>0)
00275                 {
00276                     assoc = NULL;
00277                     SCTPOpenCommand* open = check_and_cast<SCTPOpenCommand*>(controlInfo);
00278                     sctpEV3<<"Looking for assoc with remoteAddr="<<open->getRemoteAddr()<<", remotePort="<<open->getRemotePort()<<", localPort="<<open->getLocalPort()<<"\n";
00279                     for (std::list<SCTPAssociation*>::iterator iter=assocList.begin(); iter!=assocList.end(); iter++)
00280                     {
00281                         sctpEV3<<"remoteAddr="<<(*iter)->remoteAddr<<", remotePort="<<(*iter)->remotePort<<", localPort="<<(*iter)->localPort<<"\n";
00282                         if ((*iter)->remoteAddr == open->getRemoteAddr() && (*iter)->localPort==open->getLocalPort() && (*iter)->remotePort==open->getRemotePort())
00283                         {
00284                             assoc = (*iter);
00285                             break;
00286                         }
00287                     }
00288                 }
00289                 if (assoc==NULL)
00290                 {
00291                     assoc = new SCTPAssociation(this,appGateIndex,assocId);
00292 
00293                     AppConnKey key;
00294                     key.appGateIndex = appGateIndex;
00295                     key.assocId = assocId;
00296                     sctpAppConnMap[key] = assoc;
00297                     sctpEV3 << "SCTP association created for appGateIndex " << appGateIndex << " and assoc "<<assocId<<"\n";
00298                     bool ret = assoc->processAppCommand(PK(msg));
00299                     if (!ret)
00300                     {
00301                         removeAssociation(assoc);
00302                     }
00303                 }
00304             }
00305         }
00306         else
00307         {
00308             sctpEV3<<"assoc found\n";
00309             bool ret = assoc->processAppCommand(PK(msg));
00310 
00311             if (!ret)
00312                 removeAssociation(assoc);
00313         }
00314         delete msg;
00315     }
00316     if (ev.isGUI())
00317         updateDisplayString();
00318 }
00319 
00320 void SCTP::sendAbortFromMain(SCTPMessage* sctpmsg, IPvXAddress srcAddr, IPvXAddress destAddr)
00321 {
00322     SCTPMessage *msg = new SCTPMessage();
00323 
00324     sctpEV3<<"\n\nSCTPMain:sendABORT \n";
00325 
00326     msg->setSrcPort(sctpmsg->getDestPort());
00327     msg->setDestPort(sctpmsg->getSrcPort());
00328     msg->setBitLength(SCTP_COMMON_HEADER*8);
00329     msg->setChecksumOk(true);
00330 
00331     SCTPAbortChunk* abortChunk = new SCTPAbortChunk("ABORT");
00332     abortChunk->setChunkType(ABORT);
00333     if (sctpmsg->getChunksArraySize()>0 && ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT)
00334     {
00335 
00336         SCTPInitChunk* initChunk = check_and_cast<SCTPInitChunk *>(sctpmsg->getChunks(0));
00337         abortChunk->setT_Bit(0);
00338         msg->setTag(initChunk->getInitTag());
00339     }
00340     else
00341     {
00342         abortChunk->setT_Bit(1);
00343         msg->setTag(sctpmsg->getTag());
00344     }
00345     abortChunk->setBitLength(SCTP_ABORT_CHUNK_LENGTH*8);
00346     msg->addChunk(abortChunk);
00347     if ((bool)par("udpEncapsEnabled"))
00348     {
00349         msg->setKind(UDP_C_DATA);
00350         std::cout<<"VTag="<<msg->getTag()<<"\n";
00351         UDPControlInfo *ctrl = new UDPControlInfo();
00352         ctrl->setSrcPort(9899);
00353         ctrl->setDestAddr(destAddr.get4());
00354         ctrl->setDestPort(9899);
00355         msg->setControlInfo(ctrl);
00356     }
00357     else
00358     {
00359         IPControlInfo *controlInfo = new IPControlInfo();
00360         controlInfo->setProtocol(IP_PROT_SCTP);
00361         controlInfo->setSrcAddr(srcAddr.get4());
00362         controlInfo->setDestAddr(destAddr.get4());
00363         msg->setControlInfo(controlInfo);
00364     }
00365     send(msg,"to_ip");
00366 }
00367 
00368 void SCTP::sendShutdownCompleteFromMain(SCTPMessage* sctpmsg, IPvXAddress srcAddr, IPvXAddress destAddr)
00369 {
00370     SCTPMessage *msg = new SCTPMessage();
00371 
00372     sctpEV3<<"\n\nSCTP:sendABORT \n";
00373 
00374     msg->setSrcPort(sctpmsg->getDestPort());
00375     msg->setDestPort(sctpmsg->getSrcPort());
00376     msg->setBitLength(SCTP_COMMON_HEADER*8);
00377     msg->setChecksumOk(true);
00378 
00379     SCTPShutdownCompleteChunk* scChunk = new SCTPShutdownCompleteChunk("SHUTDOWN_COMPLETE");
00380     scChunk->setChunkType(SHUTDOWN_COMPLETE);
00381     scChunk->setTBit(1);
00382     msg->setTag(sctpmsg->getTag());
00383 
00384     scChunk->setBitLength(SCTP_SHUTDOWN_ACK_LENGTH*8);
00385     msg->addChunk(scChunk);
00386     IPControlInfo *controlInfo = new IPControlInfo();
00387     controlInfo->setProtocol(IP_PROT_SCTP);
00388     controlInfo->setSrcAddr(srcAddr.get4());
00389     controlInfo->setDestAddr(destAddr.get4());
00390     msg->setControlInfo(controlInfo);
00391     send(msg,"to_ip");
00392 }
00393 
00394 
00395 void SCTP::updateDisplayString()
00396 {
00397     if (ev.disable_tracing)
00398     {
00399         // in express mode, we don't bother to update the display
00400         // (std::map's iteration is not very fast if map is large)
00401         getDisplayString().setTagArg("t",0,"");
00402         return;
00403     }
00404 
00405 }
00406 
00407 SCTPAssociation *SCTP::findAssocWithVTag(uint32 peerVTag, uint32 remotePort, uint32 localPort)
00408 {
00409 
00410     printVTagMap();
00411     sctpEV3<<"findAssocWithVTag: peerVTag="<<peerVTag<<" srcPort="<<remotePort<<"    destPort="<<localPort<<"\n";
00412     printInfoConnMap();
00413 
00414     // try with fully qualified SockPair
00415     for (SctpVTagMap::iterator i=sctpVTagMap.begin(); i!=sctpVTagMap.end();i++)
00416     {
00417         if ((i->second.peerVTag==peerVTag && i->second.localPort==localPort
00418             && i->second.remotePort==remotePort)
00419             || (i->second.localVTag==peerVTag && i->second.localPort==localPort
00420             && i->second.remotePort==remotePort))
00421             return getAssoc(i->first);
00422     }
00423     return NULL;
00424 }
00425 
00426 SCTPAssociation *SCTP::findAssocForMessage(IPvXAddress srcAddr, IPvXAddress destAddr, uint32 srcPort, uint32 destPort, bool findListen)
00427 {
00428     SockPair key;
00429 
00430     key.localAddr = destAddr;
00431     key.remoteAddr = srcAddr;
00432     key.localPort = destPort;
00433     key.remotePort = srcPort;
00434     SockPair save = key;
00435     sctpEV3<<"findAssocForMessage: srcAddr="<<destAddr<<" destAddr="<<srcAddr<<" srcPort="<<destPort<<"  destPort="<<srcPort<<"\n";
00436     printInfoConnMap();
00437 
00438     // try with fully qualified SockPair
00439     SctpConnMap::iterator i;
00440     i = sctpConnMap.find(key);
00441     if (i!=sctpConnMap.end())
00442         return i->second;
00443 
00444 
00445     // try with localAddr missing (only localPort specified in passive/active open)
00446     key.localAddr.set("0.0.0.0");
00447 
00448     i = sctpConnMap.find(key);
00449     if (i!=sctpConnMap.end())
00450     {
00451 
00452         //sctpEV3<<"try with localAddr missing (only localPort specified in passive/active open)\n";
00453 
00454         return i->second;
00455     }
00456 
00457     if (findListen==true)
00458     {
00459         /*key = save;
00460         key.localPort = 0;
00461         key.localAddr.set("0.0.0.0");
00462         i = sctpConnMap.find(key);
00463         if (i!=sctpConnMap.end())
00464         {
00465             return i->second;
00466         }*/
00467 
00468 
00469         // try fully qualified local socket + blank remote socket (for incoming SYN)
00470         key = save;
00471         key.remoteAddr.set("0.0.0.0");
00472         key.remotePort = 0;
00473         i = sctpConnMap.find(key);
00474         if (i!=sctpConnMap.end())
00475         {
00476 
00477             //sctpEV3<<"try fully qualified local socket + blank remote socket \n";
00478 
00479             return i->second;
00480         }
00481 
00482 
00483         // try with blank remote socket, and localAddr missing (for incoming SYN)
00484         key.localAddr.set("0.0.0.0");
00485         i = sctpConnMap.find(key);
00486         if (i!=sctpConnMap.end())
00487         {
00488 
00489             //sctpEV3<<"try with blank remote socket, and localAddr missing \n";
00490 
00491             return i->second;
00492         }
00493     }
00494     // given up
00495 
00496     sctpEV3<<"giving up on trying to find assoc for localAddr="<<srcAddr<<" remoteAddr="<<destAddr<<" localPort="<<srcPort<<" remotePort="<<destPort<<"\n";
00497     return NULL;
00498 }
00499 
00500 SCTPAssociation *SCTP::findAssocForApp(int32 appGateIndex, int32 assocId)
00501 {
00502     AppConnKey key;
00503     key.appGateIndex = appGateIndex;
00504     key.assocId = assocId;
00505     sctpEV3<<"findAssoc for appGateIndex "<<appGateIndex<<" and assoc "<<assocId<<"\n";
00506     SctpAppConnMap::iterator i = sctpAppConnMap.find(key);
00507     return i==sctpAppConnMap.end() ? NULL : i->second;
00508 }
00509 
00510 uint16 SCTP::getEphemeralPort()
00511 {
00512     if (nextEphemeralPort==5000)
00513         error("Ephemeral port range 1024..4999 exhausted (email SCTP model "
00514                 "author that he should implement reuse of ephemeral ports!!!)");
00515     return nextEphemeralPort++;
00516 }
00517 
00518 void SCTP::updateSockPair(SCTPAssociation *conn, IPvXAddress localAddr, IPvXAddress remoteAddr, int32 localPort, int32 remotePort)
00519 {
00520     SockPair key;
00521     sctpEV3<<"updateSockPair:   localAddr: "<<localAddr<<"   remoteAddr="<<remoteAddr<<"    localPort="<<localPort<<" remotePort="<<remotePort<<"\n";
00522 
00523     key.localAddr = (conn->localAddr = localAddr);
00524     key.remoteAddr = (conn->remoteAddr = remoteAddr);
00525     key.localPort = conn->localPort = localPort;
00526     key.remotePort = conn->remotePort = remotePort;
00527 
00528     for (SctpConnMap::iterator i=sctpConnMap.begin(); i!=sctpConnMap.end(); i++)
00529     {
00530         if (i->second == conn)
00531         {
00532             sctpConnMap.erase(i);
00533             break;
00534         }
00535     }
00536 
00537     sctpEV3<<"updateSockPair conn="<<conn<<"    localAddr="<<key.localAddr<<"            remoteAddr="<<key.remoteAddr<<"     localPort="<<key.localPort<<"  remotePort="<<remotePort<<"\n";
00538 
00539     sctpConnMap[key] = conn;
00540     sizeConnMap = sctpConnMap.size();
00541     //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n";
00542     sctpEV3<<"assoc inserted in sctpConnMap\n";
00543     printInfoConnMap();
00544 }
00545 
00546 void SCTP::addLocalAddress(SCTPAssociation *conn, IPvXAddress address)
00547 {
00548 
00549         //sctpEV3<<"Add local address: "<<address<<"\n";
00550 
00551         SockPair key;
00552 
00553         key.localAddr = conn->localAddr;
00554         key.remoteAddr = conn->remoteAddr;
00555         key.localPort = conn->localPort;
00556         key.remotePort = conn->remotePort;
00557 
00558         SctpConnMap::iterator i = sctpConnMap.find(key);
00559         if (i!=sctpConnMap.end())
00560         {
00561             ASSERT(i->second==conn);
00562             if (key.localAddr.isUnspecified())
00563             {
00564                 sctpConnMap.erase(i);
00565                 sizeConnMap--;
00566             }
00567         }
00568         else
00569             sctpEV3<<"no actual sockPair found\n";
00570         key.localAddr = address;
00571         //key.localAddr = address.get4().getInt();
00572         // //sctpEV3<<"laddr="<<key.localAddr<<"    lp="<<key.localPort<<"  raddr="<<key.remoteAddr<<" rPort="<<key.remotePort<<"\n";
00573         sctpConnMap[key] = conn;
00574         sizeConnMap = sctpConnMap.size();
00575         sctpEV3<<"number of connections="<<sizeConnMap<<"\n";
00576 
00577         printInfoConnMap();
00578 }
00579 
00580 void SCTP::addLocalAddressToAllRemoteAddresses(SCTPAssociation *conn, IPvXAddress address, std::vector<IPvXAddress> remAddresses)
00581 {
00582 
00583         //sctpEV3<<"Add local address: "<<address<<"\n";
00584 
00585         SockPair key;
00586 
00587         for (AddressVector::iterator i=remAddresses.begin(); i!=remAddresses.end(); ++i)
00588         {
00589             //sctpEV3<<"remote address="<<(*i)<<"\n";
00590             key.localAddr = conn->localAddr;
00591             key.remoteAddr = (*i);
00592             key.localPort = conn->localPort;
00593             key.remotePort = conn->remotePort;
00594 
00595             SctpConnMap::iterator j = sctpConnMap.find(key);
00596             if (j!=sctpConnMap.end())
00597             {
00598             ASSERT(j->second==conn);
00599             if (key.localAddr.isUnspecified())
00600                     {
00601                     sctpConnMap.erase(j);
00602                     sizeConnMap--;
00603                 }
00604 
00605             }
00606             else
00607                 sctpEV3<<"no actual sockPair found\n";
00608             key.localAddr = address;
00609             sctpConnMap[key] = conn;
00610 
00611             sizeConnMap++;
00612             sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n";
00613 
00614             printInfoConnMap();
00615         }
00616 }
00617 
00618 void SCTP::removeLocalAddressFromAllRemoteAddresses(SCTPAssociation *conn, IPvXAddress address, std::vector<IPvXAddress> remAddresses)
00619 {
00620 
00621         //sctpEV3<<"Remove local address: "<<address<<"\n";
00622 
00623         SockPair key;
00624 
00625         for (AddressVector::iterator i=remAddresses.begin(); i!=remAddresses.end(); ++i)
00626         {
00627             //sctpEV3<<"remote address="<<(*i)<<"\n";
00628             key.localAddr = address;
00629             key.remoteAddr = (*i);
00630             key.localPort = conn->localPort;
00631             key.remotePort = conn->remotePort;
00632 
00633             SctpConnMap::iterator j = sctpConnMap.find(key);
00634             if (j!=sctpConnMap.end())
00635             {
00636                 ASSERT(j->second==conn);
00637                 sctpConnMap.erase(j);
00638                 sizeConnMap--;
00639             }
00640             else
00641                 sctpEV3<<"no actual sockPair found\n";
00642 
00643             //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n";
00644 
00645             printInfoConnMap();
00646         }
00647 }
00648 
00649 void SCTP::removeRemoteAddressFromAllConnections(SCTPAssociation *conn, IPvXAddress address, std::vector<IPvXAddress> locAddresses)
00650 {
00651 
00652         //sctpEV3<<"Remove remote address: "<<address<<"\n";
00653 
00654         SockPair key;
00655 
00656         for (AddressVector::iterator i=locAddresses.begin(); i!=locAddresses.end(); i++)
00657         {
00658             //sctpEV3<<"local address="<<(*i)<<"\n";
00659             key.localAddr = (*i);
00660             key.remoteAddr = address;
00661             key.localPort = conn->localPort;
00662             key.remotePort = conn->remotePort;
00663 
00664             SctpConnMap::iterator j = sctpConnMap.find(key);
00665             if (j!=sctpConnMap.end())
00666             {
00667                 ASSERT(j->second==conn);
00668                 sctpConnMap.erase(j);
00669                 sizeConnMap--;
00670             }
00671             else
00672                 sctpEV3<<"no actual sockPair found\n";
00673 
00674             //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n";
00675 
00676             printInfoConnMap();
00677         }
00678 }
00679 
00680 void SCTP::addRemoteAddress(SCTPAssociation *conn, IPvXAddress localAddress, IPvXAddress remoteAddress)
00681 {
00682 
00683     sctpEV3<<"Add remote Address: "<<remoteAddress<<" to local Address "<<localAddress<<"\n";
00684 
00685     SockPair key;
00686     key.localAddr = localAddress;
00687     key.remoteAddr = remoteAddress;
00688     key.localPort = conn->localPort;
00689     key.remotePort = conn->remotePort;
00690 
00691     SctpConnMap::iterator i = sctpConnMap.find(key);
00692     if (i!=sctpConnMap.end())
00693     {
00694         ASSERT(i->second==conn);
00695     }
00696     else
00697     {
00698 
00699         //sctpEV3<<"no actual sockPair found\n";
00700 
00701         sctpConnMap[key] = conn;
00702         sizeConnMap++;
00703     }
00704 
00705     //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n";
00706     printInfoConnMap();
00707 }
00708 
00709 void SCTP::addForkedAssociation(SCTPAssociation *assoc, SCTPAssociation *newAssoc, IPvXAddress localAddr, IPvXAddress remoteAddr, int32 localPort, int32 remotePort)
00710 {
00711     SockPair keyAssoc;
00712 
00713     ev<<"addForkedConnection assocId="<<assoc->assocId<<"    newId="<<newAssoc->assocId<<"\n";
00714 
00715     for (SctpConnMap::iterator j=sctpConnMap.begin(); j!=sctpConnMap.end(); ++j)
00716         if (assoc->assocId==j->second->assocId)
00717             keyAssoc = j->first;
00718     // update conn's socket pair, and register newConn (which'll keep LISTENing)
00719     updateSockPair(assoc, localAddr, remoteAddr, localPort, remotePort);
00720     updateSockPair(newAssoc, keyAssoc.localAddr, keyAssoc.remoteAddr, keyAssoc.localPort, keyAssoc.remotePort);
00721     // conn will get a new assocId...
00722     AppConnKey key;
00723     key.appGateIndex = assoc->appGateIndex;
00724     key.assocId = assoc->assocId;
00725     sctpAppConnMap.erase(key);
00726     key.assocId = assoc->assocId = getNewConnId();
00727     sctpAppConnMap[key] = assoc;
00728 
00729     // ...and newConn will live on with the old assocId
00730     key.appGateIndex = newAssoc->appGateIndex;
00731     key.assocId = newAssoc->assocId;
00732     sctpAppConnMap[key] = newAssoc;
00733     /*ev<<"assocId="<<assoc->assocId<<" remoteAddr="<<assoc->remoteAddr<<"\n";
00734     assoc->removeOldPath();*/
00735     printInfoConnMap();
00736 }
00737 
00738 
00739 
00740 void SCTP::removeAssociation(SCTPAssociation *conn)
00741 {
00742     bool            ok    = false;
00743     bool            find = false;
00744     const int32 id    = conn->assocId;
00745 
00746     sctpEV3 << "Deleting SCTP connection " << conn << " id= "<< id << endl;
00747 
00748     printInfoConnMap();
00749     if (sizeConnMap > 0) {
00750         AssocStatMap::iterator assocStatMapIterator = assocStatMap.find(conn->assocId);
00751         if (assocStatMapIterator != assocStatMap.end()) {
00752             assocStatMapIterator->second.stop        = simulation.getSimTime();
00753             assocStatMapIterator->second.lifeTime    = assocStatMapIterator->second.stop - assocStatMapIterator->second.start;
00754             assocStatMapIterator->second.throughput = assocStatMapIterator->second.ackedBytes*8 / assocStatMapIterator->second.lifeTime.dbl();
00755         }
00756         while (!ok) {
00757             if (sizeConnMap == 0) {
00758                 ok = true;
00759             }
00760             else {
00761                 for (SctpConnMap::iterator sctpConnMapIterator = sctpConnMap.begin();
00762                       sctpConnMapIterator != sctpConnMap.end(); sctpConnMapIterator++) {
00763                     if (sctpConnMapIterator->second != NULL) {
00764                         SCTPAssociation* assoc = sctpConnMapIterator->second;
00765                         if (assoc->assocId == conn->assocId) {
00766                             if (assoc->T1_InitTimer) {
00767                                 assoc->stopTimer(assoc->T1_InitTimer);
00768                             }
00769                             if (assoc->T2_ShutdownTimer) {
00770                                 assoc->stopTimer(assoc->T2_ShutdownTimer);
00771                             }
00772                             if (assoc->T5_ShutdownGuardTimer) {
00773                                 assoc->stopTimer(assoc->T5_ShutdownGuardTimer);
00774                             }
00775                             if (assoc->SackTimer) {
00776                                 assoc->stopTimer(assoc->SackTimer);
00777                             }
00778                             sctpConnMap.erase(sctpConnMapIterator);
00779                             sizeConnMap--;
00780                             find = true;
00781                             break;
00782                         }
00783                     }
00784                 }
00785             }
00786 
00787             if (!find) {
00788                 ok = true;
00789             }
00790             else {
00791                 find = false;
00792             }
00793         }
00794     }
00795 
00796     // T.D. 26.11.09: Write statistics
00797     char str[128];
00798     for (SCTPAssociation::SCTPPathMap::iterator pathMapIterator = conn->sctpPathMap.begin();
00799           pathMapIterator != conn->sctpPathMap.end(); pathMapIterator++) {
00800         const SCTPPathVariables* path = pathMapIterator->second;
00801         snprintf((char*)&str, sizeof(str), "Number of Fast Retransmissions %d:%s",
00802                  conn->assocId, path->remoteAddress.str().c_str());
00803         recordScalar(str, path->numberOfFastRetransmissions);
00804         snprintf((char*)&str, sizeof(str), "Number of Timer-Based Retransmissions %d:%s",
00805                  conn->assocId, path->remoteAddress.str().c_str());
00806         recordScalar(str, path->numberOfTimerBasedRetransmissions);
00807         snprintf((char*)&str, sizeof(str), "Number of Heartbeats Sent %d:%s",
00808                  conn->assocId, path->remoteAddress.str().c_str());
00809         recordScalar(str, path->numberOfHeartbeatsSent);
00810         snprintf((char*)&str, sizeof(str), "Number of Heartbeats Received %d:%s",
00811                  conn->assocId, path->remoteAddress.str().c_str());
00812         recordScalar(str, path->numberOfHeartbeatsRcvd);
00813         snprintf((char*)&str, sizeof(str), "Number of Heartbeat ACKs Sent %d:%s",
00814                  conn->assocId, path->remoteAddress.str().c_str());
00815         recordScalar(str, path->numberOfHeartbeatAcksSent);
00816         snprintf((char*)&str, sizeof(str), "Number of Heartbeat ACKs Received %d:%s",
00817                  conn->assocId, path->remoteAddress.str().c_str());
00818         recordScalar(str, path->numberOfHeartbeatAcksRcvd);
00819     }
00820 
00821 
00822     conn->removePath();
00823     conn->deleteStreams();
00824 
00825     // TD 20.11.09: Chunks may be in the transmission and retransmission queues simultaneously.
00826     //                   Remove entry from transmission queue if it is already in the retransmission queue.
00827     for (SCTPQueue::PayloadQueue::iterator i = conn->getRetransmissionQueue()->payloadQueue.begin();
00828           i != conn->getRetransmissionQueue()->payloadQueue.end(); i++) {
00829         SCTPQueue::PayloadQueue::iterator j = conn->getTransmissionQueue()->payloadQueue.find(i->second->tsn);
00830         if(j != conn->getTransmissionQueue()->payloadQueue.end()) {
00831             conn->getTransmissionQueue()->payloadQueue.erase(j);
00832         }
00833     }
00834      // TD 20.11.09: Now, both queues can be safely deleted.
00835     delete conn->getRetransmissionQueue();
00836     delete conn->getTransmissionQueue();
00837 
00838     AppConnKey key;
00839     key.appGateIndex = conn->appGateIndex;
00840     key.assocId       = conn->assocId;
00841     sctpAppConnMap.erase(key);
00842     assocList.remove(conn);
00843     delete conn;
00844 }
00845 
00846 SCTPAssociation* SCTP::getAssoc(int32 assocId)
00847 {
00848     for (SctpAppConnMap::iterator i = sctpAppConnMap.begin(); i!=sctpAppConnMap.end(); i++)
00849     {
00850         if (i->first.assocId==assocId)
00851             return i->second;
00852     }
00853     return NULL;
00854 }
00855 
00856 void SCTP::finish()
00857 {
00858     SctpConnMap::iterator connMapIterator = sctpConnMap.begin();
00859     while (connMapIterator != sctpConnMap.end()) {
00860         removeAssociation(connMapIterator->second);
00861         connMapIterator = sctpConnMap.begin();
00862     }
00863     ev << getFullPath() << ": finishing SCTP with "
00864         << sctpConnMap.size() << " connections open." << endl;
00865 
00866     for (AssocStatMap::const_iterator iterator = assocStatMap.begin();
00867           iterator != assocStatMap.end(); iterator++) {
00868         const SCTP::AssocStat& assoc = iterator->second;
00869 
00870         ev << "Association " << assoc.assocId << ": started at " << assoc.start
00871             << " and finished at " << assoc.stop << " --> lifetime: " << assoc.lifeTime << endl;
00872         ev << "Association " << assoc.assocId << ": sent bytes=" << assoc.sentBytes
00873             << ", acked bytes=" << assoc.ackedBytes<< ", throughput=" << assoc.throughput<< " bit/s" << endl;
00874         ev << "Association " << assoc.assocId << ": transmitted Bytes="
00875             << assoc.transmittedBytes<< ", retransmitted Bytes=" << assoc.transmittedBytes-assoc.ackedBytes<< endl;
00876         ev << "Association " << assoc.assocId << ": number of Fast RTX="
00877             << assoc.numFastRtx << ", number of Timer-Based RTX=" << assoc.numT3Rtx
00878             << ", path failures=" << assoc.numPathFailures<< ", ForwardTsns=" << assoc.numForwardTsn<< endl;
00879         ev << "AllMessages=" <<numPacketsReceived<< " BadMessages=" <<numPacketsDropped<< endl;
00880 
00881         recordScalar("Association Lifetime", assoc.lifeTime);
00882         recordScalar("Acked Bytes",          assoc.ackedBytes);
00883         recordScalar("Throughput [bit/s]",   assoc.throughput);
00884         recordScalar("Transmitted Bytes",    assoc.transmittedBytes);
00885         recordScalar("Fast RTX",                 assoc.numFastRtx);
00886         recordScalar("Timer-Based RTX",      assoc.numT3Rtx);
00887         recordScalar("Duplicate Acks",       assoc.numDups);
00888         recordScalar("Packets Received",         numPacketsReceived);
00889         recordScalar("Packets Dropped",      numPacketsDropped);
00890 
00891     }
00892 }