SCTPSerializer.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2005 Christian Dankbar, Irene Ruengeler, Michael Tuexen, Andras Varga
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 <platdep/sockets.h>
00020 #include "headers/defs.h"
00021 namespace INETFw // load headers into a namespace, to avoid conflicts with platform definitions of the same stuff
00022 {
00023 #include "headers/bsdint.h"
00024 #include "headers/in.h"
00025 #include "headers/in_systm.h"
00026 #include "headers/ip.h"
00027 #include "headers/sctp.h"
00028 };
00029 
00030 #include "SCTPSerializer.h"
00031 #include "SCTPAssociation.h"
00032 //#include "platdep/intxtypes.h"
00033 
00034 #if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) && !defined(__CYGWIN__) && !defined(_WIN64)
00035 #include <netinet/in.h>  // htonl, ntohl, ...
00036 #include <arpa/inet.h>
00037 #include <sys/socket.h>
00038 #endif
00039 
00040 #include <sys/types.h>
00041 
00042 
00043 using namespace INETFw;
00044 
00045 
00046 
00047 int32 SCTPSerializer::serialize(const SCTPMessage *msg, unsigned char *buf, uint32 bufsize)
00048 {
00049     int32 size_init_chunk = sizeof(struct init_chunk);
00050     int32 size_sack_chunk = sizeof(struct sack_chunk);
00051     int32 size_heartbeat_chunk = sizeof(struct heartbeat_chunk);
00052     int32 size_heartbeat_ack_chunk = sizeof(struct heartbeat_ack_chunk);
00053     int32 size_chunk = sizeof(struct chunk);
00054 
00055 
00056     struct common_header *ch = (struct common_header*) (buf);
00057     uint32 writtenbytes = sizeof(struct common_header);
00058 
00059     // fill SCTP common header structure
00060     ch->source_port = htons(msg->getSrcPort());
00061     ch->destination_port = htons(msg->getDestPort());
00062     ch->verification_tag = htonl(msg->getTag());
00063 
00064 
00065     // SCTP chunks:
00066     int32 noChunks = msg->getChunksArraySize();
00067         for(int32 cc = 0; cc < noChunks; cc++)
00068         {
00069             const SCTPChunk *chunk = check_and_cast<SCTPChunk *>(((SCTPMessage *)msg)->getChunks(cc));
00070             unsigned char chunkType = chunk->getChunkType();
00071             switch(chunkType)
00072             {
00073                 case DATA:
00074                 {
00075                     //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: Data sent \n";
00076                     SCTPDataChunk *dataChunk = check_and_cast<SCTPDataChunk *>(chunk);
00077                     struct data_chunk *dc = (struct data_chunk*) (buf + writtenbytes); // append data to buffer
00078                     unsigned char flags = 0;
00079 
00080                     // fill buffer with data from SCTP data chunk structure
00081                     dc->type = dataChunk->getChunkType();
00082                     if (dataChunk->getUBit())
00083                         flags |= UNORDERED_BIT;
00084                     if (dataChunk->getBBit())
00085                         flags |= BEGIN_BIT;
00086                     if (dataChunk->getEBit())
00087                         flags |= END_BIT;
00088                     dc->flags = flags;
00089                     dc->length = htons(dataChunk->getByteLength());
00090                     dc->tsn = htonl(dataChunk->getTsn());
00091                     dc->sid = htons(dataChunk->getSid());
00092                     dc->ssn = htons(dataChunk->getSsn());
00093                     dc->ppi = htonl(dataChunk->getPpid());
00094                     writtenbytes += SCTP_DATA_CHUNK_LENGTH;
00095 
00096                     SCTPSimpleMessage *smsg = check_and_cast<SCTPSimpleMessage *>(dataChunk->getEncapsulatedMsg());
00097                         // T.D. 09.02.2010: Only copy data when there is something to copy!
00098                         const uint32 datalen = smsg->getDataLen();
00099                         if( smsg->getDataArraySize() >= datalen) {
00100                             for (uint32 i = 0; i < datalen; i++) {
00101                                 dc->user_data[i] = smsg->getData(i);
00102                             }
00103                         }
00104                         writtenbytes += ADD_PADDING(datalen);
00105                     break;
00106                 }
00107                 case INIT:
00108                 {
00109                     //sctpEV3<<"serialize INIT sizeKeyVector="<<sizeKeyVector<<"\n";
00110                     // source data from internal struct:
00111                     SCTPInitChunk *initChunk = check_and_cast<SCTPInitChunk *>(chunk);
00112                     //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: Init sent \n";
00113                     // destination is send buffer:
00114                     struct init_chunk *ic = (struct init_chunk*) (buf + writtenbytes); // append data to buffer
00115                     //buflen += (initChunk->getBitLength() / 8);
00116 
00117                     // fill buffer with data from SCTP init chunk structure
00118                     ic->type = initChunk->getChunkType();
00119                     ic->flags = 0; // no flags available in this type of SCTPChunk
00120                     ic->initiate_tag = htonl(initChunk->getInitTag());
00121                     ic->a_rwnd = htonl(initChunk->getA_rwnd());
00122                     ic->mos = htons(initChunk->getNoOutStreams());
00123                     ic->mis = htons(initChunk->getNoInStreams());
00124                     ic->initial_tsn = htonl(initChunk->getInitTSN());
00125                     int32 parPtr = 0;
00126                     // Var.-Len. Parameters
00127                     struct supported_address_types_parameter* sup_addr = (struct supported_address_types_parameter*) (((unsigned char *)ic) + size_init_chunk + parPtr);
00128                     sup_addr->type = htons(INIT_SUPPORTED_ADDRESS);
00129                     sup_addr->length = htons(6);
00130                     sup_addr->address_type = htons(INIT_PARAM_IPV4);
00131                     parPtr += 8;
00132                     int32 numaddr = initChunk->getAddressesArraySize();
00133                     for(int32 i=0; i<numaddr; i++)
00134                     {
00135                             struct init_ipv4_address_parameter *ipv4addr = (struct init_ipv4_address_parameter*) (((unsigned char *)ic) + size_init_chunk + parPtr);
00136                             ipv4addr->type = htons(INIT_PARAM_IPV4);
00137                             ipv4addr->length = htons(8);
00138                             ipv4addr->address = htonl(initChunk->getAddresses(i).get4().getInt());
00139                             parPtr += sizeof(struct init_ipv4_address_parameter);
00140                     }
00141                     ic->length = htons(SCTP_INIT_CHUNK_LENGTH+parPtr);
00142                     writtenbytes += SCTP_INIT_CHUNK_LENGTH+parPtr;
00143                     break;
00144                 }
00145                 case INIT_ACK:
00146                 {
00147                     //sctpEV3<<"serialize INIT_ACK sizeKeyVector="<<sizeKeyVector<<"\n";
00148                     SCTPInitAckChunk *initAckChunk = check_and_cast<SCTPInitAckChunk *>(chunk);
00149                     //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: InitAck sent \n";
00150                     // destination is send buffer:
00151                     struct init_ack_chunk *iac = (struct init_ack_chunk*) (buf + writtenbytes); // append data to buffer
00152                     // fill buffer with data from SCTP init ack chunk structure
00153                     iac->type = initAckChunk->getChunkType();
00154 //                  iac->flags = initAckChunk->getFlags(); // no flags available in this type of SCTPChunk
00155                     iac->initiate_tag = htonl(initAckChunk->getInitTag());
00156                     iac->a_rwnd = htonl(initAckChunk->getA_rwnd());
00157                     iac->mos = htons(initAckChunk->getNoOutStreams());
00158                     iac->mis = htons(initAckChunk->getNoInStreams());
00159                     iac->initial_tsn = htonl(initAckChunk->getInitTSN());
00160                     // Var.-Len. Parameters
00161                     int32 parPtr=0;
00162 
00163                     struct supported_address_types_parameter* sup_addr = (struct supported_address_types_parameter*) (((unsigned char *)iac) + size_init_chunk + parPtr);
00164                     sup_addr->type = htons(INIT_SUPPORTED_ADDRESS);
00165                     sup_addr->length = htons(6);
00166                     sup_addr->address_type = htons(INIT_PARAM_IPV4);
00167                     parPtr += 8;
00168 
00169 
00170                     int32 numaddr = initAckChunk->getAddressesArraySize();
00171                     for(int32 i=0; i<numaddr; i++)
00172                     {
00173                         struct init_ipv4_address_parameter *ipv4addr = (struct init_ipv4_address_parameter*) (((unsigned char *)iac) + size_init_chunk + parPtr);
00174                         ipv4addr->type = htons(INIT_PARAM_IPV4);
00175                         ipv4addr->length = htons(8);
00176                         ipv4addr->address = htonl(initAckChunk->getAddresses(i).get4().getInt());
00177                         parPtr += 8;
00178                     }
00179                     uint32 uLen = initAckChunk->getUnrecognizedParametersArraySize();
00180                     if (uLen>0)
00181                     {
00182                         //sctpEV3<<"uLen="<<uLen<<"\n";
00183                         int32 k=0;
00184                         uint32 pLen=0;
00185                         while (uLen>0)
00186                         {
00187                             struct tlv* unknown = (struct tlv*) (((unsigned char *)iac) + size_init_chunk + parPtr);
00188                             unknown->type = htons(UNRECOGNIZED_PARAMETER);
00189                             pLen = initAckChunk->getUnrecognizedParameters(k+2)*16+initAckChunk->getUnrecognizedParameters(k+3);
00190                             unknown->length = htons(pLen+4);
00191                             //sctpEV3<<"unknown->length="<<pLen<<"\n";
00192                             for (uint32 i=0; i<ADD_PADDING(pLen); i++,k++)
00193                                 unknown->value[i] = initAckChunk->getUnrecognizedParameters(k);
00194                             parPtr += ADD_PADDING(pLen+4);
00195                             uLen-=ADD_PADDING(pLen);
00196                         }
00197                     }
00198 
00199                     /*if(cookielen == 0)
00200                     {
00201                         cookielen = 4;
00202                         initAckChunk->setCookieArraySize(cookielen);
00203                         initAckChunk->setCookie(0, '1');
00204                         initAckChunk->setCookie(1, '3');
00205                         initAckChunk->setCookie(2, '3');
00206                         initAckChunk->setCookie(3, '7');
00207                         iac->length = htons(ntohs(iac->length) + 8);
00208                     }*/
00209                     int32 cookielen = initAckChunk->getCookieArraySize();
00210                     if (cookielen == 0)
00211                     {
00212                         SCTPCookie* stateCookie = check_and_cast<SCTPCookie*>(initAckChunk->getStateCookie());
00213                         struct init_cookie_parameter *cookie = (struct init_cookie_parameter*) (((unsigned char *)iac) + size_init_chunk + parPtr);
00214                         cookie->type = htons(INIT_PARAM_COOKIE);
00215                         cookie->length = htons(SCTP_COOKIE_LENGTH + 4);
00216                         cookie->creationTime = htonl((uint32)stateCookie->getCreationTime().dbl());
00217                         cookie->localTag = htonl(stateCookie->getLocalTag());
00218                         cookie->peerTag = htonl(stateCookie->getPeerTag());
00219                         for(int32 i=0; i<32; i++)
00220                         {
00221                             cookie->localTieTag[i] = stateCookie->getLocalTieTag(i);
00222                             cookie->peerTieTag[i] = stateCookie->getPeerTieTag(i);
00223                         }
00224                         parPtr += (SCTP_COOKIE_LENGTH + 4);
00225                     }
00226                     else
00227                     {
00228                         struct tlv *cookie = (struct tlv*) (((unsigned char *)iac) + size_init_chunk + parPtr);
00229                         cookie->type = htons(INIT_PARAM_COOKIE);
00230                         cookie->length = htons(cookielen+4);
00231                         for(int32 i=0; i<cookielen; i++)
00232                             cookie->value[i] = initAckChunk->getCookie(i);
00233                         parPtr += cookielen + 4;
00234                     }
00235                     iac->length = htons(SCTP_INIT_CHUNK_LENGTH+parPtr);
00236                     writtenbytes += SCTP_INIT_CHUNK_LENGTH+parPtr;
00237                     break;
00238                 }
00239                 case SACK:
00240                 {
00241                     SCTPSackChunk *sackChunk = check_and_cast<SCTPSackChunk *>(chunk);
00242 
00243                     // destination is send buffer:
00244                     struct sack_chunk *sac = (struct sack_chunk*) (buf + writtenbytes); // append data to buffer
00245                     writtenbytes += (sackChunk->getBitLength() / 8);
00246 
00247                     // fill buffer with data from SCTP init ack chunk structure
00248                     sac->type = sackChunk->getChunkType();
00249 //                  sac->flags = sackChunk->getFlags(); // no flags available in this type of SCTPChunk
00250                     sac->length = htons(sackChunk->getBitLength() / 8);
00251                     uint32 cumtsnack = sackChunk->getCumTsnAck();
00252                     sac->cum_tsn_ack = htonl(cumtsnack);
00253                     sac->a_rwnd = htonl(sackChunk->getA_rwnd());
00254                     sac->nr_of_gaps = htons(sackChunk->getNumGaps());
00255                     sac->nr_of_dups = htons(sackChunk->getNumDupTsns());
00256 
00257                     // GAPs and Dup. TSNs:
00258                     int32 numgaps = sackChunk->getNumGaps();
00259                     int32 numdups = sackChunk->getNumDupTsns();
00260                     for(int32 i=0; i<numgaps; i++)
00261                     {
00262                         struct sack_gap *gap = (struct sack_gap*) (((unsigned char *)sac) + size_sack_chunk + i*sizeof(struct sack_gap));
00263                         gap->start = htons(sackChunk->getGapStart(i) - cumtsnack);
00264                         gap->stop = htons(sackChunk->getGapStop(i) - cumtsnack);
00265                     }
00266                     for(int32 i=0; i<numdups; i++)
00267                     {
00268                         struct sack_duptsn *dup = (struct sack_duptsn*) (((unsigned char *)sac) + size_sack_chunk + numgaps*sizeof(struct sack_gap) + i*sizeof(sack_duptsn));
00269                         dup->tsn = htonl(sackChunk->getDupTsns(i));
00270                     }
00271                     break;
00272                 }
00273                 case HEARTBEAT:
00274                 {
00275                     //sctpEV3<<simulation.simTime()<<"  SCTPAssociation:: Heartbeat sent \n";
00276                     SCTPHeartbeatChunk *heartbeatChunk = check_and_cast<SCTPHeartbeatChunk *>(chunk);
00277 
00278                     // destination is send buffer:
00279                     struct heartbeat_chunk *hbc = (struct heartbeat_chunk*) (buf + writtenbytes); // append data to buffer
00280                     writtenbytes += (heartbeatChunk->getBitLength() / 8);
00281 
00282                     // fill buffer with data from SCTP init ack chunk structure
00283                     hbc->type = heartbeatChunk->getChunkType();
00284 //                  hbc->flags = heartbeatChunk->getFlags(); // no flags available in this type of SCTPChunk
00285                     hbc->length = htons(heartbeatChunk->getBitLength() / 8);
00286 
00287                     // deliver info:
00288                     struct heartbeat_info *hbi = (struct heartbeat_info*) (((unsigned char*)hbc) + size_heartbeat_chunk);
00289                     IPvXAddress addr = heartbeatChunk->getRemoteAddr();
00290                     simtime_t time = heartbeatChunk->getTimeField();
00291                     int32 infolen = sizeof(addr.get4().getInt()) + sizeof(uint32);
00292                     hbi->type = htons(1);   // mandatory
00293                     hbi->length = htons(infolen+4);
00294                     HBI_ADDR(hbi) = htonl(addr.get4().getInt());
00295                     HBI_TIME(hbi) = htonl((uint32)time.dbl());
00296                     break;
00297                 }
00298                 case HEARTBEAT_ACK:
00299                 {
00300                     //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: HeartbeatAck sent \n";
00301                     SCTPHeartbeatAckChunk *heartbeatAckChunk = check_and_cast<SCTPHeartbeatAckChunk *>(chunk);
00302 
00303                     // destination is send buffer:
00304                     struct heartbeat_ack_chunk *hbac = (struct heartbeat_ack_chunk*) (buf + writtenbytes); // append data to buffer
00305                     writtenbytes += (heartbeatAckChunk->getBitLength() / 8);
00306 
00307                     // fill buffer with data from SCTP init ack chunk structure
00308                     hbac->type = heartbeatAckChunk->getChunkType();
00309 //                  hbac->flags = heartbeatAckChunk->getFlags(); // no flags available in this type of SCTPChunk
00310                     hbac->length = htons(heartbeatAckChunk->getBitLength() / 8);
00311 
00312                     // deliver info:
00313                     struct heartbeat_info *hbi = (struct heartbeat_info*) (((unsigned char*)hbac) + size_heartbeat_ack_chunk);
00314                     int32 infolen = heartbeatAckChunk->getInfoArraySize();
00315                     hbi->type = htons(1); //mandatory
00316                     if (infolen > 0)
00317                     {
00318                         hbi->length = htons(infolen+4);
00319                         for(int32 i=0; i<infolen; i++)
00320                         {
00321                             HBI_INFO(hbi)[i] = heartbeatAckChunk->getInfo(i);
00322                         }
00323                     }
00324                     else
00325                     {
00326                         IPvXAddress addr = heartbeatAckChunk->getRemoteAddr();
00327                         infolen = sizeof(addr.get4().getInt()) + sizeof(uint32);
00328                         hbi->type = htons(1);   // mandatory
00329                         hbi->length = htons(infolen+4);
00330 
00331                         simtime_t time = heartbeatAckChunk->getTimeField();
00332                         HBI_ADDR(hbi) = htonl(addr.get4().getInt());
00333                         HBI_TIME(hbi) = htonl((uint32)time.dbl());
00334                     }
00335                     break;
00336                 }
00337                 case ABORT:
00338                 {
00339                     //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: Abort sent \n";
00340                     SCTPAbortChunk *abortChunk = check_and_cast<SCTPAbortChunk *>(chunk);
00341 
00342                     // destination is send buffer:
00343                     struct abort_chunk *ac = (struct abort_chunk*) (buf + writtenbytes); // append data to buffer
00344                     writtenbytes += (abortChunk->getBitLength() / 8);
00345 
00346                     // fill buffer with data from SCTP init ack chunk structure
00347                     ac->type = abortChunk->getChunkType();
00348                     unsigned char flags = 0;
00349                     if(abortChunk->getT_Bit())
00350                         flags |= T_BIT;
00351                     ac->flags = flags;
00352                     ac->length = htons(abortChunk->getBitLength() / 8);
00353                     break;
00354                 }
00355                 case COOKIE_ECHO:
00356                 {
00357                     //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: CookieEcho sent \n";
00358                     SCTPCookieEchoChunk *cookieChunk = check_and_cast<SCTPCookieEchoChunk *>(chunk);
00359 
00360                     struct cookie_echo_chunk *cec = (struct cookie_echo_chunk*) (buf + writtenbytes);
00361 
00362 
00363                     cec->type = cookieChunk->getChunkType();
00364                     cec->length = htons(cookieChunk->getBitLength() / 8);
00365                     int32 cookielen = cookieChunk->getCookieArraySize();
00366                     if (cookielen>0)
00367                     {
00368                         for(int32 i=0; i<cookielen; i++)
00369                             cec->state_cookie[i] = cookieChunk->getCookie(i);
00370                     }
00371                     else
00372                     {
00373                         SCTPCookie* stateCookie = check_and_cast<SCTPCookie*>(cookieChunk->getStateCookie());
00374                         struct cookie_parameter *cookie = (struct cookie_parameter*) (buf + writtenbytes+4);
00375                         cookie->creationTime = htonl((uint32)stateCookie->getCreationTime().dbl());
00376                         cookie->localTag = htonl(stateCookie->getLocalTag());
00377                         cookie->peerTag = htonl(stateCookie->getPeerTag());
00378                         for(int32 i=0; i<32; i++)
00379                         {
00380                             cookie->localTieTag[i] = stateCookie->getLocalTieTag(i);
00381                             cookie->peerTieTag[i] = stateCookie->getPeerTieTag(i);
00382                         }
00383                     }
00384                     writtenbytes += (ADD_PADDING(cookieChunk->getBitLength() / 8));
00385                     //sctpEV3<<"buflen cookie_echo="<<buflen<<"\n";
00386                     uint32 uLen = cookieChunk->getUnrecognizedParametersArraySize();
00387                     if (uLen>0)
00388                     {
00389                         //sctpEV3<<"uLen="<<uLen<<"\n";
00390                         struct error_chunk* error = (struct error_chunk*)(buf + writtenbytes);
00391                         error->type = ERRORTYPE;
00392                         error->flags = 0;
00393                         int32 k=0;
00394                         uint32 pLen=0;
00395                         uint32 ecLen = SCTP_ERROR_CHUNK_LENGTH;
00396                         uint32 ecParPtr = 0;
00397                         while (uLen>0)
00398                         {
00399                             struct tlv* unknown = (struct tlv*) (((unsigned char *)error) + sizeof(struct error_chunk) + ecParPtr);
00400                             unknown->type = htons(UNRECOGNIZED_PARAMETER);
00401                             pLen = cookieChunk->getUnrecognizedParameters(k+2)*16+cookieChunk->getUnrecognizedParameters(k+3);
00402                             unknown->length = htons(pLen+4);
00403                             ecLen += pLen+4;
00404                             //sctpEV3<<"plength="<<pLen<<" ecLen="<<ecLen<<"\n";
00405                             for (uint32 i=0; i<ADD_PADDING(pLen); i++,k++)
00406                                 unknown->value[i] = cookieChunk->getUnrecognizedParameters(k);
00407                             ecParPtr += ADD_PADDING(pLen+4);
00408                             //sctpEV3<<"ecParPtr="<<ecParPtr<<"\n";
00409                             uLen-=ADD_PADDING(pLen);
00410                         }
00411                         error->length = htons(ecLen);
00412                         writtenbytes += SCTP_ERROR_CHUNK_LENGTH+ecParPtr;
00413                     }
00414 
00415                     break;
00416                 }
00417                 case COOKIE_ACK:
00418                 {
00419                     //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: CookieAck sent \n";
00420                     SCTPCookieAckChunk *cookieAckChunk = check_and_cast<SCTPCookieAckChunk *>(chunk);
00421 
00422                     struct cookie_ack_chunk *cac = (struct cookie_ack_chunk*) (buf + writtenbytes);
00423                     writtenbytes += (cookieAckChunk->getBitLength() / 8);
00424 
00425                     cac->type = cookieAckChunk->getChunkType();
00426                     cac->length = htons(cookieAckChunk->getBitLength() / 8);
00427 
00428                     break;
00429                 }
00430                 case SHUTDOWN:
00431                 {
00432                     //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: ShutdownAck sent \n";
00433                     SCTPShutdownChunk *shutdownChunk = check_and_cast<SCTPShutdownChunk *>(chunk);
00434 
00435                     struct shutdown_chunk *sac = (struct shutdown_chunk*) (buf + writtenbytes);
00436                     writtenbytes += (shutdownChunk->getBitLength() / 8);
00437 
00438                     sac->type = shutdownChunk->getChunkType();
00439                     sac->cumulative_tsn_ack = htonl(shutdownChunk->getCumTsnAck());
00440                     sac->length = htons(shutdownChunk->getBitLength() / 8);
00441 
00442                     break;
00443                 }
00444                 case SHUTDOWN_ACK:
00445                 {
00446                     //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: ShutdownAck sent \n";
00447                     SCTPShutdownAckChunk *shutdownAckChunk = check_and_cast<SCTPShutdownAckChunk *>(chunk);
00448 
00449                     struct shutdown_ack_chunk *sac = (struct shutdown_ack_chunk*) (buf + writtenbytes);
00450                     writtenbytes += (shutdownAckChunk->getBitLength() / 8);
00451 
00452                     sac->type = shutdownAckChunk->getChunkType();
00453                     sac->length = htons(shutdownAckChunk->getBitLength() / 8);
00454 
00455                     break;
00456                 }
00457                 case SHUTDOWN_COMPLETE:
00458                 {
00459                     //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: ShutdownAck sent \n";
00460                     SCTPShutdownCompleteChunk *shutdownCompleteChunk = check_and_cast<SCTPShutdownCompleteChunk *>(chunk);
00461 
00462                     struct shutdown_complete_chunk *sac = (struct shutdown_complete_chunk*) (buf + writtenbytes);
00463                     writtenbytes += (shutdownCompleteChunk->getBitLength() / 8);
00464 
00465                     sac->type = shutdownCompleteChunk->getChunkType();
00466                     sac->length = htons(shutdownCompleteChunk->getBitLength() / 8);
00467                     unsigned char flags = 0;
00468                     if(shutdownCompleteChunk->getTBit())
00469                         flags |= T_BIT;
00470                     sac->flags = flags;
00471                     break;
00472                 }
00473                 case ERRORTYPE:
00474                 {
00475                     SCTPErrorChunk* errorchunk = check_and_cast<SCTPErrorChunk*>(chunk);
00476                     struct error_chunk* error = (struct error_chunk*)(buf + writtenbytes);
00477                     error->type = errorchunk->getChunkType();
00478                     error->flags = 0;
00479 
00480                     if (errorchunk->getParametersArraySize()>0)
00481                     {
00482                         writtenbytes += size_chunk;
00483                     }
00484                     else
00485                         writtenbytes += ADD_PADDING(error->length);
00486                     break;
00487                 }
00488                 default:
00489                     printf("Serialize TODO: Implement for outgoing chunk type %d!\n", chunkType);
00490                     throw new cRuntimeError("TODO: unknown chunktype in outgoing packet on external interface! Implement it!");
00491                 // break;
00492 
00493             }
00494 
00495             /*drop(chunk);
00496             delete chunk;*/
00497 
00498         }
00499     // finally, set the CRC32 checksum field in the SCTP common header
00500 
00501     /*sctpEV3<<"srcport="<<msg->getSrcPort() <<"destport="<<msg->getDestPort() <<"writtenbytes vor checksum="<<writtenbytes<<"\n";*/
00502 
00503     ch->checksum = checksum((unsigned char*)ch, writtenbytes);
00504     return writtenbytes;
00505 }
00506 
00507 uint32 SCTPSerializer::checksum(const uint8_t *buf, register uint32 len)
00508 {
00509     uint32 h;
00510     unsigned char byte0, byte1, byte2, byte3;
00511     uint32 crc32c;
00512     register uint32 i;
00513     register uint32 res = (~0L);
00514     for (i = 0; i < len; i++)
00515       CRC32C(res, buf[i]);
00516     h      = ~res;
00517     byte0  = h & 0xff;
00518     byte1  = (h>>8) & 0xff;
00519     byte2  = (h>>16) & 0xff;
00520     byte3  = (h>>24) & 0xff;
00521     crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
00522     return htonl(crc32c);
00523 }
00524 
00525 void SCTPSerializer::parse(const uint8_t *buf, uint32 bufsize, SCTPMessage *dest)
00526 {
00527     int32 size_common_header = sizeof(struct common_header);
00528     int32 size_init_chunk = sizeof(struct init_chunk);
00529     int32 size_init_ack_chunk = sizeof(struct init_ack_chunk);
00530     int32 size_data_chunk = sizeof(struct data_chunk);
00531     int32 size_sack_chunk = sizeof(struct sack_chunk);
00532     int32 size_heartbeat_chunk = sizeof(struct heartbeat_chunk);
00533     int32 size_heartbeat_ack_chunk = sizeof(struct heartbeat_ack_chunk);
00534     int32 size_abort_chunk = sizeof(struct abort_chunk);
00535     int32 size_cookie_echo_chunk = sizeof(struct cookie_echo_chunk);
00536     uint16 paramType;
00537     int32 parptr, chunklen, cLen, woPadding;
00538     struct common_header *common_header = (struct common_header*) (buf);
00539     int32 tempChecksum = common_header->checksum;
00540     common_header->checksum = 0;
00541     int32 chksum = checksum((unsigned char*)common_header, bufsize);
00542     common_header->checksum = tempChecksum;
00543 
00544     const unsigned char *chunks = (unsigned char*) (buf + size_common_header);
00545     sctpEV3<<"SCTPSerializer::parse SCTPMessage\n";
00546     if (tempChecksum == chksum)
00547         dest->setChecksumOk(true);
00548     else
00549         dest->setChecksumOk(false);
00550     sctpEV3<<"checksumOK="<<dest->getChecksumOk()<<"\n";
00551     dest->setSrcPort(ntohs(common_header->source_port));
00552     dest->setDestPort(ntohs(common_header->destination_port));
00553     dest->setTag(ntohl(common_header->verification_tag));
00554     dest->setBitLength(SCTP_COMMON_HEADER*8);
00555     // chunks
00556     uint32 chunkPtr = 0;
00557 
00558     // catch ALL chunks - when a chunk is taken, the chunkPtr is set to the next chunk
00559     while(chunkPtr < (bufsize - size_common_header))
00560     {
00561         const struct chunk * chunk = (struct chunk*)(chunks + chunkPtr);
00562         int32 chunkType = chunk->type;
00563 sctpEV3<<"chunkType="<<chunkType<<"\n";
00564         woPadding = ntohs(chunk->length);
00565 sctpEV3<<"chunk->length="<<ntohs(chunk->length)<<"\n";
00566         cLen = ADD_PADDING(woPadding);
00567         switch(chunkType)
00568         {
00569             case DATA:
00570             {
00571                 ev<<"Data received\n";
00572                 const struct data_chunk *dc = (struct data_chunk*) (chunks + chunkPtr);
00573                 sctpEV3<<"cLen="<<cLen<<"\n";
00574                 if(cLen == 0)
00575                     throw new cRuntimeError("Incoming SCTP packet contains data chunk with length==0");
00576                 SCTPDataChunk *chunk = new SCTPDataChunk("DATA");
00577                 chunk->setChunkType(chunkType);
00578                 chunk->setUBit(dc->flags & UNORDERED_BIT);
00579                 chunk->setBBit(dc->flags & BEGIN_BIT);
00580                 chunk->setEBit(dc->flags & END_BIT);
00581                 chunk->setTsn(ntohl(dc->tsn));
00582                 chunk->setSid(ntohs(dc->sid));
00583                 chunk->setSsn(ntohs(dc->ssn));
00584                 chunk->setPpid(ntohl(dc->ppi));
00585                 chunk->setBitLength(SCTP_DATA_CHUNK_LENGTH*8);
00586                 sctpEV3<<"parse data: woPadding="<<woPadding<<" size_data_chunk="<<size_data_chunk<<"\n";
00587                 if(woPadding > size_data_chunk)
00588                 {
00589                     SCTPSimpleMessage* msg=new SCTPSimpleMessage("data");
00590                     int32 datalen = (woPadding - size_data_chunk);
00591                     msg->setBitLength(datalen*8);
00592                     msg->setDataLen(datalen);
00593                     msg->setDataArraySize(datalen);
00594                     for(int32 i=0; i<datalen; i++)
00595                         msg->setData(i, dc->user_data[i]);
00596 
00597                     chunk->encapsulate(msg);
00598                 }
00599                 sctpEV3<<"datachunkLength="<<chunk->getBitLength()<<"\n";
00600                 dest->addChunk(chunk);
00601                 break;
00602             }
00603             case INIT:
00604             {
00605                 ev<<"parse INIT\n";
00606                 const struct init_chunk *init_chunk = (struct init_chunk*) (chunks + chunkPtr); // (recvBuffer + size_ip + size_common_header);
00607                 chunklen = SCTP_INIT_CHUNK_LENGTH;
00608                 SCTPInitChunk *chunk = new SCTPInitChunk("INIT");
00609                 chunk->setChunkType(chunkType);
00610                 chunk->setName("INIT");
00611                 chunk->setInitTag(ntohl(init_chunk->initiate_tag));
00612                 chunk->setA_rwnd(ntohl(init_chunk->a_rwnd));
00613                 chunk->setNoOutStreams(ntohs(init_chunk->mos));
00614                 chunk->setNoInStreams(ntohs(init_chunk->mis));
00615                 chunk->setInitTSN(ntohl(init_chunk->initial_tsn));
00616                 chunk->setAddressesArraySize(0);
00617                 chunk->setUnrecognizedParametersArraySize(0);
00618                 //sctpEV3<<"INIT arrived from wire\n";
00619                 if(cLen > size_init_chunk)
00620                 {
00621                     int32 parcounter = 0, addrcounter = 0;
00622                     parptr = 0;
00623                     bool stopProcessing = false;
00624                     while(cLen > size_init_chunk+parptr && !stopProcessing)
00625                     {
00626                         sctpEV3<<"Process INIT parameters\n";
00627                         const struct tlv *parameter = (struct tlv*)(((unsigned char*)init_chunk) + size_init_chunk + parptr);
00628                         paramType = ntohs(parameter->type);
00629                         sctpEV3<<"search for param "<<paramType<<"\n";
00630                         switch (paramType)
00631                         {
00632                             case SUPPORTED_ADDRESS_TYPES:
00633                             {
00634                                 break;
00635                             }
00636                             case INIT_PARAM_IPV4:
00637                             {
00638                                 // we supppose an ipv4 address parameter
00639                                 sctpEV3<<"IPv4\n";
00640                                 const struct init_ipv4_address_parameter *v4addr;
00641                                 v4addr = (struct init_ipv4_address_parameter*) (((unsigned char*)init_chunk) + size_init_chunk + parptr);
00642                                 chunk->setAddressesArraySize(++addrcounter);
00643                                 IPvXAddress *localv4Addr;
00644                                 localv4Addr = new IPvXAddress("0.0.0.0");
00645                                 localv4Addr->set(ntohl(v4addr->address));
00646                                 chunk->setAddresses(addrcounter-1, *localv4Addr);
00647                                 chunklen += 8;
00648                                 break;
00649                             }
00650                             case INIT_PARAM_IPV6:
00651                             {
00652                                 sctpEV3<<"IPv6\n";
00653                                 const struct init_ipv6_address_parameter *ipv6addr;
00654                                 ipv6addr = (struct init_ipv6_address_parameter*) (((unsigned char*)init_chunk) + size_init_chunk + parptr);
00655                                 IPv6Address ipv6Addr = IPv6Address(ipv6addr->address[0], ipv6addr->address[1],
00656                                                                     ipv6addr->address[2], ipv6addr->address[3]);
00657                                 IPvXAddress *localv6Addr;
00658                                 localv6Addr = new IPvXAddress("0:0:0:0:0:0:0:0");
00659                                 sctpEV3<<"address"<<ipv6Addr<<"\n";
00660                                 localv6Addr->set(ipv6Addr);
00661                                 chunk->setAddressesArraySize(++addrcounter);
00662                                 chunk->setAddresses(addrcounter-1, *localv6Addr);
00663                                 chunklen += 20;
00664                                 break;
00665                             }
00666                             default:
00667                             {
00668                                 sctpEV3 << "ExtInterface: Unknown SCTP INIT parameter type " << paramType<<"\n";
00669                                 uint16 skip = (paramType & 0x8000) >> 15;
00670                                 if (skip == 0)
00671                                     stopProcessing = true;
00672                                 uint16 report = (paramType & 0x4000) >> 14;
00673                                 if (report != 0)
00674                                 {
00675                                     const struct tlv *unknown;
00676                                     unknown = (struct tlv*) (((unsigned char*)init_chunk) + size_init_chunk + parptr);
00677                                     uint32 unknownLen=chunk->getUnrecognizedParametersArraySize();
00678                                     chunk->setUnrecognizedParametersArraySize(unknownLen+ADD_PADDING(ntohs(unknown->length)));
00679                                     struct data_vector* dv = (struct data_vector*) (((unsigned char*)init_chunk) + size_init_chunk + parptr);
00680 
00681                                     for (uint32 i=unknownLen; i<unknownLen+ADD_PADDING(ntohs(unknown->length)); i++)
00682                                         chunk->setUnrecognizedParameters(i,dv->data[i-unknownLen]);
00683                                 }
00684                                 sctpEV3<<"stopProcessing="<<stopProcessing<<" report="<<report<<"\n";
00685                                 break;
00686                             }
00687                         }
00688                         parptr += ADD_PADDING(ntohs(parameter->length));
00689                         parcounter++;
00690                     }
00691 
00692 
00693                 }
00694                 chunk->setBitLength(chunklen*8);
00695                 dest->addChunk(chunk);
00696                 //chunkPtr += cLen;
00697                 break;
00698             }
00699             case INIT_ACK:
00700             {
00701                 const struct init_ack_chunk *iac = (struct init_ack_chunk*) (chunks + chunkPtr);
00702                 chunklen = SCTP_INIT_CHUNK_LENGTH;
00703                 SCTPInitAckChunk *chunk = new SCTPInitAckChunk("INIT_ACK");
00704                 chunk->setChunkType(chunkType);
00705                 chunk->setInitTag(ntohl(iac->initiate_tag));
00706                 chunk->setA_rwnd(ntohl(iac->a_rwnd));
00707                 chunk->setNoOutStreams(ntohs(iac->mos));
00708                 chunk->setNoInStreams(ntohs(iac->mis));
00709                 chunk->setInitTSN(ntohl(iac->initial_tsn));
00710                 chunk->setUnrecognizedParametersArraySize(0);
00711                 if(cLen > size_init_ack_chunk)
00712                 {
00713                     int32 parcounter = 0, addrcounter = 0;
00714                     parptr = 0;
00715                     bool stopProcessing = false;
00716                     //sctpEV3<<"cLen="<<cLen<<"\n";
00717                     while(cLen > size_init_ack_chunk+parptr && !stopProcessing)
00718                     {
00719                         const struct tlv *parameter = (struct tlv*)(((unsigned char*)iac) + size_init_ack_chunk + parptr);
00720                         paramType = ntohs(parameter->type);
00721                         //sctpEV3<<"ParamType = "<<paramType<<" parameterLength="<<ntohs(parameter->length)<<"\n";
00722                         switch (paramType)
00723                         {
00724                             case SUPPORTED_ADDRESS_TYPES:
00725                             {
00726                                 break;
00727                             }
00728                             case INIT_PARAM_IPV4:
00729                             {
00730                                 sctpEV3<<"parse IPv4\n";
00731                                 const struct init_ipv4_address_parameter *v4addr;
00732                                 v4addr = (struct init_ipv4_address_parameter*) (((unsigned char*)iac) + size_init_ack_chunk + parptr);
00733                                 chunk->setAddressesArraySize(++addrcounter);
00734                                 IPvXAddress *localv4Addr;
00735                                 localv4Addr = new IPvXAddress("0.0.0.0");
00736                                 localv4Addr->set(ntohl(v4addr->address));
00737                                 chunk->setAddresses(addrcounter-1, *localv4Addr);
00738                                 chunklen += 8;
00739                                 break;
00740                             }
00741                             case INIT_PARAM_IPV6:
00742                             {
00743                                 sctpEV3<<"IPv6\n";
00744                                 const struct init_ipv6_address_parameter *ipv6addr;
00745                                 ipv6addr = (struct init_ipv6_address_parameter*) (((unsigned char*)iac) + size_init_chunk + parptr);
00746                                 IPv6Address ipv6Addr = IPv6Address(ipv6addr->address[0], ipv6addr->address[1],
00747                                                                     ipv6addr->address[2], ipv6addr->address[3]);
00748                                 IPvXAddress *localv6Addr;
00749                                 localv6Addr = new IPvXAddress("0:0:0:0:0:0:0:0");
00750                                 sctpEV3<<"address"<<ipv6Addr<<"\n";
00751                                 localv6Addr->set(ipv6Addr);
00752 
00753                                 chunk->setAddressesArraySize(++addrcounter);
00754                                 chunk->setAddresses(addrcounter-1, *localv6Addr);
00755                                 chunklen += 20;
00756                                 break;
00757                             }
00758                             case INIT_PARAM_COOKIE:
00759                             {
00760                                 const struct tlv *cookie = (struct tlv*) (((unsigned char*)iac) + size_init_ack_chunk + parptr);
00761                                 int32 cookieLen = ntohs(cookie->length) - 4;
00762                                 // put cookie data into chunk (char array cookie)
00763                                 chunk->setCookieArraySize(cookieLen);
00764                                 for(int32 i=0; i<cookieLen; i++)
00765                                     chunk->setCookie(i, cookie->value[i]);
00766                                 chunklen+=cookieLen+4;
00767                                 break;
00768                             }
00769                             default:
00770                             {
00771                                 sctpEV3 << "ExtInterface: Unknown SCTP INIT-ACK parameter type " << paramType<<"\n";
00772                                 uint16 skip = (paramType & 0x8000) >> 15;
00773                                 if (skip == 0)
00774                                     stopProcessing = true;
00775                                 uint16 report = (paramType & 0x4000) >> 14;
00776                                 if (report != 0)
00777                                 {
00778                                     const struct tlv *unknown;
00779                                     unknown = (struct tlv*) (((unsigned char*)iac) + size_init_ack_chunk + parptr);
00780                                     uint32 unknownLen=chunk->getUnrecognizedParametersArraySize();
00781                                     chunk->setUnrecognizedParametersArraySize(unknownLen+ADD_PADDING(ntohs(unknown->length)));
00782                                     struct data_vector* dv = (struct data_vector*) (((unsigned char*)iac) + size_init_ack_chunk + parptr);
00783 
00784                                     for (uint32 i=unknownLen; i<unknownLen+ADD_PADDING(ntohs(unknown->length)); i++)
00785                                         chunk->setUnrecognizedParameters(i,dv->data[i-unknownLen]);
00786                                 }
00787                                 sctpEV3<<"stopProcessing="<<stopProcessing<<"  report="<<report<<"\n";
00788 
00789                                 break;
00790                             }
00791                         }
00792                         parptr += ADD_PADDING(ntohs(parameter->length));
00793                         //sctpEV3<<"parptr="<<parptr<<"\n";
00794                         parcounter++;
00795                     }
00796                 }
00797                 chunk->setBitLength(chunklen*8);
00798                 dest->addChunk(chunk);
00799                 break;
00800             }
00801             case SACK:
00802             {
00803                 ev<<"SCTPMessage: SACK received\n";
00804                 const struct sack_chunk *sac = (struct sack_chunk*) (chunks + chunkPtr);
00805                 SCTPSackChunk *chunk = new SCTPSackChunk("SACK");
00806                 chunk->setChunkType(chunkType);
00807                 uint32 cumtsnack = ntohl(sac->cum_tsn_ack);
00808                 chunk->setCumTsnAck(cumtsnack);
00809                 chunk->setA_rwnd(ntohl(sac->a_rwnd));
00810 
00811                 int32 ngaps = ntohs(sac->nr_of_gaps);
00812                 int32 ndups = ntohs(sac->nr_of_dups);
00813                 chunk->setNumGaps(ngaps);
00814                 chunk->setNumDupTsns(ndups);
00815 
00816                 chunk->setGapStartArraySize(ngaps);
00817                 chunk->setGapStopArraySize(ngaps);
00818                 chunk->setDupTsnsArraySize(ndups);
00819 
00820                 for(int32 i=0; i<ngaps; i++)
00821                 {
00822                     const struct sack_gap *gap = (struct sack_gap*) (((unsigned char*)sac) + size_sack_chunk + i*sizeof(sack_gap));
00823                     chunk->setGapStart(i, ntohs(gap->start) + cumtsnack);
00824                     chunk->setGapStop(i, ntohs(gap->stop) + cumtsnack);
00825                 }
00826                 for(int32 i=0; i<ndups; i++)
00827                 {
00828                     const struct sack_duptsn *dup = (struct sack_duptsn*) (((unsigned char*)sac) + size_sack_chunk + ngaps*sizeof(sack_gap) + i*sizeof(sack_duptsn));
00829                     chunk->setDupTsns(i, ntohl(dup->tsn));
00830                 }
00831 
00832                 chunk->setBitLength(cLen*8);
00833                 dest->addChunk(chunk);
00834                 break;
00835             }
00836             case HEARTBEAT:
00837             {
00838                 //sctpEV3<<"SCTPMessage: Heartbeat received\n";
00839                 const struct heartbeat_chunk *hbc = (struct heartbeat_chunk*) (chunks + chunkPtr);
00840                 SCTPHeartbeatChunk *chunk = new SCTPHeartbeatChunk("HEARTBEAT");
00841                 chunk->setChunkType(chunkType);
00842                 if(cLen > size_heartbeat_chunk)
00843                 {
00844                     int32 parcounter = 0;
00845                     parptr = 0;
00846                     while(cLen > size_heartbeat_chunk+parptr)
00847                     {
00848                         // we supppose type 1 here
00849                         //sctpEV3<<"HB-chunk+parptr="<<size_heartbeat_chunk+parptr<<"\n";
00850                         const struct heartbeat_info *hbi = (struct heartbeat_info*) (((unsigned char*)hbc) + size_heartbeat_chunk + parptr);
00851                         if(ntohs(hbi->type) == 1) // sender specific hb info
00852                         {
00853                             //sctpEV3<<"HBInfo\n";
00854                             int32 infoLen = ntohs(hbi->length) - 4;
00855                             parptr += ADD_PADDING(infoLen) + 4;
00856                             parcounter++;
00857                             chunk->setInfoArraySize(infoLen);
00858                             for(int32 i=0; i<infoLen; i++)
00859                                 chunk->setInfo(i, HBI_INFO(hbi)[i]);
00860                         }
00861                         else
00862                         {
00863                             parptr += ADD_PADDING(ntohs(hbi->length));  // set pointer forwards with count of bytes in length field of TLV
00864                             parcounter++;
00865                             continue;
00866                         }
00867                     }
00868                 }
00869                 chunk->setBitLength(cLen*8);
00870                 dest->addChunk(chunk);
00871                 break;
00872             }
00873             case HEARTBEAT_ACK:
00874             {
00875                 ev<<"SCTPMessage: Heartbeat_Ack received\n";
00876                 const struct heartbeat_ack_chunk *hbac = (struct heartbeat_ack_chunk*) (chunks + chunkPtr);
00877                 SCTPHeartbeatAckChunk *chunk = new SCTPHeartbeatAckChunk("HEARTBEAT_ACK");
00878                 chunk->setChunkType(chunkType);
00879                 if(cLen>size_heartbeat_ack_chunk)
00880                 {
00881                     int32 parcounter = 0;
00882                     parptr = 0;
00883                     while(cLen > size_heartbeat_ack_chunk+parptr)
00884                     {
00885                         // we supppose type 1 here, the same provided in heartbeat chunks
00886                         const struct heartbeat_info *hbi = (struct heartbeat_info*) (((unsigned char*)hbac) + size_heartbeat_ack_chunk + parptr);
00887                         if(ntohs(hbi->type) == 1) // sender specific hb info
00888                         {
00889                             parptr += sizeof(struct heartbeat_info);
00890                             parcounter++;
00891                             chunk->setRemoteAddr(IPvXAddress(ntohl(HBI_ADDR(hbi))));
00892                             chunk->setTimeField(ntohl((uint32)HBI_TIME(hbi)));
00893                         }
00894                         else
00895                         {
00896                             parptr += ntohs(hbi->length);   // set pointer forwards with count of bytes in length field of TLV
00897                             parcounter++;
00898                             continue;
00899                         }
00900 
00901                     }
00902                 }
00903                 chunk->setBitLength(cLen*8);
00904                 dest->addChunk(chunk);
00905                 break;
00906             }
00907             case ABORT:
00908             {
00909                 ev<<"SCTPMessage: Abort received\n";
00910                 const struct abort_chunk *ac = (struct abort_chunk*) (chunks + chunkPtr);
00911                 cLen = ntohs(ac->length);
00912                 SCTPAbortChunk *chunk = new SCTPAbortChunk("ABORT");
00913                 chunk->setChunkType(chunkType);
00914                 chunk->setT_Bit(ac->flags & T_BIT);
00915                 if(cLen>size_abort_chunk)
00916                 {
00917                     // TODO: handle attached error causes
00918                 }
00919                 chunk->setBitLength(cLen*8);
00920                 dest->addChunk(chunk);
00921                 break;
00922             }
00923             case COOKIE_ECHO:
00924             {
00925                 SCTPCookieEchoChunk *chunk = new SCTPCookieEchoChunk("COOKIE_ECHO");
00926                 chunk->setChunkType(chunkType);
00927                 sctpEV3<<"Parse Cookie-Echo\n";
00928                 if(cLen>size_cookie_echo_chunk)
00929                 {
00930                     int32 cookieSize = woPadding-size_cookie_echo_chunk;
00931                     sctpEV3<<"cookieSize="<<cookieSize<<"\n";
00932                     const struct cookie_parameter *cookie = (struct cookie_parameter*)(chunks+chunkPtr+4);
00933                     SCTPCookie* stateCookie = new SCTPCookie();
00934                     stateCookie->setCreationTime(ntohl(cookie->creationTime));
00935                     stateCookie->setLocalTag(ntohl(cookie->localTag));
00936                     stateCookie->setPeerTag(ntohl(cookie->peerTag));
00937                     stateCookie->setLocalTieTagArraySize(32);
00938                     stateCookie->setPeerTieTagArraySize(32);
00939                     for(int32 i=0; i<32; i++)
00940                     {
00941                         stateCookie->setLocalTieTag(i, cookie->localTieTag[i]);
00942                         stateCookie->setPeerTieTag(i, cookie->peerTieTag[i]);
00943                     }
00944                     stateCookie->setBitLength(SCTP_COOKIE_LENGTH*8);
00945                     chunk->setStateCookie(stateCookie);
00946                 }
00947                 chunk->setBitLength(woPadding*8);
00948                 dest->addChunk(chunk);
00949                 break;
00950             }
00951             case COOKIE_ACK:
00952             {
00953                 ev<<"SCTPMessage: Cookie_Ack received\n";
00954                 SCTPCookieAckChunk *chunk = new SCTPCookieAckChunk("COOKIE_ACK");
00955                 chunk->setChunkType(chunkType);
00956                 chunk->setBitLength(cLen*8);
00957                 dest->addChunk(chunk);
00958                 break;
00959             }
00960             case SHUTDOWN:
00961             {
00962                 ev<<"SCTPMessage: Shutdown received\n";
00963                 const struct shutdown_chunk *sc = (struct shutdown_chunk*) (chunks + chunkPtr);
00964                 SCTPShutdownChunk *chunk = new SCTPShutdownChunk("SHUTDOWN");
00965                 chunk->setChunkType(chunkType);
00966                 uint32 cumtsnack = ntohl(sc->cumulative_tsn_ack);
00967                 chunk->setCumTsnAck(cumtsnack);
00968                 chunk->setBitLength(cLen*8);
00969                 dest->addChunk(chunk);
00970                 break;
00971             }
00972             case SHUTDOWN_ACK:
00973             {
00974                 ev<<"SCTPMessage: ShutdownAck received\n";
00975                 SCTPShutdownAckChunk *chunk = new SCTPShutdownAckChunk("SHUTDOWN_ACK");
00976                 chunk->setChunkType(chunkType);
00977                 chunk->setBitLength(cLen*8);
00978                 dest->addChunk(chunk);
00979                 break;
00980             }
00981             case SHUTDOWN_COMPLETE:
00982             {
00983                 ev<<"SCTPMessage: ShutdownComplete received\n";
00984                 const struct shutdown_complete_chunk *scc = (struct shutdown_complete_chunk*) (chunks + chunkPtr);
00985                 SCTPShutdownCompleteChunk *chunk = new SCTPShutdownCompleteChunk("SHUTDOWN_COMPLETE");
00986                 chunk->setChunkType(chunkType);
00987                 chunk->setTBit(scc->flags & T_BIT);
00988                 chunk->setBitLength(cLen*8);
00989                 dest->addChunk(chunk);
00990                 break;
00991             }
00992             case ERRORTYPE:
00993             {
00994                 const struct error_chunk *error;
00995                 error = (struct error_chunk*) (chunks + chunkPtr);
00996                 SCTPErrorChunk *errorchunk;
00997                 errorchunk = new SCTPErrorChunk("ERROR");
00998                 errorchunk->setChunkType(chunkType);
00999                 errorchunk->setBitLength(SCTP_ERROR_CHUNK_LENGTH*8);
01000                 parptr = 0;
01001                 dest->addChunk(errorchunk);
01002                 break;
01003             }
01004             default:
01005                 //printf("TODO: Implement chunk type %d, found in chunk array on %d!\n", chunkType, ct);
01006                 sctpEV3 << "Parser: Unknown SCTP chunk type " << chunkType;
01007 
01008                 /*throw new cRuntimeError("TODO: unknown chunktype in incoming packet from external interface! Implement it!");*/
01009 
01010                 break;
01011         }   // end of switch(chunkType)
01012         chunkPtr += cLen;
01013     }   // end of while()
01014 }
01015 
01016 
01017