| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2019 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_DATA_CHANNEL_CONTROLLER_H_ |
| 12 | #define PC_DATA_CHANNEL_CONTROLLER_H_ |
| 13 | |
| Harald Alvestrand | f0d5caf | 2025-04-07 09:08:51 | [diff] [blame] | 14 | #include <cstddef> |
| 15 | #include <cstdint> |
| Philip Eliasson | 17ddd31 | 2025-04-08 08:33:49 | [diff] [blame] | 16 | #include <memory> |
| Harald Alvestrand | f0d5caf | 2025-04-07 09:08:51 | [diff] [blame] | 17 | #include <optional> |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 18 | #include <string> |
| 19 | #include <vector> |
| 20 | |
| Philip Eliasson | 17ddd31 | 2025-04-08 08:33:49 | [diff] [blame] | 21 | #include "api/array_view.h" |
| 22 | #include "api/data_channel_event_observer_interface.h" |
| Harald Alvestrand | 5761e7b | 2021-01-29 14:45:08 | [diff] [blame] | 23 | #include "api/data_channel_interface.h" |
| Florent Castelli | 0012bfa | 2024-07-26 16:16:41 | [diff] [blame] | 24 | #include "api/priority.h" |
| Harald Alvestrand | c24a218 | 2022-02-23 13:44:59 | [diff] [blame] | 25 | #include "api/rtc_error.h" |
| Harald Alvestrand | 5761e7b | 2021-01-29 14:45:08 | [diff] [blame] | 26 | #include "api/scoped_refptr.h" |
| Artem Titov | d15a575 | 2021-02-10 13:31:24 | [diff] [blame] | 27 | #include "api/sequence_checker.h" |
| Tommi | 13759ba | 2023-03-06 11:51:39 | [diff] [blame] | 28 | #include "api/task_queue/pending_task_safety_flag.h" |
| Harald Alvestrand | 5761e7b | 2021-01-29 14:45:08 | [diff] [blame] | 29 | #include "api/transport/data_channel_transport_interface.h" |
| Harald Alvestrand | 5761e7b | 2021-01-29 14:45:08 | [diff] [blame] | 30 | #include "pc/data_channel_utils.h" |
| Taylor Brandstetter | 3a034e1 | 2020-07-09 22:32:34 | [diff] [blame] | 31 | #include "pc/sctp_data_channel.h" |
| Harald Alvestrand | f0d5caf | 2025-04-07 09:08:51 | [diff] [blame] | 32 | #include "pc/sctp_utils.h" |
| Harald Alvestrand | 5761e7b | 2021-01-29 14:45:08 | [diff] [blame] | 33 | #include "rtc_base/copy_on_write_buffer.h" |
| 34 | #include "rtc_base/ssl_stream_adapter.h" |
| Harald Alvestrand | 5761e7b | 2021-01-29 14:45:08 | [diff] [blame] | 35 | #include "rtc_base/thread.h" |
| 36 | #include "rtc_base/thread_annotations.h" |
| Harald Alvestrand | 246724b | 2019-12-03 21:31:42 | [diff] [blame] | 37 | #include "rtc_base/weak_ptr.h" |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 38 | |
| 39 | namespace webrtc { |
| 40 | |
| Harald Alvestrand | 5b84f38 | 2022-02-08 10:49:09 | [diff] [blame] | 41 | class PeerConnectionInternal; |
| Mirko Bonadei | e0bc8d2 | 2022-02-08 07:41:25 | [diff] [blame] | 42 | |
| Harald Alvestrand | 9e5aeb9 | 2022-05-11 09:35:36 | [diff] [blame] | 43 | class DataChannelController : public SctpDataChannelControllerInterface, |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 44 | public DataChannelSink { |
| 45 | public: |
| Harald Alvestrand | 5b84f38 | 2022-02-08 10:49:09 | [diff] [blame] | 46 | explicit DataChannelController(PeerConnectionInternal* pc) : pc_(pc) {} |
| Harald Alvestrand | 9e5aeb9 | 2022-05-11 09:35:36 | [diff] [blame] | 47 | ~DataChannelController(); |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 48 | |
| Harald Alvestrand | ab81316 | 2020-01-09 12:29:56 | [diff] [blame] | 49 | // Not copyable or movable. |
| 50 | DataChannelController(DataChannelController&) = delete; |
| 51 | DataChannelController& operator=(const DataChannelController& other) = delete; |
| 52 | DataChannelController(DataChannelController&&) = delete; |
| 53 | DataChannelController& operator=(DataChannelController&& other) = delete; |
| 54 | |
| Harald Alvestrand | 7af57c6 | 2021-04-16 11:12:14 | [diff] [blame] | 55 | // Implements |
| Taylor Brandstetter | 3a034e1 | 2020-07-09 22:32:34 | [diff] [blame] | 56 | // SctpDataChannelProviderInterface. |
| Tommi | 1fabbac | 2023-03-21 13:48:51 | [diff] [blame] | 57 | RTCError SendData(StreamId sid, |
| 58 | const SendDataParams& params, |
| Evan Shrubsole | e6a1f70 | 2025-04-15 14:55:42 | [diff] [blame] | 59 | const CopyOnWriteBuffer& payload) override; |
| Florent Castelli | 0012bfa | 2024-07-26 16:16:41 | [diff] [blame] | 60 | void AddSctpDataStream(StreamId sid, PriorityValue priority) override; |
| Tommi | 4c84222 | 2023-03-21 10:35:24 | [diff] [blame] | 61 | void RemoveSctpDataStream(StreamId sid) override; |
| Tommi | d2afbaf | 2023-03-02 09:51:16 | [diff] [blame] | 62 | void OnChannelStateChanged(SctpDataChannel* channel, |
| 63 | DataChannelInterface::DataState state) override; |
| Victor Boivie | fea41f5 | 2024-03-11 15:43:31 | [diff] [blame] | 64 | size_t buffered_amount(StreamId sid) const override; |
| Victor Boivie | cdecc4e | 2024-03-18 12:47:34 | [diff] [blame] | 65 | size_t buffered_amount_low_threshold(StreamId sid) const override; |
| 66 | void SetBufferedAmountLowThreshold(StreamId sid, size_t bytes) override; |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 67 | |
| 68 | // Implements DataChannelSink. |
| 69 | void OnDataReceived(int channel_id, |
| 70 | DataMessageType type, |
| Evan Shrubsole | e6a1f70 | 2025-04-15 14:55:42 | [diff] [blame] | 71 | const CopyOnWriteBuffer& buffer) override; |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 72 | void OnChannelClosing(int channel_id) override; |
| 73 | void OnChannelClosed(int channel_id) override; |
| 74 | void OnReadyToSend() override; |
| Florent Castelli | dcb9ffc | 2021-06-29 12:58:23 | [diff] [blame] | 75 | void OnTransportClosed(RTCError error) override; |
| Victor Boivie | cdecc4e | 2024-03-18 12:47:34 | [diff] [blame] | 76 | void OnBufferedAmountLow(int channel_id) override; |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 77 | |
| Tommi | 1f708ef | 2023-03-31 16:40:50 | [diff] [blame] | 78 | // Called as part of destroying the owning PeerConnection. |
| 79 | void PrepareForShutdown(); |
| 80 | |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 81 | // Called from PeerConnection::SetupDataChannelTransport_n |
| Tommi | aa3c9f2 | 2023-04-18 10:19:19 | [diff] [blame] | 82 | void SetupDataChannelTransport_n(DataChannelTransportInterface* transport); |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 83 | // Called from PeerConnection::TeardownDataChannelTransport_n |
| Tommi | b00d63c | 2023-04-12 17:49:53 | [diff] [blame] | 84 | void TeardownDataChannelTransport_n(RTCError error); |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 85 | |
| 86 | // Called from PeerConnection::OnTransportChanged |
| 87 | // to make required changes to datachannels' transports. |
| 88 | void OnTransportChanged( |
| 89 | DataChannelTransportInterface* data_channel_transport); |
| 90 | |
| Tomas Gunnarsson | 2e94de5 | 2020-06-16 14:54:10 | [diff] [blame] | 91 | // Called from PeerConnection::GetDataChannelStats on the signaling thread. |
| Taylor Brandstetter | 3a034e1 | 2020-07-09 22:32:34 | [diff] [blame] | 92 | std::vector<DataChannelStats> GetDataChannelStats() const; |
| Tomas Gunnarsson | 2e94de5 | 2020-06-16 14:54:10 | [diff] [blame] | 93 | |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 94 | // Creates channel and adds it to the collection of DataChannels that will |
| Taylor Brandstetter | 3a034e1 | 2020-07-09 22:32:34 | [diff] [blame] | 95 | // be offered in a SessionDescription, and wraps it in a proxy object. |
| Evan Shrubsole | e6a1f70 | 2025-04-15 14:55:42 | [diff] [blame] | 96 | RTCErrorOr<scoped_refptr<DataChannelInterface>> |
| Tommi | 4f7ade5 | 2023-03-29 18:46:59 | [diff] [blame] | 97 | InternalCreateDataChannelWithProxy(const std::string& label, |
| 98 | const InternalDataChannelInit& config); |
| Evan Shrubsole | eb835d0 | 2025-03-12 09:41:06 | [diff] [blame] | 99 | void AllocateSctpSids(SSLRole role); |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 100 | |
| Philipp Hancke | 522380f | 2023-05-09 07:41:03 | [diff] [blame] | 101 | // Check if data channels are currently tracked. Used to decide whether a |
| 102 | // rejected m=application section should be reoffered. |
| 103 | bool HasDataChannels() const; |
| Tommi | 77158ac | 2023-03-30 07:05:23 | [diff] [blame] | 104 | |
| Harald Alvestrand | 5da3eb0 | 2023-03-15 20:39:42 | [diff] [blame] | 105 | // At some point in time, a data channel has existed. |
| 106 | bool HasUsedDataChannels() const; |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 107 | |
| Philip Eliasson | 17ddd31 | 2025-04-08 08:33:49 | [diff] [blame] | 108 | void SetEventObserver( |
| 109 | std::unique_ptr<DataChannelEventObserverInterface> observer); |
| 110 | |
| Tommi | 5271965 | 2023-04-04 09:59:55 | [diff] [blame] | 111 | protected: |
| Evan Shrubsole | 6a9a1ae | 2025-03-21 12:54:15 | [diff] [blame] | 112 | Thread* network_thread() const; |
| 113 | Thread* signaling_thread() const; |
| Tommi | 5271965 | 2023-04-04 09:59:55 | [diff] [blame] | 114 | |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 115 | private: |
| Tommi | 44ebe2a | 2023-05-15 13:14:10 | [diff] [blame] | 116 | void OnSctpDataChannelClosed(SctpDataChannel* channel); |
| 117 | |
| Tommi | f9e13f8 | 2023-04-06 19:21:45 | [diff] [blame] | 118 | // Creates a new SctpDataChannel object on the network thread. |
| Evan Shrubsole | e6a1f70 | 2025-04-15 14:55:42 | [diff] [blame] | 119 | RTCErrorOr<scoped_refptr<SctpDataChannel>> CreateDataChannel( |
| Tommi | f9e13f8 | 2023-04-06 19:21:45 | [diff] [blame] | 120 | const std::string& label, |
| 121 | InternalDataChannelInit& config) RTC_RUN_ON(network_thread()); |
| 122 | |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 123 | // Parses and handles open messages. Returns true if the message is an open |
| Tommi | 5bbfb00 | 2023-03-04 15:47:53 | [diff] [blame] | 124 | // message and should be considered to be handled, false otherwise. |
| Tommi | 4e1c957 | 2023-03-15 11:36:20 | [diff] [blame] | 125 | bool HandleOpenMessage_n(int channel_id, |
| 126 | DataMessageType type, |
| Evan Shrubsole | e6a1f70 | 2025-04-15 14:55:42 | [diff] [blame] | 127 | const CopyOnWriteBuffer& buffer) |
| Tommi | 5bbfb00 | 2023-03-04 15:47:53 | [diff] [blame] | 128 | RTC_RUN_ON(network_thread()); |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 129 | // Called when a valid data channel OPEN message is received. |
| Evan Shrubsole | e6a1f70 | 2025-04-15 14:55:42 | [diff] [blame] | 130 | void OnDataChannelOpenMessage(scoped_refptr<SctpDataChannel> channel, |
| Tommi | f9e13f8 | 2023-04-06 19:21:45 | [diff] [blame] | 131 | bool ready_to_send) |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 132 | RTC_RUN_ON(signaling_thread()); |
| 133 | |
| Tommi | 4f7ade5 | 2023-03-29 18:46:59 | [diff] [blame] | 134 | // Accepts a `StreamId` which may be pre-negotiated or unassigned. For |
| 135 | // pre-negotiated sids, attempts to reserve the sid in the allocation pool, |
| 136 | // for unassigned sids attempts to generate a new sid if possible. Returns |
| 137 | // RTCError::OK() if the sid is reserved (and may have been generated) or |
| 138 | // if not enough information exists to generate a sid, in which case the sid |
| 139 | // will still be unassigned upon return, but will be assigned later. |
| 140 | // If the pool has been exhausted or a sid has already been reserved, an |
| 141 | // error will be returned. |
| Florent Castelli | 8037fc6 | 2024-08-29 13:00:40 | [diff] [blame] | 142 | RTCError ReserveOrAllocateSid(std::optional<StreamId>& sid, |
| Evan Shrubsole | eb835d0 | 2025-03-12 09:41:06 | [diff] [blame] | 143 | std::optional<SSLRole> fallback_ssl_role) |
| Tommi | 4f7ade5 | 2023-03-29 18:46:59 | [diff] [blame] | 144 | RTC_RUN_ON(network_thread()); |
| 145 | |
| Tomas Gunnarsson | 2e94de5 | 2020-06-16 14:54:10 | [diff] [blame] | 146 | // Called when all data channels need to be notified of a transport channel |
| 147 | // (calls OnTransportChannelCreated on the signaling thread). |
| 148 | void NotifyDataChannelsOfTransportCreated(); |
| 149 | |
| Tommi | aa3c9f2 | 2023-04-18 10:19:19 | [diff] [blame] | 150 | void set_data_channel_transport(DataChannelTransportInterface* transport); |
| 151 | |
| Philip Eliasson | 17ddd31 | 2025-04-08 08:33:49 | [diff] [blame] | 152 | std::optional<DataChannelEventObserverInterface::Message> |
| 153 | BuildObserverMessage( |
| 154 | StreamId sid, |
| 155 | DataMessageType type, |
| 156 | ArrayView<const uint8_t> payload, |
| 157 | DataChannelEventObserverInterface::Message::Direction direction) const |
| 158 | RTC_RUN_ON(network_thread()); |
| 159 | |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 160 | // Plugin transport used for data channels. Pointer may be accessed and |
| 161 | // checked from any thread, but the object may only be touched on the |
| 162 | // network thread. |
| Tommi | add7ac0 | 2023-04-12 10:01:10 | [diff] [blame] | 163 | DataChannelTransportInterface* data_channel_transport_ |
| 164 | RTC_GUARDED_BY(network_thread()) = nullptr; |
| Tommi | 4f7ade5 | 2023-03-29 18:46:59 | [diff] [blame] | 165 | SctpSidAllocator sid_allocator_ RTC_GUARDED_BY(network_thread()); |
| Evan Shrubsole | e6a1f70 | 2025-04-15 14:55:42 | [diff] [blame] | 166 | std::vector<scoped_refptr<SctpDataChannel>> sctp_data_channels_n_ |
| Tommi | 4f7ade5 | 2023-03-29 18:46:59 | [diff] [blame] | 167 | RTC_GUARDED_BY(network_thread()); |
| Tommi | 44ebe2a | 2023-05-15 13:14:10 | [diff] [blame] | 168 | enum class DataChannelUsage : uint8_t { |
| 169 | kNeverUsed = 0, |
| 170 | kHaveBeenUsed, |
| 171 | kInUse |
| 172 | }; |
| 173 | DataChannelUsage channel_usage_ RTC_GUARDED_BY(signaling_thread()) = |
| 174 | DataChannelUsage::kNeverUsed; |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 175 | |
| Philip Eliasson | 17ddd31 | 2025-04-08 08:33:49 | [diff] [blame] | 176 | std::unique_ptr<DataChannelEventObserverInterface> event_observer_; |
| 177 | |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 178 | // Owning PeerConnection. |
| Harald Alvestrand | 5b84f38 | 2022-02-08 10:49:09 | [diff] [blame] | 179 | PeerConnectionInternal* const pc_; |
| Tommi | f9e13f8 | 2023-04-06 19:21:45 | [diff] [blame] | 180 | // The weak pointers must be dereferenced and invalidated on the network |
| Niels Möller | 236e36c | 2021-03-23 08:23:10 | [diff] [blame] | 181 | // thread only. |
| Evan Shrubsole | d01d07d | 2025-02-25 09:34:57 | [diff] [blame] | 182 | WeakPtrFactory<DataChannelController> weak_factory_ |
| Tommi | f9e13f8 | 2023-04-06 19:21:45 | [diff] [blame] | 183 | RTC_GUARDED_BY(network_thread()){this}; |
| Tommi | 13759ba | 2023-03-06 11:51:39 | [diff] [blame] | 184 | ScopedTaskSafety signaling_safety_; |
| Harald Alvestrand | 05e4d08 | 2019-12-03 13:04:21 | [diff] [blame] | 185 | }; |
| 186 | |
| 187 | } // namespace webrtc |
| 188 | |
| 189 | #endif // PC_DATA_CHANNEL_CONTROLLER_H_ |