|
reSIProcate/stack
9694
|
00001 #if defined(HAVE_CONFIG_H) 00002 #include "config.h" 00003 #endif 00004 00005 #include "resip/stack/SdpContents.hxx" 00006 #include "resip/stack/Helper.hxx" 00007 #include "rutil/ParseBuffer.hxx" 00008 #include "rutil/DataStream.hxx" 00009 #include "resip/stack/Symbols.hxx" 00010 #include "rutil/Logger.hxx" 00011 #include "rutil/WinLeakCheck.hxx" 00012 00013 #define RESIPROCATE_SUBSYSTEM resip::Subsystem::SDP 00014 00015 using namespace resip; 00016 using namespace std; 00017 00018 const SdpContents SdpContents::Empty; 00019 00020 bool 00021 SdpContents::init() 00022 { 00023 static ContentsFactory<SdpContents> factory; 00024 (void)factory; 00025 return true; 00026 } 00027 00028 const char* NetworkType[] = {"???", "IP4", "IP6"}; 00029 00030 static const Data rtpmap("rtpmap"); 00031 static const Data fmtp("fmtp"); 00032 00033 // RFC2327 6. page 9 00034 // "parsers should be tolerant and accept records terminated with a single 00035 // newline character" 00036 void skipEol(ParseBuffer& pb) 00037 { 00038 while(!pb.eof() && (*pb.position() == Symbols::SPACE[0] || 00039 *pb.position() == Symbols::TAB[0])) 00040 { 00041 pb.skipChar(); 00042 } 00043 00044 if (*pb.position() == Symbols::LF[0]) 00045 { 00046 pb.skipChar(); 00047 } 00048 else 00049 { 00050 // allow extra 0x0d bytes. 00051 while(*pb.position() == Symbols::CR[0]) 00052 { 00053 pb.skipChar(); 00054 } 00055 pb.skipChar(Symbols::LF[0]); 00056 } 00057 00058 } 00059 00060 AttributeHelper::AttributeHelper(const AttributeHelper& rhs) 00061 : mAttributeList(rhs.mAttributeList), 00062 mAttributes(rhs.mAttributes) 00063 { 00064 } 00065 00066 AttributeHelper::AttributeHelper() 00067 { 00068 } 00069 00070 AttributeHelper& 00071 AttributeHelper::operator=(const AttributeHelper& rhs) 00072 { 00073 if (this != &rhs) 00074 { 00075 mAttributeList = rhs.mAttributeList; 00076 mAttributes = rhs.mAttributes; 00077 } 00078 return *this; 00079 } 00080 00081 bool 00082 AttributeHelper::exists(const Data& key) const 00083 { 00084 return mAttributes.find(key) != mAttributes.end(); 00085 } 00086 00087 const list<Data>& 00088 AttributeHelper::getValues(const Data& key) const 00089 { 00090 if (!exists(key)) 00091 { 00092 static const list<Data> emptyList; 00093 return emptyList; 00094 } 00095 return mAttributes.find(key)->second; 00096 } 00097 00098 EncodeStream& 00099 AttributeHelper::encode(EncodeStream& s) const 00100 { 00101 for (std::list<std::pair<Data, Data> >::const_iterator i = mAttributeList.begin(); 00102 i != mAttributeList.end(); ++i) 00103 { 00104 s << "a=" << i->first; 00105 if (!i->second.empty()) 00106 { 00107 s << Symbols::COLON[0] << i->second; 00108 } 00109 s << Symbols::CRLF; 00110 } 00111 return s; 00112 } 00113 00114 void 00115 AttributeHelper::parse(ParseBuffer& pb) 00116 { 00117 while (!pb.eof() && *pb.position() == 'a') 00118 { 00119 Data key; 00120 Data value; 00121 00122 pb.skipChar('a'); 00123 const char* anchor = pb.skipChar(Symbols::EQUALS[0]); 00124 pb.skipToOneOf(Symbols::COLON, Symbols::CRLF); 00125 pb.data(key, anchor); 00126 if (!pb.eof() && *pb.position() == Symbols::COLON[0]) 00127 { 00128 anchor = pb.skipChar(Symbols::COLON[0]); 00129 pb.skipToOneOf(Symbols::CRLF); 00130 pb.data(value, anchor); 00131 } 00132 00133 if(!pb.eof()) skipEol(pb); 00134 00135 mAttributeList.push_back(std::make_pair(key, value)); 00136 mAttributes[key].push_back(value); 00137 } 00138 } 00139 00140 void 00141 AttributeHelper::addAttribute(const Data& key, const Data& value) 00142 { 00143 mAttributeList.push_back(std::make_pair(key, value)); 00144 mAttributes[key].push_back(value); 00145 } 00146 00147 void 00148 AttributeHelper::clearAttribute(const Data& key) 00149 { 00150 for (std::list<std::pair<Data, Data> >::iterator i = mAttributeList.begin(); 00151 i != mAttributeList.end(); ) 00152 { 00153 std::list<std::pair<Data, Data> >::iterator j = i++; 00154 if (j->first == key) 00155 { 00156 mAttributeList.erase(j); 00157 } 00158 } 00159 mAttributes.erase(key); 00160 } 00161 00162 SdpContents::SdpContents() : Contents(getStaticType()) 00163 { 00164 } 00165 00166 SdpContents::SdpContents(const HeaderFieldValue& hfv, const Mime& contentTypes) 00167 : Contents(hfv, contentTypes) 00168 { 00169 } 00170 00171 //SdpContents::SdpContents(const SdpContents& rhs) 00172 // : Contents(rhs), 00173 // mSession(rhs.mSession) 00174 //{ 00175 //} 00176 00177 SdpContents::~SdpContents() 00178 { 00179 } 00180 00181 00182 SdpContents& 00183 SdpContents::operator=(const SdpContents& rhs) 00184 { 00185 if (this != &rhs) 00186 { 00187 Contents::operator=(rhs); 00188 mSession = rhs.mSession; 00189 } 00190 return *this; 00191 } 00192 00193 Contents* 00194 SdpContents::clone() const 00195 { 00196 return new SdpContents(*this); 00197 } 00198 00199 void 00200 SdpContents::parse(ParseBuffer& pb) 00201 { 00202 mSession.parse(pb); 00203 } 00204 00205 EncodeStream& 00206 SdpContents::encodeParsed(EncodeStream& s) const 00207 { 00208 mSession.encode(s); 00209 return s; 00210 } 00211 00212 const Mime& 00213 SdpContents::getStaticType() 00214 { 00215 static Mime type("application", "sdp"); 00216 return type; 00217 } 00218 00219 static Data nullOrigin("0.0.0.0"); 00220 00221 SdpContents::Session::Origin::Origin() 00222 : mUser(), 00223 mSessionId(0), 00224 mVersion(0), 00225 mAddrType(IP4), 00226 mAddress(nullOrigin) 00227 {} 00228 00229 SdpContents::Session::Origin::Origin(const Origin& rhs) 00230 : mUser(rhs.mUser), 00231 mSessionId(rhs.mSessionId), 00232 mVersion(rhs.mVersion), 00233 mAddrType(rhs.mAddrType), 00234 mAddress(rhs.mAddress) 00235 { 00236 } 00237 00238 SdpContents::Session::Origin& 00239 SdpContents::Session::Origin::operator=(const Origin& rhs) 00240 { 00241 if (this != &rhs) 00242 { 00243 mUser = rhs.mUser; 00244 mSessionId = rhs.mSessionId; 00245 mVersion = rhs.mVersion; 00246 mAddrType = rhs.mAddrType; 00247 mAddress = rhs.mAddress; 00248 } 00249 return *this; 00250 } 00251 00252 00253 SdpContents::Session::Origin::Origin(const Data& user, 00254 const UInt64& sessionId, 00255 const UInt64& version, 00256 AddrType addr, 00257 const Data& address) 00258 : mUser(user), 00259 mSessionId(sessionId), 00260 mVersion(version), 00261 mAddrType(addr), 00262 mAddress(address) 00263 {} 00264 00265 EncodeStream& 00266 SdpContents::Session::Origin::encode(EncodeStream& s) const 00267 { 00268 s << "o=" 00269 << mUser << Symbols::SPACE[0] 00270 << mSessionId << Symbols::SPACE[0] 00271 << mVersion << Symbols::SPACE[0] 00272 << "IN " 00273 << NetworkType[mAddrType] << Symbols::SPACE[0] 00274 << mAddress << Symbols::CRLF; 00275 return s; 00276 } 00277 00278 void 00279 SdpContents::Session::Origin::setAddress(const Data& host, AddrType addr) 00280 { 00281 mAddress = host; 00282 mAddrType = addr; 00283 } 00284 00285 void 00286 SdpContents::Session::Origin::parse(ParseBuffer& pb) 00287 { 00288 pb.skipChar('o'); 00289 const char* anchor = pb.skipChar(Symbols::EQUALS[0]); 00290 00291 pb.skipToChar(Symbols::SPACE[0]); 00292 pb.data(mUser, anchor); 00293 00294 anchor = pb.skipChar(Symbols::SPACE[0]); 00295 try 00296 { 00297 mSessionId = pb.uInt64(); 00298 } 00299 catch(ParseException& e) 00300 { 00301 WarningLog(<< "Exception parsing origin sessionid: " << e); 00302 } 00303 pb.skipToChar(Symbols::SPACE[0]); 00304 00305 anchor = pb.skipChar(Symbols::SPACE[0]); 00306 try 00307 { 00308 mVersion = pb.uInt64(); 00309 } 00310 catch(ParseException& e) 00311 { 00312 WarningLog(<< "Exception parsing origin version: " << e); 00313 } 00314 pb.skipToChar(Symbols::SPACE[0]); 00315 00316 pb.skipChar(Symbols::SPACE[0]); 00317 pb.skipChar('I'); 00318 pb.skipChar('N'); 00319 00320 anchor = pb.skipChar(Symbols::SPACE[0]); 00321 pb.skipToChar(Symbols::SPACE[0]); 00322 Data addrType; 00323 pb.data(addrType, anchor); 00324 if (addrType == NetworkType[IP4]) 00325 { 00326 mAddrType = IP4; 00327 } 00328 else if (addrType == NetworkType[IP6]) 00329 { 00330 mAddrType = IP6; 00331 } 00332 else 00333 { 00334 mAddrType = static_cast<AddrType>(0); 00335 } 00336 00337 anchor = pb.skipChar(Symbols::SPACE[0]); 00338 pb.skipToOneOf(Symbols::CRLF); 00339 pb.data(mAddress, anchor); 00340 00341 skipEol(pb); 00342 } 00343 00344 SdpContents::Session::Email::Email(const Data& address, 00345 const Data& freeText) 00346 : mAddress(address), 00347 mFreeText(freeText) 00348 {} 00349 00350 SdpContents::Session::Email::Email(const Email& rhs) 00351 : mAddress(rhs.mAddress), 00352 mFreeText(rhs.mFreeText) 00353 {} 00354 00355 SdpContents::Session::Email& 00356 SdpContents::Session::Email::operator=(const Email& rhs) 00357 { 00358 if (this != &rhs) 00359 { 00360 mAddress = rhs.mAddress; 00361 mFreeText = rhs.mFreeText; 00362 } 00363 return *this; 00364 } 00365 00366 EncodeStream& 00367 SdpContents::Session::Email::encode(EncodeStream& s) const 00368 { 00369 s << "e=" << mAddress; 00370 if (!mFreeText.empty()) 00371 { 00372 s << Symbols::SPACE[0]; 00373 s << Symbols::LPAREN[0] << mFreeText << Symbols::RPAREN[0]; 00374 } 00375 s << Symbols::CRLF; 00376 00377 return s; 00378 } 00379 00380 // helper to parse email and phone numbers with display name 00381 void parseEorP(ParseBuffer& pb, Data& eOrp, Data& freeText) 00382 { 00383 // =mjh@isi.edu (Mark Handley) 00384 // =mjh@isi.edu 00385 // =Mark Handley <mjh@isi.edu> 00386 // =<mjh@isi.edu> 00387 00388 const char* anchor = pb.skipChar(Symbols::EQUALS[0]); 00389 00390 pb.skipToOneOf("<(\n\r"); // find a left angle bracket "<", a left paren "(", or a CR 00391 switch (*pb.position()) 00392 { 00393 case '\n': // Symbols::CR[0] 00394 case '\r': // Symbols::LF[0] 00395 // mjh@isi.edu 00396 // ^ 00397 pb.data(eOrp, anchor); 00398 break; 00399 00400 case '<': // Symbols::LA_QUOTE[0] 00401 // Mark Handley <mjh@isi.edu> 00402 // ^ 00403 // <mjh@isi.edu> 00404 // ^ 00405 00406 pb.data(freeText, anchor); 00407 anchor = pb.skipChar(); 00408 pb.skipToEndQuote(Symbols::RA_QUOTE[0]); 00409 pb.data(eOrp, anchor); 00410 pb.skipChar(Symbols::RA_QUOTE[0]); 00411 break; 00412 00413 case '(': // Symbols::LPAREN[0] 00414 // mjh@isi.edu (Mark Handley) 00415 // ^ 00416 00417 pb.data(eOrp, anchor); 00418 anchor = pb.skipChar(); 00419 pb.skipToEndQuote(Symbols::RPAREN[0]); 00420 pb.data(freeText, anchor); 00421 pb.skipChar(Symbols::RPAREN[0]); 00422 break; 00423 default: 00424 assert(0); 00425 } 00426 } 00427 00428 void 00429 SdpContents::Session::Email::parse(ParseBuffer& pb) 00430 { 00431 pb.skipChar('e'); 00432 parseEorP(pb, mAddress, mFreeText); 00433 skipEol(pb); 00434 } 00435 00436 SdpContents::Session::Phone::Phone(const Data& number, 00437 const Data& freeText) 00438 : mNumber(number), 00439 mFreeText(freeText) 00440 {} 00441 00442 SdpContents::Session::Phone::Phone(const Phone& rhs) 00443 : mNumber(rhs.mNumber), 00444 mFreeText(rhs.mFreeText) 00445 {} 00446 00447 SdpContents::Session::Phone& 00448 SdpContents::Session::Phone::operator=(const Phone& rhs) 00449 { 00450 if (this != &rhs) 00451 { 00452 mNumber = rhs.mNumber; 00453 mFreeText = rhs.mFreeText; 00454 } 00455 return *this; 00456 } 00457 00458 EncodeStream& 00459 SdpContents::Session::Phone::encode(EncodeStream& s) const 00460 { 00461 s << "p=" << mNumber; 00462 if (!mFreeText.empty()) 00463 { 00464 s << Symbols::SPACE[0]; 00465 s << Symbols::LPAREN[0] << mFreeText << Symbols::RPAREN[0]; 00466 } 00467 s << Symbols::CRLF; 00468 00469 return s; 00470 } 00471 00472 void 00473 SdpContents::Session::Phone::parse(ParseBuffer& pb) 00474 { 00475 pb.skipChar('p'); 00476 parseEorP(pb, mNumber, mFreeText); 00477 skipEol(pb); 00478 } 00479 00480 SdpContents::Session::Connection::Connection(AddrType addType, 00481 const Data& address, 00482 unsigned long ttl) 00483 : mAddrType(addType), 00484 mAddress(address), 00485 mTTL(ttl) 00486 {} 00487 00488 SdpContents::Session::Connection::Connection() 00489 : mAddrType(IP4), 00490 mAddress(), 00491 mTTL(0) 00492 {} 00493 00494 SdpContents::Session::Connection::Connection(const Connection& rhs) 00495 : mAddrType(rhs.mAddrType), 00496 mAddress(rhs.mAddress), 00497 mTTL(rhs.mTTL) 00498 { 00499 } 00500 00501 SdpContents::Session::Connection& 00502 SdpContents::Session::Connection::operator=(const Connection& rhs) 00503 { 00504 if (this != &rhs) 00505 { 00506 mAddrType = rhs.mAddrType; 00507 mAddress = rhs.mAddress; 00508 mTTL = rhs.mTTL; 00509 } 00510 return *this; 00511 } 00512 00513 EncodeStream& 00514 SdpContents::Session::Connection::encode(EncodeStream& s) const 00515 { 00516 s << "c=IN " 00517 << NetworkType[mAddrType] << Symbols::SPACE[0] << mAddress; 00518 00519 if (mTTL) 00520 { 00521 s << Symbols::SLASH[0] << mTTL; 00522 } 00523 s << Symbols::CRLF; 00524 return s; 00525 } 00526 00527 void 00528 SdpContents::Session::Connection::setAddress(const Data& host, AddrType addr) 00529 { 00530 mAddress = host; 00531 mAddrType = addr; 00532 } 00533 00534 void 00535 SdpContents::Session::Connection::parse(ParseBuffer& pb) 00536 { 00537 pb.skipChar('c'); 00538 pb.skipChar(Symbols::EQUALS[0]); 00539 pb.skipChar('I'); 00540 pb.skipChar('N'); 00541 00542 const char* anchor = pb.skipChar(Symbols::SPACE[0]); 00543 pb.skipToChar(Symbols::SPACE[0]); 00544 Data addrType; 00545 pb.data(addrType, anchor); 00546 if (addrType == NetworkType[IP4]) 00547 { 00548 mAddrType = IP4; 00549 } 00550 else if (addrType == NetworkType[IP6]) 00551 { 00552 mAddrType = IP6; 00553 } 00554 else 00555 { 00556 mAddrType = static_cast<AddrType>(0); 00557 } 00558 00559 anchor = pb.skipChar(); 00560 pb.skipToOneOf(Symbols::SLASH, Symbols::CRLF); 00561 pb.data(mAddress, anchor); 00562 00563 mTTL = 0; 00564 if (mAddrType == IP4 && !pb.eof() && *pb.position() == Symbols::SLASH[0]) 00565 { 00566 pb.skipChar(); 00567 mTTL = pb.integer(); 00568 } 00569 00570 // multicast dealt with above this parser 00571 if (!pb.eof() && *pb.position() != Symbols::SLASH[0]) 00572 { 00573 skipEol(pb); 00574 } 00575 } 00576 00577 SdpContents::Session::Bandwidth::Bandwidth(const Data& modifier, 00578 unsigned long kbPerSecond) 00579 : mModifier(modifier), 00580 mKbPerSecond(kbPerSecond) 00581 {} 00582 00583 SdpContents::Session::Bandwidth::Bandwidth(const Bandwidth& rhs) 00584 : mModifier(rhs.mModifier), 00585 mKbPerSecond(rhs.mKbPerSecond) 00586 {} 00587 00588 SdpContents::Session::Bandwidth& 00589 SdpContents::Session::Bandwidth::operator=(const Bandwidth& rhs) 00590 { 00591 if (this != &rhs) 00592 { 00593 mModifier = rhs.mModifier; 00594 mKbPerSecond = rhs.mKbPerSecond; 00595 } 00596 return *this; 00597 } 00598 00599 EncodeStream& 00600 SdpContents::Session::Bandwidth::encode(EncodeStream& s) const 00601 { 00602 s << "b=" 00603 << mModifier 00604 << Symbols::COLON[0] << mKbPerSecond 00605 << Symbols::CRLF; 00606 return s; 00607 } 00608 00609 void 00610 SdpContents::Session::Bandwidth::parse(ParseBuffer& pb) 00611 { 00612 pb.skipChar('b'); 00613 const char* anchor = pb.skipChar(Symbols::EQUALS[0]); 00614 00615 pb.skipToOneOf(Symbols::COLON, Symbols::CRLF); 00616 if (*pb.position() == Symbols::COLON[0]) 00617 { 00618 pb.data(mModifier, anchor); 00619 00620 anchor = pb.skipChar(Symbols::COLON[0]); 00621 mKbPerSecond = pb.integer(); 00622 00623 skipEol(pb); 00624 } 00625 else 00626 { 00627 pb.fail(__FILE__, __LINE__); 00628 } 00629 } 00630 00631 SdpContents::Session::Time::Time(unsigned long start, 00632 unsigned long stop) 00633 : mStart(start), 00634 mStop(stop) 00635 {} 00636 00637 SdpContents::Session::Time::Time(const Time& rhs) 00638 : mStart(rhs.mStart), 00639 mStop(rhs.mStop) 00640 {} 00641 00642 SdpContents::Session::Time& 00643 SdpContents::Session::Time::operator=(const Time& rhs) 00644 { 00645 if (this != &rhs) 00646 { 00647 mStart = rhs.mStart; 00648 mStop = rhs.mStop; 00649 mRepeats = rhs.mRepeats; 00650 } 00651 return *this; 00652 } 00653 00654 EncodeStream& 00655 SdpContents::Session::Time::encode(EncodeStream& s) const 00656 { 00657 s << "t=" << mStart << Symbols::SPACE[0] 00658 << mStop 00659 << Symbols::CRLF; 00660 00661 for (list<Repeat>::const_iterator i = mRepeats.begin(); 00662 i != mRepeats.end(); ++i) 00663 { 00664 i->encode(s); 00665 } 00666 return s; 00667 } 00668 00669 void 00670 SdpContents::Session::Time::parse(ParseBuffer& pb) 00671 { 00672 pb.skipChar('t'); 00673 pb.skipChar(Symbols::EQUALS[0]); 00674 00675 mStart = pb.uInt32(); 00676 pb.skipChar(Symbols::SPACE[0]); 00677 mStop = pb.uInt32(); 00678 00679 skipEol(pb); 00680 00681 while (!pb.eof() && *pb.position() == 'r') 00682 { 00683 addRepeat(Repeat()); 00684 mRepeats.back().parse(pb); 00685 } 00686 } 00687 00688 void 00689 SdpContents::Session::Time::addRepeat(const Repeat& repeat) 00690 { 00691 mRepeats.push_back(repeat); 00692 } 00693 00694 SdpContents::Session::Time::Repeat::Repeat(unsigned long interval, 00695 unsigned long duration, 00696 list<int> offsets) 00697 : mInterval(interval), 00698 mDuration(duration), 00699 mOffsets(offsets) 00700 {} 00701 00702 EncodeStream& 00703 SdpContents::Session::Time::Repeat::encode(EncodeStream& s) const 00704 { 00705 s << "r=" 00706 << mInterval << Symbols::SPACE[0] 00707 << mDuration << 's'; 00708 for (list<int>::const_iterator i = mOffsets.begin(); 00709 i != mOffsets.end(); ++i) 00710 { 00711 s << Symbols::SPACE[0] << *i << 's'; 00712 } 00713 00714 s << Symbols::CRLF; 00715 return s; 00716 } 00717 00718 int 00719 parseTypedTime(ParseBuffer& pb) 00720 { 00721 int v = pb.integer(); 00722 if (!pb.eof()) 00723 { 00724 switch (*pb.position()) 00725 { 00726 case 's' : 00727 pb.skipChar(); 00728 break; 00729 case 'm' : 00730 v *= 60; 00731 pb.skipChar(); 00732 break; 00733 case 'h' : 00734 v *= 3600; 00735 pb.skipChar(); 00736 break; 00737 case 'd' : 00738 v *= 3600*24; 00739 pb.skipChar(); 00740 } 00741 } 00742 return v; 00743 } 00744 00745 void 00746 SdpContents::Session::Time::Repeat::parse(ParseBuffer& pb) 00747 { 00748 pb.skipChar('r'); 00749 pb.skipChar(Symbols::EQUALS[0]); 00750 00751 mInterval = parseTypedTime(pb); 00752 pb.skipChar(Symbols::SPACE[0]); 00753 00754 mDuration = parseTypedTime(pb); 00755 00756 while (!pb.eof() && *pb.position() != Symbols::CR[0]) 00757 { 00758 pb.skipChar(Symbols::SPACE[0]); 00759 00760 mOffsets.push_back(parseTypedTime(pb)); 00761 } 00762 00763 skipEol(pb); 00764 } 00765 00766 SdpContents::Session::Timezones::Adjustment::Adjustment(unsigned long _time, 00767 int _offset) 00768 : time(_time), 00769 offset(_offset) 00770 {} 00771 00772 SdpContents::Session::Timezones::Adjustment::Adjustment(const Adjustment& rhs) 00773 : time(rhs.time), 00774 offset(rhs.offset) 00775 {} 00776 00777 SdpContents::Session::Timezones::Adjustment& 00778 SdpContents::Session::Timezones::Adjustment::operator=(const Adjustment& rhs) 00779 { 00780 if (this != &rhs) 00781 { 00782 time = rhs.time; 00783 offset = rhs.offset; 00784 } 00785 return *this; 00786 } 00787 00788 SdpContents::Session::Timezones::Timezones() 00789 : mAdjustments() 00790 {} 00791 00792 SdpContents::Session::Timezones::Timezones(const Timezones& rhs) 00793 : mAdjustments(rhs.mAdjustments) 00794 {} 00795 00796 SdpContents::Session::Timezones& 00797 SdpContents::Session::Timezones::operator=(const Timezones& rhs) 00798 { 00799 if (this != &rhs) 00800 { 00801 mAdjustments = rhs.mAdjustments; 00802 } 00803 return *this; 00804 } 00805 00806 EncodeStream& 00807 SdpContents::Session::Timezones::encode(EncodeStream& s) const 00808 { 00809 if (!mAdjustments.empty()) 00810 { 00811 s << "z="; 00812 bool first = true; 00813 for (list<Adjustment>::const_iterator i = mAdjustments.begin(); 00814 i != mAdjustments.end(); ++i) 00815 { 00816 if (!first) 00817 { 00818 s << Symbols::SPACE[0]; 00819 } 00820 first = false; 00821 s << i->time << Symbols::SPACE[0] 00822 << i->offset << 's'; 00823 } 00824 00825 s << Symbols::CRLF; 00826 } 00827 return s; 00828 } 00829 00830 void 00831 SdpContents::Session::Timezones::parse(ParseBuffer& pb) 00832 { 00833 pb.skipChar('z'); 00834 pb.skipChar(Symbols::EQUALS[0]); 00835 00836 while (!pb.eof() && *pb.position() != Symbols::CR[0]) 00837 { 00838 Adjustment adj(0, 0); 00839 adj.time = pb.integer(); 00840 pb.skipChar(Symbols::SPACE[0]); 00841 adj.offset = parseTypedTime(pb); 00842 addAdjustment(adj); 00843 00844 if (!pb.eof() && *pb.position() == Symbols::SPACE[0]) 00845 { 00846 pb.skipChar(); 00847 } 00848 } 00849 00850 skipEol(pb); 00851 } 00852 00853 void 00854 SdpContents::Session::Timezones::addAdjustment(const Adjustment& adjust) 00855 { 00856 mAdjustments.push_back(adjust); 00857 } 00858 00859 SdpContents::Session::Encryption::Encryption() 00860 : mMethod(NoEncryption), 00861 mKey() 00862 {} 00863 00864 SdpContents::Session::Encryption::Encryption(const KeyType& method, 00865 const Data& key) 00866 : mMethod(method), 00867 mKey(key) 00868 {} 00869 00870 SdpContents::Session::Encryption::Encryption(const Encryption& rhs) 00871 : mMethod(rhs.mMethod), 00872 mKey(rhs.mKey) 00873 {} 00874 00875 SdpContents::Session::Encryption& 00876 SdpContents::Session::Encryption::operator=(const Encryption& rhs) 00877 { 00878 if (this != &rhs) 00879 { 00880 mMethod = rhs.mMethod; 00881 mKey = rhs.mKey; 00882 } 00883 return *this; 00884 } 00885 00886 const char* KeyTypes[] = {"????", "prompt", "clear", "base64", "uri"}; 00887 00888 EncodeStream& 00889 SdpContents::Session::Encryption::encode(EncodeStream& s) const 00890 { 00891 s << "k=" 00892 << KeyTypes[mMethod]; 00893 if (mMethod != Prompt) 00894 { 00895 s << Symbols::COLON[0] << mKey; 00896 } 00897 s << Symbols::CRLF; 00898 00899 return s; 00900 } 00901 00902 void 00903 SdpContents::Session::Encryption::parse(ParseBuffer& pb) 00904 { 00905 pb.skipChar('k'); 00906 const char* anchor = pb.skipChar(Symbols::EQUALS[0]); 00907 00908 pb.skipToChar(Symbols::COLON[0]); 00909 if (!pb.eof()) 00910 { 00911 Data p; 00912 pb.data(p, anchor); 00913 if (p == KeyTypes[Clear]) 00914 { 00915 mMethod = Clear; 00916 } 00917 else if (p == KeyTypes[Base64]) 00918 { 00919 mMethod = Base64; 00920 } 00921 else if (p == KeyTypes[UriKey]) 00922 { 00923 mMethod = UriKey; 00924 } 00925 00926 anchor = pb.skipChar(Symbols::COLON[0]); 00927 pb.skipToOneOf(Symbols::CRLF); 00928 pb.data(mKey, anchor); 00929 } 00930 else 00931 { 00932 pb.reset(anchor); 00933 pb.skipToOneOf(Symbols::CRLF); 00934 00935 Data p; 00936 pb.data(p, anchor); 00937 if (p == KeyTypes[Prompt]) 00938 { 00939 mMethod = Prompt; 00940 } 00941 } 00942 00943 skipEol(pb); 00944 } 00945 00946 SdpContents::Session::Session(int version, 00947 const Origin& origin, 00948 const Data& name) 00949 : mVersion(version), 00950 mOrigin(origin), 00951 mName(name) 00952 {} 00953 00954 SdpContents::Session::Session(const Session& rhs) 00955 { 00956 *this = rhs; 00957 } 00958 00959 SdpContents::Session& 00960 SdpContents::Session::operator=(const Session& rhs) 00961 { 00962 if (this != &rhs) 00963 { 00964 mVersion = rhs.mVersion; 00965 mOrigin = rhs.mOrigin; 00966 mName = rhs.mName; 00967 mMedia = rhs.mMedia; 00968 mInformation = rhs.mInformation; 00969 mUri = rhs.mUri; 00970 mEmails = rhs.mEmails; 00971 mPhones = rhs.mPhones; 00972 mConnection = rhs.mConnection; 00973 mBandwidths = rhs.mBandwidths; 00974 mTimes = rhs.mTimes; 00975 mTimezones = rhs.mTimezones; 00976 mEncryption = rhs.mEncryption; 00977 mAttributeHelper = rhs.mAttributeHelper; 00978 00979 for (MediumContainer::iterator i=mMedia.begin(); i != mMedia.end(); ++i) 00980 { 00981 i->setSession(this); 00982 } 00983 } 00984 return *this; 00985 } 00986 00987 void 00988 SdpContents::Session::parse(ParseBuffer& pb) 00989 { 00990 pb.skipChar('v'); 00991 pb.skipChar(Symbols::EQUALS[0]); 00992 mVersion = pb.integer(); 00993 skipEol(pb); 00994 00995 mOrigin.parse(pb); 00996 00997 pb.skipChar('s'); 00998 const char* anchor = pb.skipChar(Symbols::EQUALS[0]); 00999 pb.skipToOneOf(Symbols::CRLF); 01000 pb.data(mName, anchor); 01001 skipEol(pb); 01002 01003 if (!pb.eof() && *pb.position() == 'i') 01004 { 01005 pb.skipChar('i'); 01006 const char* anchor = pb.skipChar(Symbols::EQUALS[0]); 01007 pb.skipToOneOf(Symbols::CRLF); 01008 pb.data(mInformation, anchor); 01009 skipEol(pb); 01010 } 01011 01012 if (!pb.eof() && *pb.position() == 'u') 01013 { 01014 pb.skipChar('u'); 01015 pb.skipChar(Symbols::EQUALS[0]); 01016 mUri.parse(pb); 01017 skipEol(pb); 01018 } 01019 01020 while (!pb.eof() && *pb.position() == 'e') 01021 { 01022 addEmail(Email()); 01023 mEmails.back().parse(pb); 01024 } 01025 01026 while (!pb.eof() && *pb.position() == 'p') 01027 { 01028 addPhone(Phone()); 01029 mPhones.back().parse(pb); 01030 } 01031 01032 if (!pb.eof() && *pb.position() == 'c') 01033 { 01034 mConnection.parse(pb); 01035 } 01036 01037 while (!pb.eof() && *pb.position() == 'b') 01038 { 01039 addBandwidth(Bandwidth()); 01040 mBandwidths.back().parse(pb); 01041 } 01042 01043 while (!pb.eof() && *pb.position() == 't') 01044 { 01045 addTime(Time()); 01046 mTimes.back().parse(pb); 01047 } 01048 01049 if (!pb.eof() && *pb.position() == 'z') 01050 { 01051 mTimezones.parse(pb); 01052 } 01053 01054 if (!pb.eof() && *pb.position() == 'k') 01055 { 01056 mEncryption.parse(pb); 01057 } 01058 01059 mAttributeHelper.parse(pb); 01060 01061 while (!pb.eof() && *pb.position() == 'm') 01062 { 01063 addMedium(Medium()); 01064 mMedia.back().parse(pb); 01065 } 01066 } 01067 01068 EncodeStream& 01069 SdpContents::Session::encode(EncodeStream& s) const 01070 { 01071 s << "v=" << mVersion << Symbols::CRLF; 01072 mOrigin.encode(s); 01073 s << "s=" << mName << Symbols::CRLF; 01074 01075 if (!mInformation.empty()) 01076 { 01077 s << "i=" << mInformation << Symbols::CRLF; 01078 } 01079 01080 if (!mUri.host().empty()) 01081 { 01082 s << "u="; 01083 mUri.encode(s); 01084 s << Symbols::CRLF; 01085 } 01086 01087 for (list<Email>::const_iterator i = mEmails.begin(); 01088 i != mEmails.end(); ++i) 01089 { 01090 i->encode(s); 01091 } 01092 01093 for (list<Phone>::const_iterator i = mPhones.begin(); 01094 i != mPhones.end(); ++i) 01095 { 01096 i->encode(s); 01097 } 01098 01099 if (!mConnection.getAddress().empty()) 01100 { 01101 mConnection.encode(s); 01102 } 01103 01104 for (list<Bandwidth>::const_iterator i = mBandwidths.begin(); 01105 i != mBandwidths.end(); ++i) 01106 { 01107 i->encode(s); 01108 } 01109 01110 if (mTimes.empty()) 01111 { 01112 s << "t=0 0" << Symbols::CRLF; 01113 } 01114 else 01115 { 01116 for (list<Time>::const_iterator i = mTimes.begin(); 01117 i != mTimes.end(); ++i) 01118 { 01119 i->encode(s); 01120 } 01121 } 01122 01123 mTimezones.encode(s); 01124 01125 if (mEncryption.getMethod() != Encryption::NoEncryption) 01126 { 01127 mEncryption.encode(s); 01128 } 01129 01130 mAttributeHelper.encode(s); 01131 01132 for (MediumContainer::const_iterator i = mMedia.begin(); 01133 i != mMedia.end(); ++i) 01134 { 01135 i->encode(s); 01136 } 01137 01138 return s; 01139 } 01140 01141 void 01142 SdpContents::Session::addEmail(const Email& email) 01143 { 01144 mEmails.push_back(email); 01145 } 01146 01147 void 01148 SdpContents::Session::addTime(const Time& t) 01149 { 01150 mTimes.push_back(t); 01151 } 01152 01153 void 01154 SdpContents::Session::addPhone(const Phone& phone) 01155 { 01156 mPhones.push_back(phone); 01157 } 01158 01159 void 01160 SdpContents::Session::addBandwidth(const Bandwidth& bandwidth) 01161 { 01162 mBandwidths.push_back(bandwidth); 01163 } 01164 01165 void 01166 SdpContents::Session::addMedium(const Medium& medium) 01167 { 01168 mMedia.push_back(medium); 01169 mMedia.back().setSession(this); 01170 } 01171 01172 void 01173 SdpContents::Session::addAttribute(const Data& key, const Data& value) 01174 { 01175 mAttributeHelper.addAttribute(key, value); 01176 01177 if (key == rtpmap) 01178 { 01179 for (MediumContainer::iterator i = mMedia.begin(); 01180 i != mMedia.end(); ++i) 01181 { 01182 i->mRtpMapDone = false; 01183 } 01184 } 01185 } 01186 01187 void 01188 SdpContents::Session::clearAttribute(const Data& key) 01189 { 01190 mAttributeHelper.clearAttribute(key); 01191 01192 if (key == rtpmap) 01193 { 01194 for (MediumContainer::iterator i = mMedia.begin(); 01195 i != mMedia.end(); ++i) 01196 { 01197 i->mRtpMapDone = false; 01198 } 01199 } 01200 } 01201 01202 bool 01203 SdpContents::Session::exists(const Data& key) const 01204 { 01205 return mAttributeHelper.exists(key); 01206 } 01207 01208 const list<Data>& 01209 SdpContents::Session::getValues(const Data& key) const 01210 { 01211 return mAttributeHelper.getValues(key); 01212 } 01213 01214 SdpContents::Session::Medium::Medium(const Data& name, 01215 unsigned long port, 01216 unsigned long multicast, 01217 const Data& protocol) 01218 : mSession(0), 01219 mName(name), 01220 mPort(port), 01221 mMulticast(multicast), 01222 mProtocol(protocol), 01223 mRtpMapDone(false) 01224 {} 01225 01226 SdpContents::Session::Medium::Medium() 01227 : mSession(0), 01228 mPort(0), 01229 mMulticast(1), 01230 mRtpMapDone(false) 01231 {} 01232 01233 SdpContents::Session::Medium::Medium(const Medium& rhs) 01234 : mSession(0), 01235 mName(rhs.mName), 01236 mPort(rhs.mPort), 01237 mMulticast(rhs.mMulticast), 01238 mProtocol(rhs.mProtocol), 01239 mFormats(rhs.mFormats), 01240 mCodecs(rhs.mCodecs), 01241 mTransport(rhs.mTransport), 01242 mInformation(rhs.mInformation), 01243 mConnections(rhs.mConnections), 01244 mBandwidths(rhs.mBandwidths), 01245 mEncryption(rhs.mEncryption), 01246 mAttributeHelper(rhs.mAttributeHelper), 01247 mRtpMapDone(rhs.mRtpMapDone), 01248 mRtpMap(rhs.mRtpMap) 01249 { 01250 } 01251 01252 01253 SdpContents::Session::Medium& 01254 SdpContents::Session::Medium::operator=(const Medium& rhs) 01255 { 01256 if (this != &rhs) 01257 { 01258 mSession = 0; 01259 mName = rhs.mName; 01260 mPort = rhs.mPort; 01261 mMulticast = rhs.mMulticast; 01262 mProtocol = rhs.mProtocol; 01263 mFormats = rhs.mFormats; 01264 mCodecs = rhs.mCodecs; 01265 mTransport = rhs.mTransport; 01266 mInformation = rhs.mInformation; 01267 mConnections = rhs.mConnections; 01268 mBandwidths = rhs.mBandwidths; 01269 mEncryption = rhs.mEncryption; 01270 mAttributeHelper = rhs.mAttributeHelper; 01271 mRtpMapDone = rhs.mRtpMapDone; 01272 mRtpMap = rhs.mRtpMap; 01273 } 01274 return *this; 01275 } 01276 01277 void 01278 SdpContents::Session::Medium::setPort(int port) 01279 { 01280 mPort = port; 01281 } 01282 01283 void 01284 SdpContents::Session::Medium::setSession(Session* session) 01285 { 01286 mSession = session; 01287 } 01288 01289 void 01290 SdpContents::Session::Medium::parse(ParseBuffer& pb) 01291 { 01292 pb.skipChar('m'); 01293 const char* anchor = pb.skipChar(Symbols::EQUALS[0]); 01294 01295 pb.skipToChar(Symbols::SPACE[0]); 01296 pb.data(mName, anchor); 01297 pb.skipChar(Symbols::SPACE[0]); 01298 01299 mPort = pb.integer(); 01300 01301 if (*pb.position() == Symbols::SLASH[0]) 01302 { 01303 pb.skipChar(); 01304 mMulticast = pb.integer(); 01305 } 01306 01307 anchor = pb.skipChar(Symbols::SPACE[0]); 01308 pb.skipToOneOf(Symbols::SPACE, Symbols::CRLF); 01309 pb.data(mProtocol, anchor); 01310 01311 while (*pb.position() != Symbols::CR[0] && 01312 *pb.position() != Symbols::LF[0]) 01313 { 01314 anchor = pb.skipChar(Symbols::SPACE[0]); 01315 pb.skipToOneOf(Symbols::SPACE, Symbols::CRLF); 01316 if(pb.position() != anchor) 01317 { 01318 Data format; 01319 pb.data(format, anchor); 01320 addFormat(format); 01321 } 01322 } 01323 01324 skipEol(pb); 01325 01326 if (!pb.eof() && *pb.position() == 'i') 01327 { 01328 pb.skipChar('i'); 01329 anchor = pb.skipChar(Symbols::EQUALS[0]); 01330 pb.skipToOneOf(Symbols::CRLF); 01331 pb.data(mInformation, anchor); 01332 01333 skipEol(pb); 01334 } 01335 01336 while (!pb.eof() && *pb.position() == 'c') 01337 { 01338 addConnection(Connection()); 01339 mConnections.back().parse(pb); 01340 if (!pb.eof() && *pb.position() == Symbols::SLASH[0]) 01341 { 01342 // Note: we only get here if there was a /<number of addresses> 01343 // parameter following the connection address. 01344 pb.skipChar(); 01345 int num = pb.integer(); 01346 01347 Connection& con = mConnections.back(); 01348 const Data& addr = con.getAddress(); 01349 size_t i = addr.size() - 1; 01350 for (; i; i--) 01351 { 01352 if (addr[i] == '.' || addr[i] == ':') // ipv4 or ipv6 01353 { 01354 break; 01355 } 01356 } 01357 01358 if (addr[i] == '.') // add a number of ipv4 connections 01359 { 01360 Data before(addr.data(), i+1); 01361 ParseBuffer subpb(addr.data()+i+1, addr.size()-i-1); 01362 int after = subpb.integer(); 01363 01364 for (int i = 1; i < num; i++) 01365 { 01366 addConnection(con); 01367 mConnections.back().mAddress = before + Data(after+i); 01368 } 01369 } 01370 if (addr[i] == ':') // add a number of ipv6 connections 01371 { 01372 Data before(addr.data(), i+1); 01373 int after = Helper::hex2integer(addr.data()+i+1); 01374 char hexstring[9]; 01375 01376 for (int i = 1; i < num; i++) 01377 { 01378 addConnection(con); 01379 memset(hexstring, 0, sizeof(hexstring)); 01380 Helper::integer2hex(hexstring, after+i, false /* supress leading zeros */); 01381 mConnections.back().mAddress = before + Data(hexstring); 01382 } 01383 } 01384 01385 skipEol(pb); 01386 } 01387 } 01388 01389 while (!pb.eof() && *pb.position() == 'b') 01390 { 01391 addBandwidth(Bandwidth()); 01392 mBandwidths.back().parse(pb); 01393 } 01394 01395 if (!pb.eof() && *pb.position() == 'k') 01396 { 01397 mEncryption.parse(pb); 01398 } 01399 01400 mAttributeHelper.parse(pb); 01401 } 01402 01403 EncodeStream& 01404 SdpContents::Session::Medium::encode(EncodeStream& s) const 01405 { 01406 s << "m=" 01407 << mName << Symbols::SPACE[0] 01408 << mPort; 01409 if (mMulticast > 1) 01410 { 01411 s << Symbols::SLASH[0] << mMulticast; 01412 } 01413 s << Symbols::SPACE[0] 01414 << mProtocol; 01415 01416 for (list<Data>::const_iterator i = mFormats.begin(); 01417 i != mFormats.end(); ++i) 01418 { 01419 s << Symbols::SPACE[0] << *i; 01420 } 01421 01422 if (!mCodecs.empty()) 01423 { 01424 for (CodecContainer::const_iterator i = mCodecs.begin(); 01425 i != mCodecs.end(); ++i) 01426 { 01427 s << Symbols::SPACE[0] << i->payloadType(); 01428 } 01429 } 01430 01431 s << Symbols::CRLF; 01432 01433 if (!mInformation.empty()) 01434 { 01435 s << "i=" << mInformation << Symbols::CRLF; 01436 } 01437 01438 for (list<Connection>::const_iterator i = mConnections.begin(); 01439 i != mConnections.end(); ++i) 01440 { 01441 i->encode(s); 01442 } 01443 01444 for (list<Bandwidth>::const_iterator i = mBandwidths.begin(); 01445 i != mBandwidths.end(); ++i) 01446 { 01447 i->encode(s); 01448 } 01449 01450 if (mEncryption.getMethod() != Encryption::NoEncryption) 01451 { 01452 mEncryption.encode(s); 01453 } 01454 01455 if (!mCodecs.empty()) 01456 { 01457 // add codecs to information and attributes 01458 for (CodecContainer::const_iterator i = mCodecs.begin(); 01459 i != mCodecs.end(); ++i) 01460 { 01461 // If codec is static (defined in RFC 3551) we probably shouldn't 01462 // add attributes for it. But some UAs do include them. 01463 //Codec::CodecMap& staticCodecs = Codec::getStaticCodecs(); 01464 //if (staticCodecs.find(i->payloadType()) != staticCodecs.end()) 01465 //{ 01466 // continue; 01467 //} 01468 01469 s << "a=rtpmap:" 01470 << i->payloadType() << Symbols::SPACE[0] << *i 01471 << Symbols::CRLF; 01472 if (!i->parameters().empty()) 01473 { 01474 s << "a=fmtp:" 01475 << i->payloadType() << Symbols::SPACE[0] << i->parameters() 01476 << Symbols::CRLF; 01477 } 01478 } 01479 } 01480 01481 mAttributeHelper.encode(s); 01482 01483 return s; 01484 } 01485 01486 void 01487 SdpContents::Session::Medium::addFormat(const Data& format) 01488 { 01489 mFormats.push_back(format); 01490 } 01491 01492 void 01493 SdpContents::Session::Medium::setConnection(const Connection& connection) 01494 { 01495 mConnections.clear(); 01496 addConnection(connection); 01497 } 01498 01499 void 01500 SdpContents::Session::Medium::addConnection(const Connection& connection) 01501 { 01502 mConnections.push_back(connection); 01503 } 01504 01505 void 01506 SdpContents::Session::Medium::setBandwidth(const Bandwidth& bandwidth) 01507 { 01508 mBandwidths.clear(); 01509 addBandwidth(bandwidth); 01510 } 01511 01512 void 01513 SdpContents::Session::Medium::addBandwidth(const Bandwidth& bandwidth) 01514 { 01515 mBandwidths.push_back(bandwidth); 01516 } 01517 01518 void 01519 SdpContents::Session::Medium::addAttribute(const Data& key, const Data& value) 01520 { 01521 mAttributeHelper.addAttribute(key, value); 01522 if (key == rtpmap) 01523 { 01524 mRtpMapDone = false; 01525 } 01526 } 01527 01528 const list<SdpContents::Session::Connection> 01529 SdpContents::Session::Medium::getConnections() const 01530 { 01531 list<Connection> connections = const_cast<Medium*>(this)->getMediumConnections(); 01532 // If there are connections specified at the medium level, then check if a session level 01533 // connection is present - if so then return it 01534 if (connections.empty() && mSession && !mSession->connection().getAddress().empty()) 01535 { 01536 connections.push_back(mSession->connection()); 01537 } 01538 01539 return connections; 01540 } 01541 01542 bool 01543 SdpContents::Session::Medium::exists(const Data& key) const 01544 { 01545 if (mAttributeHelper.exists(key)) 01546 { 01547 return true; 01548 } 01549 return mSession && mSession->exists(key); 01550 } 01551 01552 const list<Data>& 01553 SdpContents::Session::Medium::getValues(const Data& key) const 01554 { 01555 if (mAttributeHelper.exists(key)) 01556 { 01557 return mAttributeHelper.getValues(key); 01558 } 01559 if (!mSession) 01560 { 01561 assert(false); 01562 static list<Data> error; 01563 return error; 01564 } 01565 return mSession->getValues(key); 01566 } 01567 01568 void 01569 SdpContents::Session::Medium::clearAttribute(const Data& key) 01570 { 01571 mAttributeHelper.clearAttribute(key); 01572 if (key == rtpmap) 01573 { 01574 mRtpMapDone = false; 01575 } 01576 } 01577 01578 void 01579 SdpContents::Session::Medium::clearCodecs() 01580 { 01581 mFormats.clear(); 01582 clearAttribute(rtpmap); 01583 clearAttribute(fmtp); 01584 mCodecs.clear(); 01585 } 01586 01587 void 01588 SdpContents::Session::Medium::addCodec(const Codec& codec) 01589 { 01590 codecs(); 01591 mCodecs.push_back(codec); 01592 } 01593 01594 01595 const SdpContents::Session::Medium::CodecContainer& 01596 SdpContents::Session::Medium::codecs() const 01597 { 01598 return const_cast<Medium*>(this)->codecs(); 01599 } 01600 01601 SdpContents::Session::Medium::CodecContainer& 01602 SdpContents::Session::Medium::codecs() 01603 { 01604 #if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER < 1310) // CJ TODO fix 01605 assert(0); 01606 #else 01607 if (!mRtpMapDone) 01608 { 01609 // prevent recursion 01610 mRtpMapDone = true; 01611 01612 if (exists(rtpmap)) 01613 { 01614 for (list<Data>::const_iterator i = getValues(rtpmap).begin(); 01615 i != getValues(rtpmap).end(); ++i) 01616 { 01617 //DebugLog(<< "SdpContents::Session::Medium::getCodec(" << *i << ")"); 01618 ParseBuffer pb(i->data(), i->size()); 01619 int format = pb.integer(); 01620 // pass to codec constructor for parsing 01621 // pass this for other codec attributes 01622 try 01623 { 01624 mRtpMap[format].parse(pb, *this, format); 01625 } 01626 catch (ParseException& e) 01627 { 01628 ErrLog(<<"Caught exception: "<< e); 01629 mRtpMap.erase(format); 01630 } 01631 } 01632 } 01633 01634 for (list<Data>::const_iterator i = mFormats.begin(); 01635 i != mFormats.end(); ++i) 01636 { 01637 int mapKey = i->convertInt(); 01638 RtpMap::const_iterator ri = mRtpMap.find(mapKey); 01639 if (ri != mRtpMap.end()) 01640 { 01641 //DebugLog(<< "SdpContents::Session::Medium::getCodec[](" << ri->second << ")"); 01642 mCodecs.push_back(ri->second); 01643 } 01644 else 01645 { 01646 // !kk! Is it a static format? 01647 Codec::CodecMap& staticCodecs = Codec::getStaticCodecs(); 01648 Codec::CodecMap::const_iterator ri = staticCodecs.find(mapKey); 01649 if (ri != staticCodecs.end()) 01650 { 01651 //DebugLog(<< "Found static codec for format: " << mapKey); 01652 Codec codec(ri->second); 01653 01654 // Look for format parameters, and assign 01655 codec.assignFormatParameters(*this); 01656 01657 mCodecs.push_back(codec); 01658 } 01659 } 01660 } 01661 01662 // don't store twice 01663 mFormats.clear(); 01664 mAttributeHelper.clearAttribute(rtpmap); 01665 mAttributeHelper.clearAttribute(fmtp); // parsed out in codec.parse 01666 } 01667 #endif 01668 01669 return mCodecs; 01670 } 01671 01672 static Codec emptyCodec; 01673 const Codec& 01674 SdpContents::Session::Medium::findFirstMatchingCodecs(const CodecContainer& codecList, Codec* pMatchingCodec) const 01675 { 01676 const CodecContainer& internalCodecList = codecs(); 01677 resip::SdpContents::Session::Medium::CodecContainer::const_iterator sIter; 01678 resip::SdpContents::Session::Medium::CodecContainer::const_iterator sEnd = internalCodecList.end(); 01679 resip::SdpContents::Session::Medium::CodecContainer::const_iterator eIter; 01680 resip::SdpContents::Session::Medium::CodecContainer::const_iterator eEnd = codecList.end(); 01681 for (eIter = codecList.begin(); eIter != eEnd ; ++eIter) 01682 { 01683 for (sIter = internalCodecList.begin(); sIter != sEnd; ++sIter) 01684 { 01685 if (*sIter == *eIter) 01686 { 01687 if (pMatchingCodec) 01688 { 01689 *pMatchingCodec = *eIter; 01690 } 01691 return *sIter; 01692 } 01693 } 01694 } 01695 return emptyCodec; 01696 } 01697 01698 const Codec& 01699 SdpContents::Session::Medium::findFirstMatchingCodecs(const Medium& medium, Codec* pMatchingCodec) const 01700 { 01701 if (&medium == this) 01702 { 01703 return codecs().front(); 01704 } 01705 else 01706 { 01707 return findFirstMatchingCodecs(medium.codecs(), pMatchingCodec); 01708 } 01709 } 01710 01711 int 01712 SdpContents::Session::Medium::findTelephoneEventPayloadType() const 01713 { 01714 const CodecContainer& codecList = codecs(); 01715 for (CodecContainer::const_iterator i = codecList.begin(); i != codecList.end(); i++) 01716 { 01717 if (i->getName() == SdpContents::Session::Codec::TelephoneEvent.getName()) 01718 { 01719 return i->payloadType(); 01720 } 01721 } 01722 return -1; 01723 } 01724 01725 Codec::Codec(const Data& name, 01726 unsigned long rate, 01727 const Data& parameters, 01728 const Data& encodingParameters) 01729 : mName(name), 01730 mRate(rate), 01731 mPayloadType(-1), 01732 mParameters(parameters), 01733 mEncodingParameters(encodingParameters) 01734 { 01735 } 01736 01737 Codec::Codec(const Codec& rhs) 01738 : mName(rhs.mName), 01739 mRate(rhs.mRate), 01740 mPayloadType(rhs.mPayloadType), 01741 mParameters(rhs.mParameters), 01742 mEncodingParameters(rhs.mEncodingParameters) 01743 { 01744 } 01745 01746 Codec::Codec(const Data& name, int payloadType, int rate) 01747 : mName(name), 01748 mRate(rate), 01749 mPayloadType(payloadType) 01750 { 01751 } 01752 01753 Codec& 01754 Codec::operator=(const Codec& rhs) 01755 { 01756 if (this != &rhs) 01757 { 01758 mName = rhs.mName; 01759 mRate = rhs.mRate; 01760 mPayloadType = rhs.mPayloadType; 01761 mParameters = rhs.mParameters; 01762 mEncodingParameters = rhs.mEncodingParameters; 01763 } 01764 return *this; 01765 } 01766 01767 void 01768 Codec::parse(ParseBuffer& pb, 01769 const SdpContents::Session::Medium& medium, 01770 int payloadType) 01771 { 01772 const char* anchor = pb.skipWhitespace(); 01773 pb.skipToChar(Symbols::SLASH[0]); 01774 mName = pb.data(anchor); 01775 if(!pb.eof()) 01776 { 01777 pb.skipChar(Symbols::SLASH[0]); 01778 mRate = pb.integer(); 01779 pb.skipToChar(Symbols::SLASH[0]); 01780 } 01781 if(!pb.eof() && *pb.position() == Symbols::SLASH[0]) 01782 { 01783 anchor = pb.skipChar(Symbols::SLASH[0]); 01784 pb.skipToEnd(); 01785 mEncodingParameters = pb.data(anchor); 01786 } 01787 mPayloadType = payloadType; 01788 01789 assignFormatParameters(medium); 01790 } 01791 01792 void 01793 Codec::assignFormatParameters(const SdpContents::Session::Medium& medium) 01794 { 01795 // get parameters if they exist 01796 if (medium.exists(fmtp)) 01797 { 01798 for (list<Data>::const_iterator i = medium.getValues(fmtp).begin(); 01799 i != medium.getValues(fmtp).end(); ++i) 01800 { 01801 try 01802 { 01803 ParseBuffer pb(i->data(), i->size()); 01804 int payload = pb.integer(); 01805 if (payload == mPayloadType) 01806 { 01807 const char* anchor = pb.skipWhitespace(); 01808 pb.skipToEnd(); 01809 mParameters = pb.data(anchor); 01810 break; 01811 } 01812 } 01813 catch (ParseException &pe) 01814 { 01815 InfoLog(<<"Caught exception when parsing a=fmtp: "<< pe); 01816 } 01817 } 01818 } 01819 } 01820 01821 const Data& 01822 Codec::getName() const 01823 { 01824 return mName; 01825 } 01826 01827 int 01828 Codec::getRate() const 01829 { 01830 return mRate; 01831 } 01832 01833 Codec::CodecMap& Codec::getStaticCodecs() 01834 { 01835 if (! sStaticCodecsCreated) 01836 { 01837 // 01838 // Build map of static codecs as defined in RFC 3551 01839 // 01840 sStaticCodecs = std::auto_ptr<CodecMap>(new CodecMap); 01841 01842 // Audio codecs 01843 sStaticCodecs->insert(make_pair(0,Codec("PCMU",0,8000))); 01844 sStaticCodecs->insert(make_pair(3,Codec("GSM",3,8000))); 01845 sStaticCodecs->insert(make_pair(4,Codec("G723",4,8000))); 01846 sStaticCodecs->insert(make_pair(5,Codec("DVI4",5,8000))); 01847 sStaticCodecs->insert(make_pair(6,Codec("DVI4",6,16000))); 01848 sStaticCodecs->insert(make_pair(7,Codec("LPC",7,8000))); 01849 sStaticCodecs->insert(make_pair(8,Codec("PCMA",8,8000))); 01850 sStaticCodecs->insert(make_pair(9,Codec("G722",9,8000))); 01851 sStaticCodecs->insert(make_pair(10,Codec("L16-2",10,44100))); 01852 sStaticCodecs->insert(make_pair(11,Codec("L16-1",11,44100))); 01853 sStaticCodecs->insert(make_pair(12,Codec("QCELP",12,8000))); 01854 sStaticCodecs->insert(make_pair(13,Codec("CN",13,8000))); 01855 sStaticCodecs->insert(make_pair(14,Codec("MPA",14,90000))); 01856 sStaticCodecs->insert(make_pair(15,Codec("G728",15,8000))); 01857 sStaticCodecs->insert(make_pair(16,Codec("DVI4",16,11025))); 01858 sStaticCodecs->insert(make_pair(17,Codec("DVI4",17,22050))); 01859 sStaticCodecs->insert(make_pair(18,Codec("G729",18,8000))); 01860 01861 // Video or audio/video codecs 01862 sStaticCodecs->insert(make_pair(25,Codec("CelB",25,90000))); 01863 sStaticCodecs->insert(make_pair(26,Codec("JPEG",26,90000))); 01864 sStaticCodecs->insert(make_pair(28,Codec("nv",28,90000))); 01865 sStaticCodecs->insert(make_pair(31,Codec("H261",31,90000))); 01866 sStaticCodecs->insert(make_pair(32,Codec("MPV",32,90000))); 01867 sStaticCodecs->insert(make_pair(33,Codec("MP2T",33,90000))); 01868 sStaticCodecs->insert(make_pair(34,Codec("H263",34,90000))); 01869 01870 sStaticCodecsCreated = true; 01871 } 01872 return *(sStaticCodecs.get()); 01873 } 01874 01875 bool 01876 resip::operator==(const Codec& lhs, const Codec& rhs) 01877 { 01878 static Data defaultEncodingParameters(Data("1")); // Default for audio streams (1-Channel) 01879 return (isEqualNoCase(lhs.mName, rhs.mName) && lhs.mRate == rhs.mRate && 01880 (lhs.mEncodingParameters == rhs.mEncodingParameters || 01881 (lhs.mEncodingParameters.empty() && rhs.mEncodingParameters == defaultEncodingParameters) || 01882 (lhs.mEncodingParameters == defaultEncodingParameters && rhs.mEncodingParameters.empty()))); 01883 } 01884 01885 EncodeStream& 01886 resip::operator<<(EncodeStream& str, const Codec& codec) 01887 { 01888 str << codec.mName; 01889 str << Symbols::SLASH[0]; 01890 str << codec.mRate; 01891 if(!codec.mEncodingParameters.empty()) 01892 { 01893 str << Symbols::SLASH[0]; 01894 str << codec.mEncodingParameters; 01895 } 01896 return str; 01897 } 01898 01899 const Codec Codec::ULaw_8000("PCMU", 0, 8000); 01900 const Codec Codec::ALaw_8000("PCMA", 8, 8000); 01901 const Codec Codec::G729_8000("G729", 18, 8000); 01902 const Codec Codec::G723_8000("G723", 4, 8000); 01903 const Codec Codec::GSM_8000("GSM", 3, 8000); 01904 01905 const Codec Codec::TelephoneEvent("telephone-event", 101, 8000); 01906 const Codec Codec::FrfDialedDigit("frf-dialed-event",102, 8000); 01907 const Codec Codec::CN("CN", 13, 8000); 01908 01909 bool Codec::sStaticCodecsCreated = false; 01910 std::auto_ptr<Codec::CodecMap> Codec::sStaticCodecs; 01911 01912 /* ==================================================================== 01913 * The Vovida Software License, Version 1.0 01914 * 01915 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 01916 * 01917 * Redistribution and use in source and binary forms, with or without 01918 * modification, are permitted provided that the following conditions 01919 * are met: 01920 * 01921 * 1. Redistributions of source code must retain the above copyright 01922 * notice, this list of conditions and the following disclaimer. 01923 * 01924 * 2. Redistributions in binary form must reproduce the above copyright 01925 * notice, this list of conditions and the following disclaimer in 01926 * the documentation and/or other materials provided with the 01927 * distribution. 01928 * 01929 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 01930 * and "Vovida Open Communication Application Library (VOCAL)" must 01931 * not be used to endorse or promote products derived from this 01932 * software without prior written permission. For written 01933 * permission, please contact vocal@vovida.org. 01934 * 01935 * 4. Products derived from this software may not be called "VOCAL", nor 01936 * may "VOCAL" appear in their name, without prior written 01937 * permission of Vovida Networks, Inc. 01938 * 01939 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 01940 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 01941 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 01942 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 01943 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 01944 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 01945 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 01946 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 01947 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 01948 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 01949 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 01950 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 01951 * DAMAGE. 01952 * 01953 * ==================================================================== 01954 * 01955 * This software consists of voluntary contributions made by Vovida 01956 * Networks, Inc. and many individuals on behalf of Vovida Networks, 01957 * Inc. For more information on Vovida Networks, Inc., please see 01958 * <http://www.vovida.org/>. 01959 * 01960 */
1.7.5.1