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