Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  jsep.cc

  Sprache: C
 

/*
 *  Copyright 2017 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.h"

#include <algorithm>
#include <cstddef>
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "api/candidate.h"
#include "api/sequence_checker.h"
#include "api/webrtc_sdp.h"
#include "p2p/base/p2p_constants.h"
#include "p2p/base/transport_info.h"
#include "pc/session_description.h"
#include "rtc_base/checks.h"
#include "rtc_base/ip_address.h"
#include "rtc_base/net_helper.h"
#include "rtc_base/net_helpers.h"
#include "rtc_base/socket_address.h"

namespace webrtc {
namespace {
constexpr char kDummyAddress[] = "0.0.0.0";
constexpr int kDummyPort = 9;

// Update the connection address for the MediaContentDescription based on the
// candidates.
void UpdateConnectionAddress(const IceCandidateCollection& candidate_collection,
                             MediaContentDescription* media_desc) {
  int port = kDummyPort;
  std::string ip = kDummyAddress;
  std::string hostname;
  int current_preference = 0;  // Start with lowest preference.
  int current_family = AF_UNSPEC;
  for (size_t i = 0; i < candidate_collection.count(); ++i) {
    const IceCandidate* jsep_candidate = candidate_collection.at(i);
    if (jsep_candidate->candidate().component() !=
        ICE_CANDIDATE_COMPONENT_RTP) {
      continue;
    }
    // Default destination should be UDP only.
    if (jsep_candidate->candidate().protocol() != UDP_PROTOCOL_NAME) {
      continue;
    }
    const int preference = jsep_candidate->candidate().type_preference();
    const int family = jsep_candidate->candidate().address().ipaddr().family();
    // See if this candidate is more preferable then the current one if it's the
    // same family. Or if the current family is IPv4 already so we could safely
    // ignore all IPv6 ones. WebRTC bug 4269.
    // http://code.google.com/p/webrtc/issues/detail?id=4269
    if ((preference <= current_preference && current_family == family) ||
        (current_family == AF_INET && family == AF_INET6)) {
      continue;
    }
    current_preference = preference;
    current_family = family;
    const SocketAddress& candidate_addr = jsep_candidate->candidate().address();
    port = candidate_addr.port();
    ip = candidate_addr.ipaddr().ToString();
    hostname = candidate_addr.hostname();
  }
  SocketAddress connection_addr(ip, port);
  if (IPIsUnspec(connection_addr.ipaddr()) && !hostname.empty()) {
    // When a hostname candidate becomes the (default) connection address,
    // we use the dummy address 0.0.0.0 and port 9 in the c= and the m= lines.
    //
    // We have observed in deployment that with a FQDN in a c= line, SDP parsing
    // could fail in other JSEP implementations. We note that the wildcard
    // addresses (0.0.0.0 or ::) with port 9 are given the exception as the
    // connection address that will not result in an ICE mismatch
    // (draft-ietf-mmusic-ice-sip-sdp). Also, 0.0.0.0 or :: can be used as the
    // connection address in the initial offer or answer with trickle ICE
    // if the offerer or answerer does not want to include the host IP address
    // (draft-ietf-mmusic-trickle-ice-sip), and in particular 0.0.0.0 has been
    // widely deployed for this use without outstanding compatibility issues.
    // Combining the above considerations, we use 0.0.0.0 with port 9 to
    // populate the c= and the m= lines. See `BuildMediaDescription` in
    // webrtc_sdp.cc for the SDP generation with
    // `media_desc->connection_address()`.
    connection_addr = SocketAddress(kDummyAddress, kDummyPort);
  }
  media_desc->set_connection_address(connection_addr);
}

std::vector<IceCandidateCollection> CloneCandidateCollection(
    const std::vector<IceCandidateCollection>& original) {
  std::vector<IceCandidateCollection> ret;
  ret.reserve(original.size());
  for (const auto& collection : original) {
    ret.push_back(collection.Clone());
  }
  return ret;
}
}  // namespace

const char SessionDescriptionInterface::kOffer[] = "offer";
const char SessionDescriptionInterface::kPrAnswer[] = "pranswer";
const char SessionDescriptionInterface::kAnswer[] = "answer";
const char SessionDescriptionInterface::kRollback[] = "rollback";

const char* SdpTypeToString(SdpType type) {
  switch (type) {
    case SdpType::kOffer:
      return SessionDescriptionInterface::kOffer;
    case SdpType::kPrAnswer:
      return SessionDescriptionInterface::kPrAnswer;
    case SdpType::kAnswer:
      return SessionDescriptionInterface::kAnswer;
    case SdpType::kRollback:
      return SessionDescriptionInterface::kRollback;
  }
  return "";
}

std::optional<SdpType> SdpTypeFromString(const std::string& type_str) {
  if (type_str == SessionDescriptionInterface::kOffer) {
    return SdpType::kOffer;
  } else if (type_str == SessionDescriptionInterface::kPrAnswer) {
    return SdpType::kPrAnswer;
  } else if (type_str == SessionDescriptionInterface::kAnswer) {
    return SdpType::kAnswer;
  } else if (type_str == SessionDescriptionInterface::kRollback) {
    return SdpType::kRollback;
  } else {
    return std::nullopt;
  }
}

std::unique_ptr<IceCandidate> CreateIceCandidate(absl::string_view sdp_mid,
                                                 int sdp_mline_index,
                                                 const Candidate& candidate) {
  return std::make_unique<IceCandidate>(sdp_mid, sdp_mline_index, candidate);
}

IceCandidate* CreateIceCandidate(absl::string_view sdp_mid,
                                 int sdp_mline_index,
                                 const std::string& sdp,
                                 SdpParseError* error) {
  return IceCandidate::Create(sdp_mid, sdp_mline_index, sdp, error).release();
}

std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
    SdpType type,
    absl::string_view sdp) {
  return CreateSessionDescription(type, sdp, nullptr);
}

std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
    SdpType type,
    absl::string_view sdp,
    SdpParseError* error_out) {
  if (type == SdpType::kRollback) {
    return CreateRollbackSessionDescription();
  }
  return SdpDeserialize(type, sdp, error_out);
}

std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
    SdpType type,
    absl::string_view session_id,
    absl::string_view session_version,
    std::unique_ptr<SessionDescription> description) {
  return SessionDescriptionInterface::Create(type, std::move(description),
                                             session_id, session_version);
}

std::unique_ptr<SessionDescriptionInterface> CreateRollbackSessionDescription(
    absl::string_view session_id,
    absl::string_view session_version) {
  return SessionDescriptionInterface::Create(
      SdpType::kRollback, /*description=*/nullptr, session_id, session_version);
}

