reSIProcate/stack  9694
SdpContents.cxx
Go to the documentation of this file.
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  */