00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00044 #include "private.h"
00045 #include <ccrtp/rtppkt.h>
00046 #include <ccrtp/CryptoContext.h>
00047
00048 #ifdef CCXX_NAMESPACES
00049 namespace ost {
00050 #endif
00051
00052
00053 const uint32 PayloadFormat::defaultRTPClockRate = 8000;
00054
00055
00056 uint32 StaticPayloadFormat::staticAudioTypesRates[] = {
00057
00058 8000,
00059 0,
00060 8000,
00061 8000,
00062 8000,
00063 8000,
00064 16000,
00065 8000,
00066 8000,
00067 8000,
00068 44100,
00069 44100,
00070 8000,
00071 0,
00072 90000,
00073 8000,
00074 11015,
00075 22050,
00076 8000
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 };
00089
00090 StaticPayloadFormat::StaticPayloadFormat(StaticPayloadType type)
00091 {
00092 setPayloadType( (type <= lastStaticPayloadType)? type : 0);
00093 if ( type <= sptG729 ) {
00094
00095 setRTPClockRate(staticAudioTypesRates[type]);
00096 } else {
00097
00098 setRTPClockRate(90000);
00099 }
00100 }
00101
00102 DynamicPayloadFormat::DynamicPayloadFormat(PayloadType type, uint32 rate)
00103 {
00104 PayloadFormat::setPayloadType(type);
00105 setRTPClockRate(rate);
00106 }
00107
00108
00109 RTPPacket::RTPPacket(const unsigned char* const block, size_t len,
00110 bool duplicate):
00111 total((uint32)len),
00112 duplicated(duplicate)
00113 {
00114
00115 const RTPFixedHeader* const header =
00116 reinterpret_cast<const RTPFixedHeader*>(block);
00117 hdrSize = sizeof(RTPFixedHeader) + (header->cc << 2);
00118 if ( header->extension ){
00119 RTPHeaderExt *ext = (RTPHeaderExt *)(block + hdrSize);
00120 hdrSize += sizeof(uint32) + (ntohs(ext->length) * 4);
00121 }
00122 if ( header->padding )
00123 len -= block[len - 1];
00124 payloadSize = (uint32)(len - hdrSize);
00125
00126 if ( duplicate ) {
00127 buffer = new unsigned char[len];
00128 setbuffer(block,len,0);
00129 } else {
00130 buffer = const_cast<unsigned char*>(block);
00131 }
00132 }
00133
00134
00135 RTPPacket::RTPPacket(size_t hdrlen, size_t plen, uint8 paddinglen, CryptoContext* pcc ) :
00136 payloadSize((uint32)plen),
00137 buffer(NULL),
00138 hdrSize((uint32)hdrlen),
00139 duplicated(false)
00140 {
00141 total = (uint32)(hdrlen + payloadSize);
00142
00143 uint8 padding = 0;
00144 if ( 0 != paddinglen ) {
00145 padding = paddinglen - (total % paddinglen);
00146 total += padding;
00147 }
00148 srtpLength = 0;
00149 srtpDataOffset = 0;
00150 if (pcc != NULL) {
00151
00152 srtpLength = pcc->getTagLength() + pcc->getMkiLength();
00153 srtpDataOffset = total;
00154 }
00155
00156
00157
00158
00159
00160 buffer = new unsigned char[total + srtpLength];
00161 *(reinterpret_cast<uint32*>(getHeader())) = 0;
00162 getHeader()->version = CCRTP_VERSION;
00163 if ( 0 != padding ) {
00164 memset(buffer + total - padding,0,padding - 1);
00165 buffer[total - 1] = padding;
00166 getHeader()->padding = 1;
00167 } else {
00168 getHeader()->padding = 0;
00169 }
00170 }
00171
00172 void
00173 RTPPacket::endPacket()
00174 {
00175 #ifdef CCXX_EXCEPTIONS
00176 try {
00177 #endif
00178 delete [] buffer;
00179 #ifdef CCXX_EXCEPTIONS
00180 } catch (...) { };
00181 #endif
00182 }
00183
00184 OutgoingRTPPkt::OutgoingRTPPkt(
00185 const uint32* const csrcs, uint16 numcsrc,
00186 const unsigned char* const hdrext, uint32 hdrextlen,
00187 const unsigned char* const data, size_t datalen,
00188 uint8 paddinglen, CryptoContext* pcc) :
00189 RTPPacket((getSizeOfFixedHeader() + sizeof(uint32) * numcsrc
00190 + hdrextlen),datalen,paddinglen, pcc)
00191 {
00192 uint32 pointer = (uint32)getSizeOfFixedHeader();
00193
00194 setCSRCArray(csrcs,numcsrc);
00195 pointer += numcsrc * sizeof(uint32);
00196
00197
00198 setbuffer(hdrext,hdrextlen,pointer);
00199 setExtension(hdrextlen > 0);
00200 pointer += hdrextlen;
00201
00202
00203 setbuffer(data,datalen,pointer);
00204 }
00205
00206 OutgoingRTPPkt::OutgoingRTPPkt(
00207 const uint32* const csrcs, uint16 numcsrc,
00208 const unsigned char* data, size_t datalen,
00209 uint8 paddinglen, CryptoContext* pcc) :
00210 RTPPacket((getSizeOfFixedHeader() + sizeof(uint32) *numcsrc),datalen,
00211 paddinglen, pcc)
00212 {
00213 uint32 pointer = (uint32)getSizeOfFixedHeader();
00214
00215 setCSRCArray(csrcs,numcsrc);
00216 pointer += numcsrc * sizeof(uint32);
00217
00218
00219
00220
00221
00222
00223 setbuffer(data,datalen,pointer);
00224 }
00225
00226 OutgoingRTPPkt::OutgoingRTPPkt(const unsigned char* data, size_t datalen,
00227 uint8 paddinglen, CryptoContext* pcc) :
00228 RTPPacket(getSizeOfFixedHeader(),datalen,paddinglen, pcc)
00229 {
00230
00231
00232
00233
00234
00235 setbuffer(data,datalen,getSizeOfFixedHeader());
00236 }
00237
00238 void
00239 OutgoingRTPPkt::setCSRCArray(const uint32* const csrcs, uint16 numcsrc)
00240 {
00241 setbuffer(csrcs, numcsrc * sizeof(uint32),getSizeOfFixedHeader());
00242 uint32* csrc = const_cast<uint32*>(getCSRCs());
00243 for ( int i = 0; i < numcsrc; i++ )
00244 csrc[i] = htonl(csrc[i]);
00245 getHeader()->cc = numcsrc;
00246 }
00247
00248 void
00249 OutgoingRTPPkt::protect(uint32 ssrc, CryptoContext* pcc)
00250 {
00251
00252 uint64 index = ((uint64)pcc->getRoc() << 16) | (uint64)getSeqNum();
00253
00254 pcc->srtpEncrypt(this, index, ssrc);
00255
00256
00257
00258
00259
00260 pcc->srtpAuthenticate(this, pcc->getRoc(),
00261 const_cast<uint8*>(getRawPacket()+srtpDataOffset) );
00262
00263 if (getSeqNum() == 0xFFFF ) {
00264 pcc->setRoc(pcc->getRoc() + 1);
00265 }
00266 }
00267
00268
00269 const uint16 IncomingRTPPkt::RTP_INVALID_PT_MASK = (0x7e);
00270 const uint16 IncomingRTPPkt::RTP_INVALID_PT_VALUE = (0x48);
00271
00272 IncomingRTPPkt::IncomingRTPPkt(const unsigned char* const block, size_t len) :
00273 RTPPacket(block,len)
00274 {
00275
00276
00277
00278
00279
00280 if ( getProtocolVersion() != CCRTP_VERSION
00281 ||
00282 (getPayloadType() & RTP_INVALID_PT_MASK) == RTP_INVALID_PT_VALUE) {
00283
00284
00285
00286
00287 headerValid = false;
00288 return;
00289 }
00290 headerValid = true;
00291 cachedTimestamp = getRawTimestamp();
00292 cachedSeqNum = ntohs(getHeader()->sequence);
00293 cachedSSRC = ntohl(getHeader()->sources[0]);
00294 }
00295
00296 int32
00297 IncomingRTPPkt::unprotect(CryptoContext* pcc)
00298 {
00299 if (pcc == NULL) {
00300 return true;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 uint32 srtpDataIndex = total - (pcc->getTagLength() + pcc->getMkiLength());
00318
00319
00320
00321 total -= pcc->getTagLength() + pcc->getMkiLength();
00322
00323
00324 payloadSize -= pcc->getTagLength() + pcc->getMkiLength();
00325
00326
00327
00328 const uint8* tag = getRawPacket() + srtpDataIndex + pcc->getMkiLength();
00329
00330
00331 if (!pcc->checkReplay(cachedSeqNum)) {
00332 return -2;
00333 }
00334
00335 uint64 guessedIndex = pcc->guessIndex(cachedSeqNum);
00336
00337 uint32 guessedRoc = guessedIndex >> 16;
00338 uint8* mac = new uint8[pcc->getTagLength()];
00339
00340 pcc->srtpAuthenticate(this, guessedRoc, mac);
00341 if (memcmp(tag, mac, pcc->getTagLength()) != 0) {
00342 delete[] mac;
00343 return -1;
00344 }
00345 delete[] mac;
00346
00347
00348 pcc->srtpEncrypt( this, guessedIndex, cachedSSRC );
00349
00350
00351 pcc->update(cachedSeqNum);
00352
00353 return 1;
00354 }
00355
00356 #ifdef CCXX_NAMESPACES
00357 }
00358 #endif
00359