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 _JSEPTRANSCEIVER_H_ 6 #define _JSEPTRANSCEIVER_H_ 7 8 #include <string> 9 10 #include "sdp/SdpAttribute.h" 11 #include "sdp/SdpMediaSection.h" 12 #include "sdp/Sdp.h" 13 #include "jsep/JsepTransport.h" 14 #include "jsep/JsepTrack.h" 15 16 #include <mozilla/OwningNonNull.h> 17 #include "nsISupportsImpl.h" 18 #include "nsError.h" 19 20 namespace mozilla { 21 22 class JsepTransceiver { 23 private: ~JsepTransceiver()24 ~JsepTransceiver(){}; 25 26 public: 27 explicit JsepTransceiver(SdpMediaSection::MediaType type, 28 SdpDirectionAttribute::Direction jsDirection = 29 SdpDirectionAttribute::kSendrecv) mJsDirection(jsDirection)30 : mJsDirection(jsDirection), 31 mSendTrack(type, sdp::kSend), 32 mRecvTrack(type, sdp::kRecv), 33 mLevel(SIZE_MAX), 34 mBundleLevel(SIZE_MAX), 35 mAddTrackMagic(false), 36 mWasCreatedBySetRemote(false), 37 mStopped(false), 38 mRemoved(false), 39 mNegotiated(false), 40 mCanRecycle(false) {} 41 42 // Can't use default copy c'tor because of the refcount members. Ugh. JsepTransceiver(const JsepTransceiver & orig)43 JsepTransceiver(const JsepTransceiver& orig) 44 : mJsDirection(orig.mJsDirection), 45 mSendTrack(orig.mSendTrack), 46 mRecvTrack(orig.mRecvTrack), 47 mTransport(orig.mTransport), 48 mMid(orig.mMid), 49 mLevel(orig.mLevel), 50 mBundleLevel(orig.mBundleLevel), 51 mAddTrackMagic(orig.mAddTrackMagic), 52 mWasCreatedBySetRemote(orig.mWasCreatedBySetRemote), 53 mStopped(orig.mStopped), 54 mRemoved(orig.mRemoved), 55 mNegotiated(orig.mNegotiated), 56 mCanRecycle(orig.mCanRecycle) {} 57 58 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(JsepTransceiver); 59 Rollback(JsepTransceiver & oldTransceiver,bool rollbackLevel)60 void Rollback(JsepTransceiver& oldTransceiver, bool rollbackLevel) { 61 MOZ_ASSERT(oldTransceiver.GetMediaType() == GetMediaType()); 62 MOZ_ASSERT(!oldTransceiver.IsNegotiated() || !oldTransceiver.HasLevel() || 63 !HasLevel() || oldTransceiver.GetLevel() == GetLevel()); 64 mTransport = oldTransceiver.mTransport; 65 if (rollbackLevel) { 66 mLevel = oldTransceiver.mLevel; 67 mBundleLevel = oldTransceiver.mBundleLevel; 68 } 69 mRecvTrack = oldTransceiver.mRecvTrack; 70 71 // Don't allow rollback to re-associate a transceiver. 72 if (!oldTransceiver.IsAssociated()) { 73 Disassociate(); 74 } 75 } 76 IsAssociated()77 bool IsAssociated() const { return !mMid.empty(); } 78 GetMid()79 const std::string& GetMid() const { 80 MOZ_ASSERT(IsAssociated()); 81 return mMid; 82 } 83 Associate(const std::string & mid)84 void Associate(const std::string& mid) { 85 MOZ_ASSERT(HasLevel()); 86 mMid = mid; 87 } 88 Disassociate()89 void Disassociate() { mMid.clear(); } 90 HasLevel()91 bool HasLevel() const { return mLevel != SIZE_MAX; } 92 SetLevel(size_t level)93 void SetLevel(size_t level) { 94 MOZ_ASSERT(level != SIZE_MAX); 95 MOZ_ASSERT(!HasLevel()); 96 MOZ_ASSERT(!IsStopped()); 97 98 mLevel = level; 99 } 100 ClearLevel()101 void ClearLevel() { 102 MOZ_ASSERT(!IsAssociated()); 103 mLevel = SIZE_MAX; 104 mBundleLevel = SIZE_MAX; 105 } 106 GetLevel()107 size_t GetLevel() const { 108 MOZ_ASSERT(HasLevel()); 109 return mLevel; 110 } 111 Stop()112 void Stop() { mStopped = true; } 113 IsStopped()114 bool IsStopped() const { return mStopped; } 115 RestartDatachannelTransceiver()116 void RestartDatachannelTransceiver() { 117 MOZ_RELEASE_ASSERT(GetMediaType() == SdpMediaSection::kApplication); 118 mStopped = false; 119 } 120 SetRemoved()121 void SetRemoved() { mRemoved = true; } 122 IsRemoved()123 bool IsRemoved() const { return mRemoved; } 124 HasBundleLevel()125 bool HasBundleLevel() const { return mBundleLevel != SIZE_MAX; } 126 BundleLevel()127 size_t BundleLevel() const { 128 MOZ_ASSERT(HasBundleLevel()); 129 return mBundleLevel; 130 } 131 SetBundleLevel(size_t aBundleLevel)132 void SetBundleLevel(size_t aBundleLevel) { 133 MOZ_ASSERT(aBundleLevel != SIZE_MAX); 134 mBundleLevel = aBundleLevel; 135 } 136 ClearBundleLevel()137 void ClearBundleLevel() { mBundleLevel = SIZE_MAX; } 138 GetTransportLevel()139 size_t GetTransportLevel() const { 140 MOZ_ASSERT(HasLevel()); 141 if (HasBundleLevel()) { 142 return BundleLevel(); 143 } 144 return GetLevel(); 145 } 146 SetAddTrackMagic()147 void SetAddTrackMagic() { mAddTrackMagic = true; } 148 HasAddTrackMagic()149 bool HasAddTrackMagic() const { return mAddTrackMagic; } 150 SetCreatedBySetRemote()151 void SetCreatedBySetRemote() { mWasCreatedBySetRemote = true; } 152 WasCreatedBySetRemote()153 bool WasCreatedBySetRemote() const { return mWasCreatedBySetRemote; } 154 SetNegotiated()155 void SetNegotiated() { 156 MOZ_ASSERT(IsAssociated()); 157 MOZ_ASSERT(HasLevel()); 158 mNegotiated = true; 159 } 160 IsNegotiated()161 bool IsNegotiated() const { return mNegotiated; } 162 SetCanRecycle()163 void SetCanRecycle() { mCanRecycle = true; } 164 CanRecycle()165 bool CanRecycle() const { return mCanRecycle; } 166 167 // Convenience function GetMediaType()168 SdpMediaSection::MediaType GetMediaType() const { 169 MOZ_ASSERT(mRecvTrack.GetMediaType() == mSendTrack.GetMediaType()); 170 return mRecvTrack.GetMediaType(); 171 } 172 HasOwnTransport()173 bool HasOwnTransport() const { 174 if (mTransport.mComponents && 175 (!HasBundleLevel() || (GetLevel() == BundleLevel()))) { 176 return true; 177 } 178 return false; 179 } 180 181 // See Bug 1642419, this can be removed when all sites are working with RTX. SetRtxIsAllowed(bool aRtxIsAllowed)182 void SetRtxIsAllowed(bool aRtxIsAllowed) { 183 mSendTrack.SetRtxIsAllowed(aRtxIsAllowed); 184 mRecvTrack.SetRtxIsAllowed(aRtxIsAllowed); 185 } 186 187 // This is the direction JS wants. It might not actually happen. 188 SdpDirectionAttribute::Direction mJsDirection; 189 190 JsepTrack mSendTrack; 191 JsepTrack mRecvTrack; 192 JsepTransport mTransport; 193 194 private: 195 // Stuff that is not negotiated 196 std::string mMid; 197 size_t mLevel; // SIZE_MAX if no level 198 // Is this track pair sharing a transport with another? 199 size_t mBundleLevel; // SIZE_MAX if no bundle level 200 // The w3c and IETF specs have a lot of "magical" behavior that happens 201 // when addTrack is used. This was a deliberate design choice. Sadface. 202 bool mAddTrackMagic; 203 bool mWasCreatedBySetRemote; 204 bool mStopped; 205 bool mRemoved; 206 bool mNegotiated; 207 bool mCanRecycle; 208 }; 209 210 } // namespace mozilla 211 212 #endif // _JSEPTRANSCEIVER_H_ 213