tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

jsep.h (16321B)


      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 // This file contains declarations of interfaces that wrap SDP-related
     12 // constructs; session descriptions and ICE candidates. The inner "webrtc::"
     13 // objects shouldn't be accessed directly; the intention is that an application
     14 // using the PeerConnection API only creates these objects from strings, and
     15 // them passes them into the PeerConnection.
     16 //
     17 // Though in the future, we're planning to provide an SDP parsing API, with a
     18 // structure more friendly than webrtc::SessionDescription.
     19 
     20 #ifndef API_JSEP_H_
     21 #define API_JSEP_H_
     22 
     23 #include <stddef.h>
     24 
     25 #include <memory>
     26 #include <optional>
     27 #include <string>
     28 #include <utility>
     29 #include <vector>
     30 
     31 #include "absl/base/nullability.h"
     32 #include "absl/strings/str_format.h"
     33 #include "absl/strings/string_view.h"
     34 #include "api/candidate.h"
     35 #include "api/ref_count.h"
     36 #include "api/rtc_error.h"
     37 #include "api/sequence_checker.h"
     38 #include "rtc_base/system/no_unique_address.h"
     39 #include "rtc_base/system/rtc_export.h"
     40 
     41 namespace webrtc {
     42 
     43 class SessionDescription;
     44 
     45 struct SdpParseError {
     46 public:
     47  // The sdp line that causes the error.
     48  std::string line;
     49  // Explains the error.
     50  std::string description;
     51 };
     52 
     53 // Class representation of an ICE candidate.
     54 class RTC_EXPORT IceCandidate final {
     55 public:
     56  IceCandidate(absl::string_view sdp_mid,
     57               int sdp_mline_index,
     58               const Candidate& candidate);
     59  ~IceCandidate() = default;
     60 
     61  IceCandidate(const IceCandidate&) = delete;
     62  IceCandidate& operator=(const IceCandidate&) = delete;
     63 
     64  // Parses an sdp candidate string (only the first line) to construct an
     65  // IceCandidate instance. If an error occurs, details about the error can
     66  // optionally be returned via the `error` paramter, and the function returns
     67  // nullptr.
     68  static std::unique_ptr<IceCandidate> Create(
     69      absl::string_view mid,
     70      int sdp_mline_index,
     71      absl::string_view sdp,
     72      SdpParseError* absl_nullable error = nullptr);
     73 
     74  // If present, this is the value of the "a=mid" attribute of the candidate's
     75  // m= section in SDP, which identifies the m= section.
     76  // TODO: webrtc:406795492 - string_view.
     77  std::string sdp_mid() const { return sdp_mid_; }
     78 
     79  // This indicates the index (starting at zero) of m= section this candidate
     80  // is associated with. Needed when an endpoint doesn't support MIDs.
     81  int sdp_mline_index() const { return sdp_mline_index_; }
     82 
     83  // Only for use internally.
     84  const Candidate& candidate() const { return candidate_; }
     85 
     86  // The URL of the ICE server which this candidate was gathered from.
     87  // TODO: webrtc:406795492 - string_view.
     88  std::string server_url() const { return candidate_.url(); }
     89 
     90  // Creates a SDP-ized form of this candidate.
     91  std::string ToString() const;
     92 
     93  // TODO: webrtc:406795492 - Deprecate and remove this method.
     94  bool ToString(std::string* out) const {
     95    if (!out)
     96      return false;
     97    *out = ToString();
     98    return !out->empty();
     99  }
    100 
    101  template <typename Sink>
    102  friend void AbslStringify(Sink& sink, const IceCandidate& c) {
    103    absl::Format(&sink, "IceCandidate: {'%s', %i, '%s'}", c.sdp_mid_.c_str(),
    104                 c.sdp_mline_index_, c.ToString().c_str());
    105  }
    106 
    107 private:
    108  const std::string sdp_mid_;
    109  const int sdp_mline_index_;
    110  const Candidate candidate_;
    111 };
    112 
    113 // TODO: webrtc:406795492 - Deprecate and eventually remove these types when no
    114 // longer referenced. They're provided here for backwards compatiblity.
    115 using JsepIceCandidate = IceCandidate;
    116 using IceCandidateInterface = IceCandidate;
    117 
    118 // Creates an IceCandidate based on SDP string.
    119 // Returns null if the sdp string can't be parsed.
    120 // `error` may be null.
    121 RTC_EXPORT IceCandidate* CreateIceCandidate(const std::string& sdp_mid,
    122                                            int sdp_mline_index,
    123                                            const std::string& sdp,
    124                                            SdpParseError* error);
    125 
    126 // Creates an IceCandidate based on a parsed candidate structure.
    127 RTC_EXPORT std::unique_ptr<IceCandidate> CreateIceCandidate(
    128    const std::string& sdp_mid,
    129    int sdp_mline_index,
    130    const Candidate& candidate);
    131 
    132 // This class represents a collection of candidates for a specific m= section.
    133 // Used in SessionDescriptionInterface.
    134 class IceCandidateCollection final {
    135 public:
    136  IceCandidateCollection() = default;
    137  explicit IceCandidateCollection(
    138      std::vector<std::unique_ptr<IceCandidate>>&& candidates)
    139      : candidates_(std::move(candidates)) {}
    140  ~IceCandidateCollection() = default;
    141 
    142  // Move constructor is defined so that a vector of IceCandidateCollections
    143  // can be resized.
    144  IceCandidateCollection(IceCandidateCollection&& o) = default;
    145 
    146  IceCandidateCollection(const IceCandidateCollection&) = delete;
    147  IceCandidateCollection& operator=(const IceCandidateCollection&) = delete;
    148 
    149  size_t count() const { return candidates_.size(); }
    150  bool empty() const { return candidates_.empty(); }
    151  const IceCandidate* at(size_t index) const;
    152 
    153  // Adds and takes ownership of the IceCandidate.
    154  void add(std::unique_ptr<IceCandidate> candidate);
    155  [[deprecated("Use unique_ptr version")]]
    156  void add(IceCandidate* candidate);
    157 
    158  // Appends a collection of candidates.
    159  void Append(IceCandidateCollection collection);
    160 
    161  // Removes the candidate that has a matching address and protocol.
    162  //
    163  // Returns the number of candidates that were removed.
    164  size_t remove(const IceCandidate* candidate);
    165 
    166  const std::vector<std::unique_ptr<IceCandidate>>& candidates() const {
    167    return candidates_;
    168  }
    169 
    170  // Returns true if an equivalent `candidate` exist in the collection.
    171  bool HasCandidate(const IceCandidate* candidate) const;
    172 
    173  IceCandidateCollection Clone() const;
    174 
    175 private:
    176  std::vector<std::unique_ptr<IceCandidate>> candidates_;
    177 };
    178 
    179 // TODO: webrtc:406795492 - Deprecate.
    180 using JsepCandidateCollection = IceCandidateCollection;
    181 
    182 // Enum that describes the type of the SessionDescriptionInterface.
    183 // Corresponds to RTCSdpType in the WebRTC specification.
    184 // https://w3c.github.io/webrtc-pc/#dom-rtcsdptype
    185 enum class SdpType {
    186  kOffer,     // Description must be treated as an SDP offer.
    187  kPrAnswer,  // Description must be treated as an SDP answer, but not a final
    188              // answer.
    189  kAnswer,    // Description must be treated as an SDP final answer, and the
    190              // offer-answer exchange must be considered complete after
    191              // receiving this.
    192  kRollback   // Resets any pending offers and sets signaling state back to
    193              // stable.
    194 };
    195 
    196 // Returns the string form of the given SDP type. String forms are defined in
    197 // SessionDescriptionInterface.
    198 RTC_EXPORT const char* SdpTypeToString(SdpType type);
    199 
    200 template <typename Sink>
    201 void AbslStringify(Sink& sink, SdpType sdp_type) {
    202  sink.Append(SdpTypeToString(sdp_type));
    203 }
    204 
    205 // Returns the SdpType from its string form. The string form can be one of the
    206 // constants defined in SessionDescriptionInterface. Passing in any other string
    207 // results in nullopt.
    208 RTC_EXPORT std::optional<SdpType> SdpTypeFromString(
    209    const std::string& type_str);
    210 
    211 // TODO: bugs.webrtc.org/442220720 - This class is temporarily here while
    212 // SessionDescriptionInterface transforms from a pure interface into a simple
    213 // non-virtual class. The purpose of `SessionDescriptionInternal` is to provide
    214 // protected methods to classes currently inheriting from
    215 // SessionDescriptionInterface, the basic implementation that satisified the
    216 // interface. Once the migration of the implementation is complete, the
    217 // SessionDescriptionInterface class can be made non-virtual, final and
    218 // SessionDescriptionInternal can effectively be renamed to
    219 // SessionDescriptionInterface. The reason for all of this is that access to and
    220 // modification of the internal state needs to be made thread aware so that
    221 // concurrent operations aren't executed on different threads or that the
    222 // state can be declared const when no known modifications are pending.
    223 class SessionDescriptionInternal {
    224 public:
    225  explicit SessionDescriptionInternal(
    226      SdpType type,
    227      absl_nullable std::unique_ptr<SessionDescription> description,
    228      absl::string_view id,
    229      absl::string_view version);
    230 
    231  ~SessionDescriptionInternal();
    232 
    233  // Resets the internal sequence_checker_ to not be attached to a particular
    234  // thread. Used when transfering object ownership between threads. Must be
    235  // called by the thread that currently owns the object before transferring the
    236  // ownership.
    237  void RelinquishThreadOwnership();
    238 
    239 protected:
    240  // Only meant for the SessionDescriptionInterface implementation.
    241  SdpType sdp_type() const { return sdp_type_; }
    242  absl::string_view id() const { return id_; }
    243  absl::string_view version() const { return version_; }
    244  const SessionDescription* description() const { return description_.get(); }
    245  SessionDescription* description() { return description_.get(); }
    246  size_t mediasection_count() const;
    247 
    248 protected:
    249  // This method is necessarily `protected`, and not private, while
    250  // the SessionDescriptionInterface implementation is being consolidated
    251  // into a single class.
    252  const SequenceChecker* sequence_checker() const { return &sequence_checker_; }
    253 
    254 private:
    255  RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_{
    256      SequenceChecker::kDetached};
    257  const SdpType sdp_type_;
    258  const std::string id_;
    259  const std::string version_;
    260  absl_nullable const std::unique_ptr<SessionDescription> description_;
    261 };
    262 
    263 // Class representation of an SDP session description.
    264 //
    265 // An instance of this interface is supposed to be owned by one class at a time
    266 // and is therefore not expected to be thread safe.
    267 //
    268 // An instance can be created by CreateSessionDescription.
    269 class RTC_EXPORT SessionDescriptionInterface
    270    : public SessionDescriptionInternal {
    271 public:
    272  static std::unique_ptr<SessionDescriptionInterface> Create(
    273      SdpType type,
    274      std::unique_ptr<SessionDescription> description,
    275      absl::string_view id,
    276      absl::string_view version,
    277      std::vector<IceCandidateCollection> candidates = {});
    278 
    279  SessionDescriptionInterface(const SessionDescriptionInterface&) = delete;
    280  SessionDescriptionInterface& operator=(const SessionDescriptionInterface&) =
    281      delete;
    282 
    283  // String representations of the supported SDP types.
    284  static const char kOffer[];
    285  static const char kPrAnswer[];
    286  static const char kAnswer[];
    287  static const char kRollback[];
    288 
    289  virtual ~SessionDescriptionInterface() {}
    290 
    291  // Create a new SessionDescriptionInterface object
    292  // with the same values as the old object.
    293  virtual std::unique_ptr<SessionDescriptionInterface> Clone() const;
    294 
    295  // Only for use internally.
    296  virtual SessionDescription* description() {
    297    return SessionDescriptionInternal::description();
    298  }
    299  virtual const SessionDescription* description() const {
    300    return SessionDescriptionInternal::description();
    301  }
    302 
    303  // Get the session id and session version, which are defined based on
    304  // RFC 4566 for the SDP o= line.
    305  virtual std::string session_id() const { return std::string(id()); }
    306  virtual std::string session_version() const { return std::string(version()); }
    307 
    308  // Returns the type of this session description as an SdpType. Descriptions of
    309  // the various types are found in the SdpType documentation.
    310  virtual SdpType GetType() const { return sdp_type(); }
    311 
    312  // TODO(steveanton): Remove this in favor of `GetType` that returns SdpType.
    313  virtual std::string type() const { return SdpTypeToString(sdp_type()); }
    314 
    315  // Adds the specified candidate to the description.
    316  //
    317  // Ownership is not transferred.
    318  //
    319  // Returns false if the session description does not have a media section
    320  // that corresponds to `candidate.sdp_mid()` or
    321  // `candidate.sdp_mline_index()`.
    322  virtual bool AddCandidate(const IceCandidate* candidate);
    323 
    324  // Removes the first matching candidate (at most 1) from the description
    325  // that meets the `Candidate::MatchesForRemoval()` requirement and matches
    326  // either the `IceCandidate::sdp_mid()` property or
    327  // `IceCandidate::sdp_mline_index()`.
    328  //
    329  // Returns false if no matching candidate was found (and removed).
    330  virtual bool RemoveCandidate(const IceCandidate* candidate);
    331 
    332  // Returns the number of m= sections in the session description.
    333  virtual size_t number_of_mediasections() const {
    334    return mediasection_count();
    335  }
    336 
    337  // Returns a collection of all candidates that belong to a certain m=
    338  // section.
    339  virtual const IceCandidateCollection* candidates(
    340      size_t mediasection_index) const;
    341 
    342  // Serializes the description to SDP.
    343  virtual bool ToString(std::string* out) const;
    344 
    345  template <typename Sink>
    346  friend void AbslStringify(Sink& sink, const SessionDescriptionInterface& p) {
    347    sink.Append("\n--- BEGIN SDP ");
    348    absl::Format(&sink, "%v", p.GetType());
    349    sink.Append(" ---\n");
    350    std::string temp;
    351    if (p.ToString(&temp)) {
    352      sink.Append(temp);
    353    } else {
    354      sink.Append("Error in ToString\n");
    355    }
    356    sink.Append("--- END SDP ---\n");
    357  }
    358 
    359 protected:
    360  explicit SessionDescriptionInterface(
    361      SdpType type,
    362      std::unique_ptr<SessionDescription> description,
    363      absl::string_view id,
    364      absl::string_view version,
    365      std::vector<IceCandidateCollection> candidates = {});
    366 
    367 private:
    368  bool IsValidMLineIndex(int index) const;
    369  bool GetMediasectionIndex(const IceCandidate* candidate, size_t* index) const;
    370  int GetMediasectionIndex(absl::string_view mid) const;
    371 
    372  std::vector<IceCandidateCollection> candidate_collection_
    373      RTC_GUARDED_BY(sequence_checker());
    374 };
    375 
    376 // Creates a SessionDescriptionInterface based on the SDP string and the type.
    377 // Returns null if the SDP string cannot be parsed.
    378 // If using the signature with `error_out`, details of the parsing error may be
    379 // written to `error_out` if it is not null.
    380 RTC_EXPORT std::unique_ptr<SessionDescriptionInterface>
    381 CreateSessionDescription(SdpType type, const std::string& sdp);
    382 RTC_EXPORT std::unique_ptr<SessionDescriptionInterface>
    383 CreateSessionDescription(SdpType type,
    384                         const std::string& sdp,
    385                         SdpParseError* error_out);
    386 
    387 // Creates a SessionDescriptionInterface based on a parsed SDP structure and the
    388 // given type, ID and version.
    389 std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
    390    SdpType type,
    391    const std::string& session_id,
    392    const std::string& session_version,
    393    std::unique_ptr<SessionDescription> description);
    394 
    395 // Creates a rollback session description object (SdpType::kRollback).
    396 std::unique_ptr<SessionDescriptionInterface> CreateRollbackSessionDescription(
    397    absl::string_view session_id = "",
    398    absl::string_view session_version = "");
    399 
    400 // CreateOffer and CreateAnswer callback interface.
    401 class RTC_EXPORT CreateSessionDescriptionObserver : public RefCountInterface {
    402 public:
    403  // This callback transfers the ownership of the `desc`.
    404  // TODO(deadbeef): Make this take an std::unique_ptr<> to avoid confusion
    405  // around ownership.
    406  virtual void OnSuccess(SessionDescriptionInterface* desc) = 0;
    407  // The OnFailure callback takes an RTCError, which consists of an
    408  // error code and a string.
    409  // RTCError is non-copyable, so it must be passed using std::move.
    410  // Earlier versions of the API used a string argument. This version
    411  // is removed; its functionality was the same as passing
    412  // error.message.
    413  virtual void OnFailure(RTCError error) = 0;
    414 
    415 protected:
    416  ~CreateSessionDescriptionObserver() override = default;
    417 };
    418 
    419 // SetLocalDescription and SetRemoteDescription callback interface.
    420 class RTC_EXPORT SetSessionDescriptionObserver : public RefCountInterface {
    421 public:
    422  virtual void OnSuccess() = 0;
    423  // See description in CreateSessionDescriptionObserver for OnFailure.
    424  virtual void OnFailure(RTCError error) = 0;
    425 
    426 protected:
    427  ~SetSessionDescriptionObserver() override = default;
    428 };
    429 
    430 }  // namespace webrtc
    431 
    432 #endif  // API_JSEP_H_