| /* |
| * Copyright 2018 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "api/jsep_ice_candidate.h" |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <limits> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "absl/algorithm/container.h" |
| #include "absl/memory/memory.h" |
| #include "absl/strings/string_view.h" |
| #include "api/candidate.h" |
| #include "api/jsep.h" |
| #include "rtc_base/checks.h" |
| #include "rtc_base/logging.h" |
| |
| namespace webrtc { |
| namespace { |
| // The sdpMLineIndex property is an unsigned short, a zero based index of the |
| // m-line associated with the candidate. This function ensures we consistently |
| // set the property to -1 for out-of-bounds values, to make candidate |
| // comparisons more robust. |
| int EnsureValidMLineIndex(int sdp_mline_index) { |
| if (sdp_mline_index < 0 || |
| sdp_mline_index > std::numeric_limits<uint16_t>::max()) |
| return -1; |
| return sdp_mline_index; |
| } |
| } // namespace |
| |
| IceCandidate::IceCandidate(absl::string_view sdp_mid, |
| int sdp_mline_index, |
| const Candidate& candidate) |
| : sdp_mid_(sdp_mid), |
| sdp_mline_index_(EnsureValidMLineIndex(sdp_mline_index)), |
| candidate_(candidate) { |
| if (sdp_mid_.empty() && sdp_mline_index_ < 0) { |
| RTC_LOG(LS_ERROR) << "Neither mid nor index supplied for IceCandidate."; |
| } |
| } |
| |
| void IceCandidateCollection::add(std::unique_ptr<IceCandidate> candidate) { |
| candidates_.push_back(std::move(candidate)); |
| } |
| |
| void IceCandidateCollection::add(IceCandidate* candidate) { |
| candidates_.push_back(absl::WrapUnique(candidate)); |
| } |
| |
| const IceCandidate* IceCandidateCollection::at(size_t index) const { |
| return candidates_[index].get(); |
| } |
| |
| bool IceCandidateCollection::HasCandidate(const IceCandidate* candidate) const { |
| const auto sdp_mid = candidate->sdp_mid(); // avoid string copy per entry. |
| return absl::c_any_of( |
| candidates_, [&](const std::unique_ptr<IceCandidate>& entry) { |
| if (!entry->candidate().IsEquivalent(candidate->candidate())) { |
| return false; |
| } |
| if (!sdp_mid.empty()) { |
| // In this case, we ignore the `sdp_mline_index()` property. |
| return sdp_mid == entry->sdp_mid(); |
| } |
| RTC_DCHECK_NE(candidate->sdp_mline_index(), -1); |
| return candidate->sdp_mline_index() == entry->sdp_mline_index(); |
| }); |
| } |
| |
| size_t JsepCandidateCollection::remove(const IceCandidate* candidate) { |
| RTC_DCHECK(candidate); |
| auto iter = |
| absl::c_find_if(candidates_, [&](const std::unique_ptr<IceCandidate>& c) { |
| return c->candidate().MatchesForRemoval(candidate->candidate()); |
| }); |
| if (iter != candidates_.end()) { |
| candidates_.erase(iter); |
| return 1u; |
| } |
| return 0u; |
| } |
| |
| } // namespace webrtc |