// static
std::unique_ptr<SessionDescriptionInterface>
SessionDescriptionInterface::Create(
    SdpType type,
    std::unique_ptr<SessionDescription> description,
    absl::string_view id,
    absl::string_view version,
    std::vector<IceCandidateCollection> candidates,
    EncodingOptions encoding_options) {
  if (!description && type != SdpType::kRollback)
    return nullptr;
  return absl::WrapUnique(
      new SessionDescriptionInterface(type, std::move(description), id, version,
                                      std::move(candidates), encoding_options));
}

SessionDescriptionInterface::~SessionDescriptionInterface() = default;

void SessionDescriptionInterface::RelinquishThreadOwnership() {
  // Ideally we should require that the method can only be called from the
  // thread that the sequence checker is currently attached to. However that's
  // not compatible with some cases outside of webrtc where initializations
  // happens on one thread and then the object is moved to a second thread (e.g.
  // signaling) where a call is made into webrtc. At that point we'd hit a
  // dcheck like this in webrtc: RTC_DCHECK_RUN_ON(&sequence_checker_);
  sequence_checker_.Detach();
  // Tie the checker to the current thread, which permits iterating
  // `candidate_collection_`
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  for (IceCandidateCollection& collection : candidate_collection_) {
    collection.RelinquishThreadOwnership();
  }
  sequence_checker_.Detach();  // Unties the checker from the current thread.
}

SessionDescriptionInterface::SessionDescriptionInterface(
    SdpType type,
    std::unique_ptr<SessionDescription> desc,
    absl::string_view id,
    absl::string_view version,
    std::vector<IceCandidateCollection> candidates,
    EncodingOptions encoding_options)
    : sdp_type_(type),
      id_(id),
      version_(version),
      description_(std::move(desc)),
      candidate_collection_(std::move(candidates)),
      encoding_options_(encoding_options) {
  RTC_DCHECK(description() || type == SdpType::kRollback);
  RTC_DCHECK(candidate_collection_.empty() ||
             candidate_collection_.size() == number_of_mediasections());
  candidate_collection_.resize(number_of_mediasections());
}

