| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license | |
| 5 * that can be found in the LICENSE file in the root of the source | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #include "webrtc/api/jsepsessiondescription.h" | |
| 12 | |
| 13 #include <memory> | |
| 14 | |
| 15 #include "webrtc/api/webrtcsdp.h" | |
| 16 #include "webrtc/base/arraysize.h" | |
| 17 #include "webrtc/base/stringencode.h" | |
| 18 #include "webrtc/pc/mediasession.h" | |
| 19 | |
| 20 using cricket::SessionDescription; | |
| 21 | |
| 22 namespace webrtc { | |
| 23 | |
| 24 static const char* kSupportedTypes[] = { | |
| 25 JsepSessionDescription::kOffer, | |
| 26 JsepSessionDescription::kPrAnswer, | |
| 27 JsepSessionDescription::kAnswer | |
| 28 }; | |
| 29 | |
| 30 static bool IsTypeSupported(const std::string& type) { | |
| 31 bool type_supported = false; | |
| 32 for (size_t i = 0; i < arraysize(kSupportedTypes); ++i) { | |
| 33 if (kSupportedTypes[i] == type) { | |
| 34 type_supported = true; | |
| 35 break; | |
| 36 } | |
| 37 } | |
| 38 return type_supported; | |
| 39 } | |
| 40 | |
| 41 const char SessionDescriptionInterface::kOffer[] = "offer"; | |
| 42 const char SessionDescriptionInterface::kPrAnswer[] = "pranswer"; | |
| 43 const char SessionDescriptionInterface::kAnswer[] = "answer"; | |
| 44 | |
| 45 const int JsepSessionDescription::kDefaultVideoCodecId = 100; | |
| 46 const char JsepSessionDescription::kDefaultVideoCodecName[] = "VP8"; | |
| 47 | |
| 48 SessionDescriptionInterface* CreateSessionDescription(const std::string& type, | |
| 49 const std::string& sdp, | |
| 50 SdpParseError* error) { | |
| 51 if (!IsTypeSupported(type)) { | |
| 52 return NULL; | |
| 53 } | |
| 54 | |
| 55 JsepSessionDescription* jsep_desc = new JsepSessionDescription(type); | |
| 56 if (!jsep_desc->Initialize(sdp, error)) { | |
| 57 delete jsep_desc; | |
| 58 return NULL; | |
| 59 } | |
| 60 return jsep_desc; | |
| 61 } | |
| 62 | |
| 63 JsepSessionDescription::JsepSessionDescription(const std::string& type) | |
| 64 : type_(type) { | |
| 65 } | |
| 66 | |
| 67 JsepSessionDescription::~JsepSessionDescription() {} | |
| 68 | |
| 69 bool JsepSessionDescription::Initialize( | |
| 70 cricket::SessionDescription* description, | |
| 71 const std::string& session_id, | |
| 72 const std::string& session_version) { | |
| 73 if (!description) | |
| 74 return false; | |
| 75 | |
| 76 session_id_ = session_id; | |
| 77 session_version_ = session_version; | |
| 78 description_.reset(description); | |
| 79 candidate_collection_.resize(number_of_mediasections()); | |
| 80 return true; | |
| 81 } | |
| 82 | |
| 83 bool JsepSessionDescription::Initialize(const std::string& sdp, | |
| 84 SdpParseError* error) { | |
| 85 return SdpDeserialize(sdp, this, error); | |
| 86 } | |
| 87 | |
| 88 bool JsepSessionDescription::AddCandidate( | |
| 89 const IceCandidateInterface* candidate) { | |
| 90 if (!candidate || candidate->sdp_mline_index() < 0) | |
| 91 return false; | |
| 92 size_t mediasection_index = 0; | |
| 93 if (!GetMediasectionIndex(candidate, &mediasection_index)) { | |
| 94 return false; | |
| 95 } | |
| 96 if (mediasection_index >= number_of_mediasections()) | |
| 97 return false; | |
| 98 const std::string& content_name = | |
| 99 description_->contents()[mediasection_index].name; | |
| 100 const cricket::TransportInfo* transport_info = | |
| 101 description_->GetTransportInfoByName(content_name); | |
| 102 if (!transport_info) { | |
| 103 return false; | |
| 104 } | |
| 105 | |
| 106 cricket::Candidate updated_candidate = candidate->candidate(); | |
| 107 if (updated_candidate.username().empty()) { | |
| 108 updated_candidate.set_username(transport_info->description.ice_ufrag); | |
| 109 } | |
| 110 if (updated_candidate.password().empty()) { | |
| 111 updated_candidate.set_password(transport_info->description.ice_pwd); | |
| 112 } | |
| 113 | |
| 114 std::unique_ptr<JsepIceCandidate> updated_candidate_wrapper( | |
| 115 new JsepIceCandidate(candidate->sdp_mid(), | |
| 116 static_cast<int>(mediasection_index), | |
| 117 updated_candidate)); | |
| 118 if (!candidate_collection_[mediasection_index].HasCandidate( | |
| 119 updated_candidate_wrapper.get())) | |
| 120 candidate_collection_[mediasection_index].add( | |
| 121 updated_candidate_wrapper.release()); | |
| 122 | |
| 123 return true; | |
| 124 } | |
| 125 | |
| 126 size_t JsepSessionDescription::RemoveCandidates( | |
| 127 const std::vector<cricket::Candidate>& candidates) { | |
| 128 size_t num_removed = 0; | |
| 129 for (auto& candidate : candidates) { | |
| 130 int mediasection_index = GetMediasectionIndex(candidate); | |
| 131 if (mediasection_index < 0) { | |
| 132 // Not found. | |
| 133 continue; | |
| 134 } | |
| 135 num_removed += candidate_collection_[mediasection_index].remove(candidate); | |
| 136 } | |
| 137 return num_removed; | |
| 138 } | |
| 139 | |
| 140 size_t JsepSessionDescription::number_of_mediasections() const { | |
| 141 if (!description_) | |
| 142 return 0; | |
| 143 return description_->contents().size(); | |
| 144 } | |
| 145 | |
| 146 const IceCandidateCollection* JsepSessionDescription::candidates( | |
| 147 size_t mediasection_index) const { | |
| 148 if (mediasection_index >= candidate_collection_.size()) | |
| 149 return NULL; | |
| 150 return &candidate_collection_[mediasection_index]; | |
| 151 } | |
| 152 | |
| 153 bool JsepSessionDescription::ToString(std::string* out) const { | |
| 154 if (!description_ || !out) { | |
| 155 return false; | |
| 156 } | |
| 157 *out = SdpSerialize(*this, false); | |
| 158 return !out->empty(); | |
| 159 } | |
| 160 | |
| 161 bool JsepSessionDescription::GetMediasectionIndex( | |
| 162 const IceCandidateInterface* candidate, | |
| 163 size_t* index) { | |
| 164 if (!candidate || !index) { | |
| 165 return false; | |
| 166 } | |
| 167 *index = static_cast<size_t>(candidate->sdp_mline_index()); | |
| 168 if (description_ && !candidate->sdp_mid().empty()) { | |
| 169 bool found = false; | |
| 170 // Try to match the sdp_mid with content name. | |
| 171 for (size_t i = 0; i < description_->contents().size(); ++i) { | |
| 172 if (candidate->sdp_mid() == description_->contents().at(i).name) { | |
| 173 *index = i; | |
| 174 found = true; | |
| 175 break; | |
| 176 } | |
| 177 } | |
| 178 if (!found) { | |
| 179 // If the sdp_mid is presented but we can't find a match, we consider | |
| 180 // this as an error. | |
| 181 return false; | |
| 182 } | |
| 183 } | |
| 184 return true; | |
| 185 } | |
| 186 | |
| 187 int JsepSessionDescription::GetMediasectionIndex( | |
| 188 const cricket::Candidate& candidate) { | |
| 189 // Find the description with a matching transport name of the candidate. | |
| 190 const std::string& transport_name = candidate.transport_name(); | |
| 191 for (size_t i = 0; i < description_->contents().size(); ++i) { | |
| 192 if (transport_name == description_->contents().at(i).name) { | |
| 193 return static_cast<int>(i); | |
| 194 } | |
| 195 } | |
| 196 return -1; | |
| 197 } | |
| 198 | |
| 199 } // namespace webrtc | |
| OLD | NEW |