SipccSdp.cpp (5148B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "sdp/SipccSdp.h" 8 9 #include <cstdlib> 10 11 #include "mozilla/Assertions.h" 12 #include "mozilla/UniquePtr.h" 13 #include "sdp/SdpParser.h" 14 15 #ifdef CRLF 16 # undef CRLF 17 #endif 18 #define CRLF "\r\n" 19 20 namespace mozilla { 21 22 SipccSdp::SipccSdp(const SipccSdp& aOrig) 23 : mOrigin(aOrig.mOrigin), 24 mBandwidths(aOrig.mBandwidths), 25 mAttributeList(aOrig.mAttributeList, nullptr) { 26 for (const auto& msection : aOrig.mMediaSections) { 27 mMediaSections.emplace_back( 28 new SipccSdpMediaSection(*msection, &mAttributeList)); 29 } 30 } 31 32 Sdp* SipccSdp::Clone() const { return new SipccSdp(*this); } 33 34 const SdpOrigin& SipccSdp::GetOrigin() const { return mOrigin; } 35 36 uint32_t SipccSdp::GetBandwidth(const std::string& type) const { 37 auto found = mBandwidths.find(type); 38 if (found == mBandwidths.end()) { 39 return 0; 40 } 41 return found->second; 42 } 43 44 const SdpMediaSection& SipccSdp::GetMediaSection(size_t level) const { 45 if (level > mMediaSections.size()) { 46 MOZ_CRASH(); 47 } 48 return *mMediaSections[level]; 49 } 50 51 SdpMediaSection& SipccSdp::GetMediaSection(size_t level) { 52 if (level > mMediaSections.size()) { 53 MOZ_CRASH(); 54 } 55 return *mMediaSections[level]; 56 } 57 58 SdpMediaSection& SipccSdp::AddMediaSection(SdpMediaSection::MediaType mediaType, 59 SdpDirectionAttribute::Direction dir, 60 uint16_t port, 61 SdpMediaSection::Protocol protocol, 62 sdp::AddrType addrType, 63 const std::string& addr) { 64 size_t level = mMediaSections.size(); 65 SipccSdpMediaSection* media = 66 new SipccSdpMediaSection(level, &mAttributeList); 67 media->mMediaType = mediaType; 68 media->mPort = port; 69 media->mPortCount = 0; 70 media->mProtocol = protocol; 71 media->mConnection = MakeUnique<SdpConnection>(addrType, addr); 72 media->GetAttributeList().SetAttribute(new SdpDirectionAttribute(dir)); 73 mMediaSections.emplace_back(media); 74 return *media; 75 } 76 77 bool SipccSdp::LoadOrigin(sdp_t* sdp, InternalResults& results) { 78 std::string username = sdp_get_owner_username(sdp); 79 uint64_t sessId = strtoull(sdp_get_owner_sessionid(sdp), nullptr, 10); 80 uint64_t sessVer = strtoull(sdp_get_owner_version(sdp), nullptr, 10); 81 82 sdp_nettype_e type = sdp_get_owner_network_type(sdp); 83 if (type != SDP_NT_INTERNET) { 84 results.AddParseError(2, "Unsupported network type"); 85 return false; 86 } 87 88 sdp::AddrType addrType; 89 switch (sdp_get_owner_address_type(sdp)) { 90 case SDP_AT_IP4: 91 addrType = sdp::kIPv4; 92 break; 93 case SDP_AT_IP6: 94 addrType = sdp::kIPv6; 95 break; 96 default: 97 results.AddParseError(2, "Unsupported address type"); 98 return false; 99 } 100 101 std::string address = sdp_get_owner_address(sdp); 102 mOrigin = SdpOrigin(username, sessId, sessVer, addrType, address); 103 return true; 104 } 105 106 bool SipccSdp::Load(sdp_t* sdp, InternalResults& results) { 107 // Believe it or not, SDP_SESSION_LEVEL is 0xFFFF 108 if (!mAttributeList.Load(sdp, SDP_SESSION_LEVEL, results)) { 109 return false; 110 } 111 112 if (!LoadOrigin(sdp, results)) { 113 return false; 114 } 115 116 if (!mBandwidths.Load(sdp, SDP_SESSION_LEVEL, results)) { 117 return false; 118 } 119 120 for (int i = 0; i < sdp_get_num_media_lines(sdp); ++i) { 121 // note that we pass a "level" here that is one higher 122 // sipcc counts media sections from 1, using 0xFFFF as the "session" 123 UniquePtr<SipccSdpMediaSection> section( 124 new SipccSdpMediaSection(i, &mAttributeList)); 125 if (!section->Load(sdp, i + 1, results)) { 126 return false; 127 } 128 mMediaSections.push_back(std::move(section)); 129 } 130 return true; 131 } 132 133 void SipccSdp::Serialize(std::ostream& os) const { 134 os << "v=0" << CRLF << mOrigin << "s=-" << CRLF; 135 136 // We don't support creating i=, u=, e=, p= 137 // We don't generate c= at the session level (only in media) 138 139 mBandwidths.Serialize(os); 140 os << "t=0 0" << CRLF; 141 142 // We don't support r= or z= 143 144 // attributes 145 os << mAttributeList; 146 147 // media sections 148 for (const auto& msection : mMediaSections) { 149 os << *msection; 150 } 151 } 152 153 bool SipccSdpBandwidths::Load(sdp_t* sdp, uint16_t level, 154 InternalResults& results) { 155 size_t count = sdp_get_num_bw_lines(sdp, level); 156 for (size_t i = 1; i <= count; ++i) { 157 sdp_bw_modifier_e bwtype = sdp_get_bw_modifier(sdp, level, i); 158 uint32_t bandwidth = sdp_get_bw_value(sdp, level, i); 159 if (bwtype != SDP_BW_MODIFIER_UNSUPPORTED) { 160 const char* typeName = sdp_get_bw_modifier_name(bwtype); 161 (*this)[typeName] = bandwidth; 162 } 163 } 164 165 return true; 166 } 167 168 void SipccSdpBandwidths::Serialize(std::ostream& os) const { 169 for (auto i = begin(); i != end(); ++i) { 170 os << "b=" << i->first << ":" << i->second << CRLF; 171 } 172 } 173 174 } // namespace mozilla