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