size_t SessionDescriptionInterface::number_of_mediasections() const {
  return description_ ? description_->contents().size() : 0u;
}

std::unique_ptr<SessionDescriptionInterface>
SessionDescriptionInterface::Clone() const {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  return SessionDescriptionInterface::Create(
      sdp_type_, description() ? description()->Clone() : nullptr, id(),
      version(), CloneCandidateCollection(candidate_collection_),
      encoding_options_);
}

bool SessionDescriptionInterface::AddCandidate(const IceCandidate* candidate) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  if (!candidate)
    return false;
  size_t index = 0;
  if (!GetMediasectionIndex(candidate, &index)) {
    return false;
  }
  ContentInfo& content = description()->contents()[index];
  const TransportInfo* transport_info =
      description()->GetTransportInfoByName(content.mid());
  if (!transport_info) {
    return false;
  }

  Candidate updated_candidate = candidate->candidate();
  if (updated_candidate.username().empty()) {
    updated_candidate.set_username(transport_info->description.ice_ufrag);
  }
  if (updated_candidate.password().empty()) {
    updated_candidate.set_password(transport_info->description.ice_pwd);
  }

  // Use `content.mid()` as the mid for the updated candidate. The
  // `candidate->sdp_mid()` property *should* be the same. However, in some
  // cases specifying an empty mid but a valid index is a way to add a candidate
  // without knowing (or caring about) the mid. This is done in several tests.
  RTC_DCHECK(candidate->sdp_mid().empty() ||
             candidate->sdp_mid() == content.mid())
      << "sdp_mid='" << candidate->sdp_mid() << "' content.mid()='"
      << content.mid() << "'";
  auto updated_candidate_wrapper = std::make_unique<IceCandidate>(
      content.mid(), static_cast<int>(index), updated_candidate);
  IceCandidateCollection& candidates = candidate_collection_[index];
  if (!candidates.HasCandidate(updated_candidate_wrapper.get())) {
    candidates.add(std::move(updated_candidate_wrapper));
    UpdateConnectionAddress(candidates, content.media_description());
  }

  return true;
}

bool SessionDescriptionInterface::RemoveCandidate(
    const IceCandidate* candidate) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  size_t index = 0u;
  if (!GetMediasectionIndex(candidate, &index)) {
    return false;
  }
  IceCandidateCollection& candidates = candidate_collection_[index];
  if (!candidates.remove(candidate)) {
    return false;
  }
  UpdateConnectionAddress(candidates,
                          description()->contents()[index].media_description());
  return true;
}

const IceCandidateCollection* SessionDescriptionInterface::candidates(
    size_t mediasection_index) const {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  if (mediasection_index >= candidate_collection_.size())
    return nullptr;
  return &candidate_collection_[mediasection_index];
}

std::string SessionDescriptionInterface::ToString() const {
  return SdpSerialize(*this);
}

bool SessionDescriptionInterface::IsValidMLineIndex(int index) const {
  RTC_DCHECK(description());
  return index >= 0 &&
         index < static_cast<int>(description()->contents().size());
}

bool SessionDescriptionInterface::GetMediasectionIndex(
    const IceCandidate* candidate,
    size_t* index) const {
  if (!candidate || !index || !description()) {
    return false;
  }

  auto mid = candidate->sdp_mid();
  if (!mid.empty()) {
    *index = GetMediasectionIndex(mid);
  } else {
    // An sdp_mline_index of -1 will be treated as invalid.
    *index = static_cast<size_t>(candidate->sdp_mline_index());
  }
  return IsValidMLineIndex(*index);
}

int SessionDescriptionInterface::GetMediasectionIndex(
    absl::string_view mid) const {
  const auto& contents = description()->contents();
  auto it =
      std::find_if(contents.begin(), contents.end(),
                   [&](const auto& content) { return mid == content.mid(); });
  return it == contents.end() ? -1 : std::distance(contents.begin(), it);
}

}  // namespace webrtc

Messung V0.5 in Prozent
C=83 H=100 G=91

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-08-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=434850
#Domains=655579