tor-browser

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

JsepSession.h (10994B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef _JSEPSESSION_H_
      6 #define _JSEPSESSION_H_
      7 
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "jsep/JsepTransceiver.h"
     12 #include "jsep/JsepTransport.h"
     13 #include "mozilla/Attributes.h"
     14 #include "mozilla/Maybe.h"
     15 #include "mozilla/UniquePtr.h"
     16 #include "mozilla/dom/PeerConnectionObserverEnumsBinding.h"
     17 #include "nsError.h"
     18 #include "sdp/Sdp.h"
     19 
     20 namespace mozilla {
     21 
     22 // Forward declarations
     23 class JsepCodecDescription;
     24 
     25 enum JsepSignalingState {
     26  kJsepStateStable,
     27  kJsepStateHaveLocalOffer,
     28  kJsepStateHaveRemoteOffer,
     29  kJsepStateHaveLocalPranswer,
     30  kJsepStateHaveRemotePranswer,
     31  kJsepStateClosed
     32 };
     33 
     34 enum JsepSdpType {
     35  kJsepSdpOffer,
     36  kJsepSdpAnswer,
     37  kJsepSdpPranswer,
     38  kJsepSdpRollback
     39 };
     40 
     41 enum JsepDescriptionPendingOrCurrent {
     42  kJsepDescriptionCurrent,
     43  kJsepDescriptionPending,
     44  kJsepDescriptionPendingOrCurrent
     45 };
     46 
     47 struct JsepOAOptions {};
     48 struct JsepOfferOptions : public JsepOAOptions {
     49  Maybe<size_t> mOfferToReceiveAudio;
     50  Maybe<size_t> mOfferToReceiveVideo;
     51  Maybe<bool> mIceRestart;  // currently ignored by JsepSession
     52 };
     53 struct JsepAnswerOptions : public JsepOAOptions {};
     54 
     55 enum JsepBundlePolicy { kBundleBalanced, kBundleMaxCompat, kBundleMaxBundle };
     56 
     57 enum JsepMediaType { kNone = 0, kAudio, kVideo, kAudioVideo };
     58 
     59 struct JsepExtmapMediaType {
     60  JsepMediaType mMediaType;
     61  SdpExtmapAttributeList::Extmap mExtmap;
     62 };
     63 
     64 class JsepSession {
     65 public:
     66  explicit JsepSession(const std::string& name)
     67      : mName(name), mState(kJsepStateStable), mNegotiations(0) {}
     68  virtual ~JsepSession() {}
     69 
     70  virtual JsepSession* Clone() const = 0;
     71 
     72  virtual nsresult Init() = 0;
     73 
     74  // Accessors for basic properties.
     75  virtual const std::string& GetName() const { return mName; }
     76  virtual JsepSignalingState GetState() const { return mState; }
     77  virtual uint32_t GetNegotiations() const { return mNegotiations; }
     78 
     79  // Set up the ICE And DTLS data.
     80  virtual nsresult SetBundlePolicy(JsepBundlePolicy policy) = 0;
     81  virtual bool RemoteIsIceLite() const = 0;
     82  virtual std::vector<std::string> GetIceOptions() const = 0;
     83 
     84  virtual nsresult AddDtlsFingerprint(const nsACString& algorithm,
     85                                      const std::vector<uint8_t>& value) = 0;
     86 
     87  virtual nsresult AddRtpExtension(
     88      JsepMediaType mediaType, const std::string& extensionName,
     89      SdpDirectionAttribute::Direction direction) = 0;
     90  virtual nsresult AddAudioRtpExtension(
     91      const std::string& extensionName,
     92      SdpDirectionAttribute::Direction direction) = 0;
     93  virtual nsresult AddVideoRtpExtension(
     94      const std::string& extensionName,
     95      SdpDirectionAttribute::Direction direction) = 0;
     96  virtual nsresult AddAudioVideoRtpExtension(
     97      const std::string& extensionName,
     98      SdpDirectionAttribute::Direction direction) = 0;
     99 
    100  // Kinda gross to be locking down the data structure type like this, but
    101  // returning by value is problematic due to the lack of stl move semantics in
    102  // our build config, since we can't use UniquePtr in the container. The
    103  // alternative is writing a raft of accessor functions that allow arbitrary
    104  // manipulation (which will be unwieldy), or allowing functors to be injected
    105  // that manipulate the data structure (still pretty unwieldy).
    106  virtual std::vector<UniquePtr<JsepCodecDescription>>& Codecs() = 0;
    107 
    108  template <class UnaryFunction>
    109  void ForEachCodec(UnaryFunction& function) {
    110    std::for_each(Codecs().begin(), Codecs().end(), function);
    111    for (auto& transceiver : GetTransceivers()) {
    112      transceiver.mSendTrack.ForEachCodec(function);
    113      transceiver.mRecvTrack.ForEachCodec(function);
    114    }
    115  }
    116 
    117  template <class BinaryPredicate>
    118  void SortCodecs(BinaryPredicate& sorter) {
    119    std::stable_sort(Codecs().begin(), Codecs().end(), sorter);
    120    for (auto& transceiver : GetTransceivers()) {
    121      transceiver.mSendTrack.SortCodecs(sorter);
    122      transceiver.mRecvTrack.SortCodecs(sorter);
    123    }
    124  }
    125 
    126  // Would be nice to have this return a Maybe containing the return of
    127  // |aFunction|, but Maybe cannot contain a void.
    128  template <typename UnaryFunction>
    129  bool ApplyToTransceiver(const std::string& aId, UnaryFunction&& aFunction) {
    130    for (auto& transceiver : GetTransceivers()) {
    131      if (transceiver.GetUuid() == aId) {
    132        std::forward<UnaryFunction>(aFunction)(transceiver);
    133        return true;
    134      }
    135    }
    136    return false;
    137  }
    138 
    139  template <typename UnaryFunction>
    140  void ForEachTransceiver(UnaryFunction&& aFunction) {
    141    for (auto& transceiver : GetTransceivers()) {
    142      std::forward<UnaryFunction>(aFunction)(transceiver);
    143    }
    144  }
    145 
    146  template <typename UnaryFunction>
    147  void ForEachTransceiver(UnaryFunction&& aFunction) const {
    148    for (const auto& transceiver : GetTransceivers()) {
    149      std::forward<UnaryFunction>(aFunction)(transceiver);
    150    }
    151  }
    152 
    153  Maybe<const JsepTransceiver> GetTransceiver(const std::string& aId) const {
    154    for (const auto& transceiver : GetTransceivers()) {
    155      if (transceiver.GetUuid() == aId) {
    156        return Some(transceiver);
    157      }
    158    }
    159    return Nothing();
    160  }
    161 
    162  template <typename MatchFunction>
    163  Maybe<const JsepTransceiver> FindTransceiver(MatchFunction&& aFunc) const {
    164    for (const auto& transceiver : GetTransceivers()) {
    165      if (std::forward<MatchFunction>(aFunc)(transceiver)) {
    166        return Some(transceiver);
    167      }
    168    }
    169    return Nothing();
    170  }
    171 
    172  bool SetTransceiver(const JsepTransceiver& aNew) {
    173    return ApplyToTransceiver(aNew.GetUuid(),
    174                              [aNew](JsepTransceiver& aOld) { aOld = aNew; });
    175  }
    176 
    177  virtual void AddTransceiver(const JsepTransceiver& transceiver) = 0;
    178 
    179  class Result {
    180   public:
    181    Result() = default;
    182    MOZ_IMPLICIT Result(dom::PCError aError) : mError(Some(aError)) {}
    183    // TODO(bug 1527916): Need c'tor and members for handling RTCError.
    184    Maybe<dom::PCError> mError;
    185  };
    186 
    187  // Basic JSEP operations.
    188  virtual Result CreateOffer(const JsepOfferOptions& options,
    189                             std::string* offer) = 0;
    190  virtual Result CreateAnswer(const JsepAnswerOptions& options,
    191                              std::string* answer) = 0;
    192  virtual std::string GetLocalDescription(
    193      JsepDescriptionPendingOrCurrent type) const = 0;
    194  virtual std::string GetRemoteDescription(
    195      JsepDescriptionPendingOrCurrent type) const = 0;
    196  virtual Result SetLocalDescription(JsepSdpType type,
    197                                     const std::string& sdp) = 0;
    198  virtual Result SetRemoteDescription(JsepSdpType type,
    199                                      const std::string& sdp) = 0;
    200  virtual Result AddRemoteIceCandidate(const std::string& candidate,
    201                                       const std::string& mid,
    202                                       const Maybe<uint16_t>& level,
    203                                       const std::string& ufrag,
    204                                       std::string* transportId) = 0;
    205  virtual nsresult AddLocalIceCandidate(const std::string& candidate,
    206                                        const std::string& transportId,
    207                                        const std::string& ufrag,
    208                                        uint16_t* level, std::string* mid,
    209                                        bool* skipped) = 0;
    210  virtual nsresult UpdateDefaultCandidate(
    211      const std::string& defaultCandidateAddr, uint16_t defaultCandidatePort,
    212      const std::string& defaultRtcpCandidateAddr,
    213      uint16_t defaultRtcpCandidatePort, const std::string& transportId) = 0;
    214  virtual nsresult Close() = 0;
    215 
    216  // ICE controlling or controlled
    217  virtual bool IsIceControlling() const = 0;
    218  virtual Maybe<bool> IsPendingOfferer() const = 0;
    219  virtual Maybe<bool> IsCurrentOfferer() const = 0;
    220  virtual bool IsIceRestarting() const = 0;
    221  virtual std::set<std::pair<std::string, std::string>> GetLocalIceCredentials()
    222      const = 0;
    223 
    224  virtual const std::string GetLastError() const { return "Error"; }
    225 
    226  virtual const std::vector<std::pair<size_t, std::string>>&
    227  GetLastSdpParsingErrors() const = 0;
    228 
    229  static const char* GetStateStr(JsepSignalingState state) {
    230    static const char* states[] = {"stable",
    231                                   "have-local-offer",
    232                                   "have-remote-offer",
    233                                   "have-local-pranswer",
    234                                   "have-remote-pranswer",
    235                                   "closed"};
    236 
    237    return states[state];
    238  }
    239 
    240  virtual bool CheckNegotiationNeeded() const = 0;
    241 
    242  void CountTransceivers(
    243      uint16_t (&recvonly)[SdpMediaSection::kMediaTypes],
    244      uint16_t (&sendonly)[SdpMediaSection::kMediaTypes],
    245      uint16_t (&sendrecv)[SdpMediaSection::kMediaTypes]) const {
    246    memset(recvonly, 0, sizeof(recvonly));
    247    memset(sendonly, 0, sizeof(sendonly));
    248    memset(sendrecv, 0, sizeof(sendrecv));
    249 
    250    for (const auto& transceiver : GetTransceivers()) {
    251      if (!transceiver.IsNegotiated()) {
    252        continue;
    253      }
    254      if ((transceiver.mRecvTrack.GetActive() &&
    255           transceiver.mSendTrack.GetActive()) ||
    256          transceiver.GetMediaType() == SdpMediaSection::kApplication) {
    257        ++sendrecv[transceiver.GetMediaType()];
    258      } else if (transceiver.mRecvTrack.GetActive()) {
    259        ++recvonly[transceiver.GetMediaType()];
    260      } else if (transceiver.mSendTrack.GetActive()) {
    261        ++sendonly[transceiver.GetMediaType()];
    262      }
    263    }
    264  }
    265 
    266  void CountTracksAndDatachannels(
    267      uint16_t (&receiving)[SdpMediaSection::kMediaTypes],
    268      uint16_t (&sending)[SdpMediaSection::kMediaTypes]) const {
    269    memset(receiving, 0, sizeof(receiving));
    270    memset(sending, 0, sizeof(sending));
    271 
    272    for (const auto& transceiver : GetTransceivers()) {
    273      if (transceiver.mRecvTrack.GetActive() ||
    274          transceiver.GetMediaType() == SdpMediaSection::kApplication) {
    275        receiving[transceiver.mRecvTrack.GetMediaType()]++;
    276      }
    277 
    278      if (transceiver.mSendTrack.GetActive() ||
    279          transceiver.GetMediaType() == SdpMediaSection::kApplication) {
    280        sending[transceiver.mSendTrack.GetMediaType()]++;
    281      }
    282    }
    283  }
    284 
    285  virtual void SetDefaultCodecs(
    286      const std::vector<UniquePtr<JsepCodecDescription>>& aPreferredCodecs) = 0;
    287 
    288  // See Bug 1642419, this can be removed when all sites are working with RTX.
    289  void SetRtxIsAllowed(bool aRtxIsAllowed) { mRtxIsAllowed = aRtxIsAllowed; }
    290 
    291 protected:
    292  friend class JsepSessionTest;
    293  // Returns transceivers in the order they were added.
    294  virtual std::vector<JsepTransceiver>& GetTransceivers() = 0;
    295  virtual const std::vector<JsepTransceiver>& GetTransceivers() const = 0;
    296 
    297  const std::string mName;
    298  JsepSignalingState mState;
    299  uint32_t mNegotiations;
    300 
    301  // See Bug 1642419, this can be removed when all sites are working with RTX.
    302  bool mRtxIsAllowed = true;
    303 };
    304 
    305 }  // namespace mozilla
    306 
    307 #endif