| /* |
| * Copyright 2021 The WebRTC Project Authors. All rights reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #ifndef PC_JSEP_TRANSPORT_COLLECTION_H_ |
| #define PC_JSEP_TRANSPORT_COLLECTION_H_ |
| |
| #include <functional> |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "api/jsep.h" |
| #include "api/peer_connection_interface.h" |
| #include "api/sequence_checker.h" |
| #include "pc/jsep_transport.h" |
| #include "pc/session_description.h" |
| #include "rtc_base/checks.h" |
| #include "rtc_base/system/no_unique_address.h" |
| #include "rtc_base/thread_annotations.h" |
| |
| namespace webrtc { |
| |
| // This class manages information about RFC 8843 BUNDLE bundles |
| // in SDP descriptions. |
| |
| // This is a work-in-progress. Planned steps: |
| // 1) Move all Bundle-related data structures from JsepTransport |
| // into this class. |
| // 2) Move all Bundle-related functions into this class. |
| // 3) Move remaining Bundle-related logic into this class. |
| // Make data members private. |
| // 4) Refine interface to have comprehensible semantics. |
| // 5) Add unit tests. |
| // 6) Change the logic to do what's right. |
| class BundleManager { |
| public: |
| explicit BundleManager(PeerConnectionInterface::BundlePolicy bundle_policy) |
| : bundle_policy_(bundle_policy) { |
| // Allow constructor to be called on a different thread. |
| sequence_checker_.Detach(); |
| } |
| const std::vector<std::unique_ptr<cricket::ContentGroup>>& bundle_groups() |
| const { |
| RTC_DCHECK_RUN_ON(&sequence_checker_); |
| return bundle_groups_; |
| } |
| // Lookup a bundle group by a member mid name. |
| const cricket::ContentGroup* LookupGroupByMid(const std::string& mid) const; |
| cricket::ContentGroup* LookupGroupByMid(const std::string& mid); |
| // Returns true if the MID is the first item of a group, or if |
| // the MID is not a member of a group. |
| bool IsFirstMidInGroup(const std::string& mid) const; |
| // Update the groups description. This completely replaces the group |
| // description with the one from the SessionDescription. |
| void Update(const cricket::SessionDescription* description, SdpType type); |
| // Delete a MID from the group that contains it. |
| void DeleteMid(const cricket::ContentGroup* bundle_group, |
| const std::string& mid); |
| // Delete a group. |
| void DeleteGroup(const cricket::ContentGroup* bundle_group); |
| // Roll back to previous stable state. |
| void Rollback(); |
| // Commit current bundle groups. |
| void Commit(); |
| |
| private: |
| // Recalculate established_bundle_groups_by_mid_ from bundle_groups_. |
| void RefreshEstablishedBundleGroupsByMid() RTC_RUN_ON(sequence_checker_); |
| |
| RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_; |
| PeerConnectionInterface::BundlePolicy bundle_policy_; |
| std::vector<std::unique_ptr<cricket::ContentGroup>> bundle_groups_ |
| RTC_GUARDED_BY(sequence_checker_); |
| std::vector<std::unique_ptr<cricket::ContentGroup>> stable_bundle_groups_ |
| RTC_GUARDED_BY(sequence_checker_); |
| std::map<std::string, cricket::ContentGroup*> |
| established_bundle_groups_by_mid_; |
| }; |
| |
| // This class keeps the mapping of MIDs to transports. |
| // It is pulled out here because a lot of the code that deals with |
| // bundles end up modifying this map, and the two need to be consistent; |
| // the managers may merge. |
| class JsepTransportCollection { |
| public: |
| JsepTransportCollection(std::function<bool(const std::string& mid, |
| cricket::JsepTransport* transport)> |
| map_change_callback, |
| std::function<void()> state_change_callback) |
| : map_change_callback_(map_change_callback), |
| state_change_callback_(state_change_callback) { |
| // Allow constructor to be called on a different thread. |
| sequence_checker_.Detach(); |
| } |
| |
| void RegisterTransport(const std::string& mid, |
| std::unique_ptr<cricket::JsepTransport> transport); |
| // Returns all transports, including those not currently mapped to any MID |
| // because they're being kept alive in case of rollback. |
| std::vector<cricket::JsepTransport*> Transports(); |
| // Only returns transports currently mapped to a MID. |
| std::vector<cricket::JsepTransport*> ActiveTransports(); |
| void DestroyAllTransports(); |
| // Lookup a JsepTransport by the MID that was used to register it. |
| cricket::JsepTransport* GetTransportByName(const std::string& mid); |
| const cricket::JsepTransport* GetTransportByName( |
| const std::string& mid) const; |
| // Lookup a JsepTransport by any MID that refers to it. |
| cricket::JsepTransport* GetTransportForMid(const std::string& mid); |
| const cricket::JsepTransport* GetTransportForMid( |
| const std::string& mid) const; |
| cricket::JsepTransport* GetTransportForMid(absl::string_view mid); |
| const cricket::JsepTransport* GetTransportForMid(absl::string_view mid) const; |
| // Set transport for a MID. This may destroy a transport if it is no |
| // longer in use. |
| bool SetTransportForMid(const std::string& mid, |
| cricket::JsepTransport* jsep_transport); |
| // Remove a transport for a MID. This may destroy a transport if it is |
| // no longer in use. |
| void RemoveTransportForMid(const std::string& mid); |
| // Roll back to previous stable mid-to-transport mappings. |
| bool RollbackTransports(); |
| // Commit pending mid-transport mappings (rollback is no longer possible), |
| // and destroy unused transports because we know now we'll never need them |
| // again. |
| void CommitTransports(); |
| |
| private: |
| // Returns true if any mid currently maps to this transport. |
| bool TransportInUse(cricket::JsepTransport* jsep_transport) const; |
| |
| // Returns true if any mid in the last stable mapping maps to this transport, |
| // meaning it should be kept alive in case of rollback. |
| bool TransportNeededForRollback(cricket::JsepTransport* jsep_transport) const; |
| |
| // Destroy a transport if it's no longer in use. This includes whether it |
| // will be needed in case of rollback. |
| void MaybeDestroyJsepTransport(cricket::JsepTransport* transport); |
| |
| // Destroys all transports that are no longer in use. |
| void DestroyUnusedTransports(); |
| |
| bool IsConsistent(); // For testing only: Verify internal structure. |
| |
| RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_; |
| // This member owns the JSEP transports. |
| std::map<std::string, std::unique_ptr<cricket::JsepTransport>> |
| jsep_transports_by_name_ RTC_GUARDED_BY(sequence_checker_); |
| |
| // This keeps track of the mapping between media section |
| // (BaseChannel/SctpTransport) and the JsepTransport underneath. |
| std::map<std::string, cricket::JsepTransport*> mid_to_transport_ |
| RTC_GUARDED_BY(sequence_checker_); |
| // A snapshot of mid_to_transport_ at the last stable state. Used for |
| // rollback. |
| std::map<std::string, cricket::JsepTransport*> stable_mid_to_transport_ |
| RTC_GUARDED_BY(sequence_checker_); |
| // Callback used to inform subscribers of altered transports. |
| const std::function<bool(const std::string& mid, |
| cricket::JsepTransport* transport)> |
| map_change_callback_; |
| // Callback used to inform subscribers of possibly altered state. |
| const std::function<void()> state_change_callback_; |
| }; |
| |
| } // namespace webrtc |
| |
| #endif // PC_JSEP_TRANSPORT_COLLECTION_H_ |