1*d9f75844SAndroid Build Coastguard Worker /* 2*d9f75844SAndroid Build Coastguard Worker * Copyright 2021 The WebRTC Project Authors. All rights reserved. 3*d9f75844SAndroid Build Coastguard Worker * 4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license 5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source 6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found 7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may 8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree. 9*d9f75844SAndroid Build Coastguard Worker */ 10*d9f75844SAndroid Build Coastguard Worker 11*d9f75844SAndroid Build Coastguard Worker #ifndef PC_JSEP_TRANSPORT_COLLECTION_H_ 12*d9f75844SAndroid Build Coastguard Worker #define PC_JSEP_TRANSPORT_COLLECTION_H_ 13*d9f75844SAndroid Build Coastguard Worker 14*d9f75844SAndroid Build Coastguard Worker #include <functional> 15*d9f75844SAndroid Build Coastguard Worker #include <map> 16*d9f75844SAndroid Build Coastguard Worker #include <memory> 17*d9f75844SAndroid Build Coastguard Worker #include <string> 18*d9f75844SAndroid Build Coastguard Worker #include <utility> 19*d9f75844SAndroid Build Coastguard Worker #include <vector> 20*d9f75844SAndroid Build Coastguard Worker 21*d9f75844SAndroid Build Coastguard Worker #include "api/jsep.h" 22*d9f75844SAndroid Build Coastguard Worker #include "api/peer_connection_interface.h" 23*d9f75844SAndroid Build Coastguard Worker #include "api/sequence_checker.h" 24*d9f75844SAndroid Build Coastguard Worker #include "pc/jsep_transport.h" 25*d9f75844SAndroid Build Coastguard Worker #include "pc/session_description.h" 26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h" 27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/system/no_unique_address.h" 28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread_annotations.h" 29*d9f75844SAndroid Build Coastguard Worker 30*d9f75844SAndroid Build Coastguard Worker namespace webrtc { 31*d9f75844SAndroid Build Coastguard Worker 32*d9f75844SAndroid Build Coastguard Worker // This class manages information about RFC 8843 BUNDLE bundles 33*d9f75844SAndroid Build Coastguard Worker // in SDP descriptions. 34*d9f75844SAndroid Build Coastguard Worker 35*d9f75844SAndroid Build Coastguard Worker // This is a work-in-progress. Planned steps: 36*d9f75844SAndroid Build Coastguard Worker // 1) Move all Bundle-related data structures from JsepTransport 37*d9f75844SAndroid Build Coastguard Worker // into this class. 38*d9f75844SAndroid Build Coastguard Worker // 2) Move all Bundle-related functions into this class. 39*d9f75844SAndroid Build Coastguard Worker // 3) Move remaining Bundle-related logic into this class. 40*d9f75844SAndroid Build Coastguard Worker // Make data members private. 41*d9f75844SAndroid Build Coastguard Worker // 4) Refine interface to have comprehensible semantics. 42*d9f75844SAndroid Build Coastguard Worker // 5) Add unit tests. 43*d9f75844SAndroid Build Coastguard Worker // 6) Change the logic to do what's right. 44*d9f75844SAndroid Build Coastguard Worker class BundleManager { 45*d9f75844SAndroid Build Coastguard Worker public: BundleManager(PeerConnectionInterface::BundlePolicy bundle_policy)46*d9f75844SAndroid Build Coastguard Worker explicit BundleManager(PeerConnectionInterface::BundlePolicy bundle_policy) 47*d9f75844SAndroid Build Coastguard Worker : bundle_policy_(bundle_policy) { 48*d9f75844SAndroid Build Coastguard Worker // Allow constructor to be called on a different thread. 49*d9f75844SAndroid Build Coastguard Worker sequence_checker_.Detach(); 50*d9f75844SAndroid Build Coastguard Worker } bundle_groups()51*d9f75844SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<cricket::ContentGroup>>& bundle_groups() 52*d9f75844SAndroid Build Coastguard Worker const { 53*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&sequence_checker_); 54*d9f75844SAndroid Build Coastguard Worker return bundle_groups_; 55*d9f75844SAndroid Build Coastguard Worker } 56*d9f75844SAndroid Build Coastguard Worker // Lookup a bundle group by a member mid name. 57*d9f75844SAndroid Build Coastguard Worker const cricket::ContentGroup* LookupGroupByMid(const std::string& mid) const; 58*d9f75844SAndroid Build Coastguard Worker cricket::ContentGroup* LookupGroupByMid(const std::string& mid); 59*d9f75844SAndroid Build Coastguard Worker // Returns true if the MID is the first item of a group, or if 60*d9f75844SAndroid Build Coastguard Worker // the MID is not a member of a group. 61*d9f75844SAndroid Build Coastguard Worker bool IsFirstMidInGroup(const std::string& mid) const; 62*d9f75844SAndroid Build Coastguard Worker // Update the groups description. This completely replaces the group 63*d9f75844SAndroid Build Coastguard Worker // description with the one from the SessionDescription. 64*d9f75844SAndroid Build Coastguard Worker void Update(const cricket::SessionDescription* description, SdpType type); 65*d9f75844SAndroid Build Coastguard Worker // Delete a MID from the group that contains it. 66*d9f75844SAndroid Build Coastguard Worker void DeleteMid(const cricket::ContentGroup* bundle_group, 67*d9f75844SAndroid Build Coastguard Worker const std::string& mid); 68*d9f75844SAndroid Build Coastguard Worker // Delete a group. 69*d9f75844SAndroid Build Coastguard Worker void DeleteGroup(const cricket::ContentGroup* bundle_group); 70*d9f75844SAndroid Build Coastguard Worker // Roll back to previous stable state. 71*d9f75844SAndroid Build Coastguard Worker void Rollback(); 72*d9f75844SAndroid Build Coastguard Worker // Commit current bundle groups. 73*d9f75844SAndroid Build Coastguard Worker void Commit(); 74*d9f75844SAndroid Build Coastguard Worker 75*d9f75844SAndroid Build Coastguard Worker private: 76*d9f75844SAndroid Build Coastguard Worker // Recalculate established_bundle_groups_by_mid_ from bundle_groups_. 77*d9f75844SAndroid Build Coastguard Worker void RefreshEstablishedBundleGroupsByMid() RTC_RUN_ON(sequence_checker_); 78*d9f75844SAndroid Build Coastguard Worker 79*d9f75844SAndroid Build Coastguard Worker RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_; 80*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::BundlePolicy bundle_policy_; 81*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<cricket::ContentGroup>> bundle_groups_ 82*d9f75844SAndroid Build Coastguard Worker RTC_GUARDED_BY(sequence_checker_); 83*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<cricket::ContentGroup>> stable_bundle_groups_ 84*d9f75844SAndroid Build Coastguard Worker RTC_GUARDED_BY(sequence_checker_); 85*d9f75844SAndroid Build Coastguard Worker std::map<std::string, cricket::ContentGroup*> 86*d9f75844SAndroid Build Coastguard Worker established_bundle_groups_by_mid_; 87*d9f75844SAndroid Build Coastguard Worker }; 88*d9f75844SAndroid Build Coastguard Worker 89*d9f75844SAndroid Build Coastguard Worker // This class keeps the mapping of MIDs to transports. 90*d9f75844SAndroid Build Coastguard Worker // It is pulled out here because a lot of the code that deals with 91*d9f75844SAndroid Build Coastguard Worker // bundles end up modifying this map, and the two need to be consistent; 92*d9f75844SAndroid Build Coastguard Worker // the managers may merge. 93*d9f75844SAndroid Build Coastguard Worker class JsepTransportCollection { 94*d9f75844SAndroid Build Coastguard Worker public: JsepTransportCollection(std::function<bool (const std::string & mid,cricket::JsepTransport * transport)> map_change_callback,std::function<void ()> state_change_callback)95*d9f75844SAndroid Build Coastguard Worker JsepTransportCollection(std::function<bool(const std::string& mid, 96*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* transport)> 97*d9f75844SAndroid Build Coastguard Worker map_change_callback, 98*d9f75844SAndroid Build Coastguard Worker std::function<void()> state_change_callback) 99*d9f75844SAndroid Build Coastguard Worker : map_change_callback_(map_change_callback), 100*d9f75844SAndroid Build Coastguard Worker state_change_callback_(state_change_callback) { 101*d9f75844SAndroid Build Coastguard Worker // Allow constructor to be called on a different thread. 102*d9f75844SAndroid Build Coastguard Worker sequence_checker_.Detach(); 103*d9f75844SAndroid Build Coastguard Worker } 104*d9f75844SAndroid Build Coastguard Worker 105*d9f75844SAndroid Build Coastguard Worker void RegisterTransport(const std::string& mid, 106*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<cricket::JsepTransport> transport); 107*d9f75844SAndroid Build Coastguard Worker // Returns all transports, including those not currently mapped to any MID 108*d9f75844SAndroid Build Coastguard Worker // because they're being kept alive in case of rollback. 109*d9f75844SAndroid Build Coastguard Worker std::vector<cricket::JsepTransport*> Transports(); 110*d9f75844SAndroid Build Coastguard Worker // Only returns transports currently mapped to a MID. 111*d9f75844SAndroid Build Coastguard Worker std::vector<cricket::JsepTransport*> ActiveTransports(); 112*d9f75844SAndroid Build Coastguard Worker void DestroyAllTransports(); 113*d9f75844SAndroid Build Coastguard Worker // Lookup a JsepTransport by the MID that was used to register it. 114*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* GetTransportByName(const std::string& mid); 115*d9f75844SAndroid Build Coastguard Worker const cricket::JsepTransport* GetTransportByName( 116*d9f75844SAndroid Build Coastguard Worker const std::string& mid) const; 117*d9f75844SAndroid Build Coastguard Worker // Lookup a JsepTransport by any MID that refers to it. 118*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* GetTransportForMid(const std::string& mid); 119*d9f75844SAndroid Build Coastguard Worker const cricket::JsepTransport* GetTransportForMid( 120*d9f75844SAndroid Build Coastguard Worker const std::string& mid) const; 121*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* GetTransportForMid(absl::string_view mid); 122*d9f75844SAndroid Build Coastguard Worker const cricket::JsepTransport* GetTransportForMid(absl::string_view mid) const; 123*d9f75844SAndroid Build Coastguard Worker // Set transport for a MID. This may destroy a transport if it is no 124*d9f75844SAndroid Build Coastguard Worker // longer in use. 125*d9f75844SAndroid Build Coastguard Worker bool SetTransportForMid(const std::string& mid, 126*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* jsep_transport); 127*d9f75844SAndroid Build Coastguard Worker // Remove a transport for a MID. This may destroy a transport if it is 128*d9f75844SAndroid Build Coastguard Worker // no longer in use. 129*d9f75844SAndroid Build Coastguard Worker void RemoveTransportForMid(const std::string& mid); 130*d9f75844SAndroid Build Coastguard Worker // Roll back to previous stable mid-to-transport mappings. 131*d9f75844SAndroid Build Coastguard Worker bool RollbackTransports(); 132*d9f75844SAndroid Build Coastguard Worker // Commit pending mid-transport mappings (rollback is no longer possible), 133*d9f75844SAndroid Build Coastguard Worker // and destroy unused transports because we know now we'll never need them 134*d9f75844SAndroid Build Coastguard Worker // again. 135*d9f75844SAndroid Build Coastguard Worker void CommitTransports(); 136*d9f75844SAndroid Build Coastguard Worker 137*d9f75844SAndroid Build Coastguard Worker private: 138*d9f75844SAndroid Build Coastguard Worker // Returns true if any mid currently maps to this transport. 139*d9f75844SAndroid Build Coastguard Worker bool TransportInUse(cricket::JsepTransport* jsep_transport) const; 140*d9f75844SAndroid Build Coastguard Worker 141*d9f75844SAndroid Build Coastguard Worker // Returns true if any mid in the last stable mapping maps to this transport, 142*d9f75844SAndroid Build Coastguard Worker // meaning it should be kept alive in case of rollback. 143*d9f75844SAndroid Build Coastguard Worker bool TransportNeededForRollback(cricket::JsepTransport* jsep_transport) const; 144*d9f75844SAndroid Build Coastguard Worker 145*d9f75844SAndroid Build Coastguard Worker // Destroy a transport if it's no longer in use. This includes whether it 146*d9f75844SAndroid Build Coastguard Worker // will be needed in case of rollback. 147*d9f75844SAndroid Build Coastguard Worker void MaybeDestroyJsepTransport(cricket::JsepTransport* transport); 148*d9f75844SAndroid Build Coastguard Worker 149*d9f75844SAndroid Build Coastguard Worker // Destroys all transports that are no longer in use. 150*d9f75844SAndroid Build Coastguard Worker void DestroyUnusedTransports(); 151*d9f75844SAndroid Build Coastguard Worker 152*d9f75844SAndroid Build Coastguard Worker bool IsConsistent(); // For testing only: Verify internal structure. 153*d9f75844SAndroid Build Coastguard Worker 154*d9f75844SAndroid Build Coastguard Worker RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_; 155*d9f75844SAndroid Build Coastguard Worker // This member owns the JSEP transports. 156*d9f75844SAndroid Build Coastguard Worker std::map<std::string, std::unique_ptr<cricket::JsepTransport>> 157*d9f75844SAndroid Build Coastguard Worker jsep_transports_by_name_ RTC_GUARDED_BY(sequence_checker_); 158*d9f75844SAndroid Build Coastguard Worker 159*d9f75844SAndroid Build Coastguard Worker // This keeps track of the mapping between media section 160*d9f75844SAndroid Build Coastguard Worker // (BaseChannel/SctpTransport) and the JsepTransport underneath. 161*d9f75844SAndroid Build Coastguard Worker std::map<std::string, cricket::JsepTransport*> mid_to_transport_ 162*d9f75844SAndroid Build Coastguard Worker RTC_GUARDED_BY(sequence_checker_); 163*d9f75844SAndroid Build Coastguard Worker // A snapshot of mid_to_transport_ at the last stable state. Used for 164*d9f75844SAndroid Build Coastguard Worker // rollback. 165*d9f75844SAndroid Build Coastguard Worker std::map<std::string, cricket::JsepTransport*> stable_mid_to_transport_ 166*d9f75844SAndroid Build Coastguard Worker RTC_GUARDED_BY(sequence_checker_); 167*d9f75844SAndroid Build Coastguard Worker // Callback used to inform subscribers of altered transports. 168*d9f75844SAndroid Build Coastguard Worker const std::function<bool(const std::string& mid, 169*d9f75844SAndroid Build Coastguard Worker cricket::JsepTransport* transport)> 170*d9f75844SAndroid Build Coastguard Worker map_change_callback_; 171*d9f75844SAndroid Build Coastguard Worker // Callback used to inform subscribers of possibly altered state. 172*d9f75844SAndroid Build Coastguard Worker const std::function<void()> state_change_callback_; 173*d9f75844SAndroid Build Coastguard Worker }; 174*d9f75844SAndroid Build Coastguard Worker 175*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc 176*d9f75844SAndroid Build Coastguard Worker 177*d9f75844SAndroid Build Coastguard Worker #endif // PC_JSEP_TRANSPORT_COLLECTION_H_ 178