blob: e252e8f5e6e6f9f5bc442d65b81d2c5f49791ff5 [file] [log] [blame]
Harald Alvestrand00cf34c2019-12-02 08:56:021/*
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
Harald Alvestrand05e4d082019-12-03 13:04:2111#include "pc/data_channel_controller.h"
12
Florent Castelli0012bfa2024-07-26 16:16:4113#include <cstdint>
Harald Alvestrand05e4d082019-12-03 13:04:2114#include <utility>
Harald Alvestrand00cf34c2019-12-02 08:56:0215
Tommi51edb562023-03-14 08:23:5116#include "absl/algorithm/container.h"
Victor Boiviecd3d29b2024-03-09 20:50:4217#include "absl/types/optional.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0818#include "api/peer_connection_interface.h"
Florent Castelli0012bfa2024-07-26 16:16:4119#include "api/priority.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0820#include "api/rtc_error.h"
Harald Alvestrand5b84f382022-02-08 10:49:0921#include "pc/peer_connection_internal.h"
Harald Alvestrand00cf34c2019-12-02 08:56:0222#include "pc/sctp_utils.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0823#include "rtc_base/logging.h"
Harald Alvestrand00cf34c2019-12-02 08:56:0224
25namespace webrtc {
26
Tommi4f7ade52023-03-29 18:46:5927DataChannelController::~DataChannelController() {
Tommi52719652023-04-04 09:59:5528 RTC_DCHECK(sctp_data_channels_n_.empty())
29 << "Missing call to TeardownDataChannelTransport_n?";
30 RTC_DCHECK(!signaling_safety_.flag()->alive())
31 << "Missing call to PrepareForShutdown?";
Tommi4f7ade52023-03-29 18:46:5932}
Harald Alvestrand9e5aeb92022-05-11 09:35:3633
Philipp Hancke522380f2023-05-09 07:41:0334bool DataChannelController::HasDataChannels() const {
Tommi44ebe2a2023-05-15 13:14:1035 RTC_DCHECK_RUN_ON(signaling_thread());
36 return channel_usage_ == DataChannelUsage::kInUse;
Harald Alvestrand05e4d082019-12-03 13:04:2137}
38
Harald Alvestrand5da3eb02023-03-15 20:39:4239bool DataChannelController::HasUsedDataChannels() const {
40 RTC_DCHECK_RUN_ON(signaling_thread());
Tommi44ebe2a2023-05-15 13:14:1041 return channel_usage_ != DataChannelUsage::kNeverUsed;
Harald Alvestrand5da3eb02023-03-15 20:39:4242}
43
Tommi1fabbac2023-03-21 13:48:5144RTCError DataChannelController::SendData(
45 StreamId sid,
46 const SendDataParams& params,
47 const rtc::CopyOnWriteBuffer& payload) {
Tommiadd7ac02023-04-12 10:01:1048 RTC_DCHECK_RUN_ON(network_thread());
49 if (!data_channel_transport_) {
50 RTC_LOG(LS_ERROR) << "SendData called before transport is ready";
51 return RTCError(RTCErrorType::INVALID_STATE);
52 }
53 return data_channel_transport_->SendData(sid.stream_id_int(), params,
54 payload);
Harald Alvestrand00cf34c2019-12-02 08:56:0255}
56
Florent Castelli0012bfa2024-07-26 16:16:4157void DataChannelController::AddSctpDataStream(StreamId sid,
58 PriorityValue priority) {
Tommi55f72802023-03-27 10:39:3359 RTC_DCHECK_RUN_ON(network_thread());
Tommiadd7ac02023-04-12 10:01:1060 if (data_channel_transport_) {
Florent Castelli0012bfa2024-07-26 16:16:4161 data_channel_transport_->OpenChannel(sid.stream_id_int(), priority);
Harald Alvestrand00cf34c2019-12-02 08:56:0262 }
63}
64
Tommi4c842222023-03-21 10:35:2465void DataChannelController::RemoveSctpDataStream(StreamId sid) {
Tommi55f72802023-03-27 10:39:3366 RTC_DCHECK_RUN_ON(network_thread());
Tommiadd7ac02023-04-12 10:01:1067 if (data_channel_transport_) {
68 data_channel_transport_->CloseChannel(sid.stream_id_int());
Harald Alvestrand00cf34c2019-12-02 08:56:0269 }
70}
71
Tommid2afbaf2023-03-02 09:51:1672void DataChannelController::OnChannelStateChanged(
73 SctpDataChannel* channel,
74 DataChannelInterface::DataState state) {
Tommif9e13f82023-04-06 19:21:4575 RTC_DCHECK_RUN_ON(network_thread());
Tommieec18102023-06-22 08:13:5276
77 // Stash away the internal id here in case `OnSctpDataChannelClosed` ends up
78 // releasing the last reference to the channel.
79 const int channel_id = channel->internal_id();
80
Tommid2afbaf2023-03-02 09:51:1681 if (state == DataChannelInterface::DataState::kClosed)
82 OnSctpDataChannelClosed(channel);
83
Tommi44ebe2a2023-05-15 13:14:1084 DataChannelUsage channel_usage = sctp_data_channels_n_.empty()
85 ? DataChannelUsage::kHaveBeenUsed
86 : DataChannelUsage::kInUse;
87 signaling_thread()->PostTask(SafeTask(
Tommieec18102023-06-22 08:13:5288 signaling_safety_.flag(), [this, channel_id, state, channel_usage] {
Tommi44ebe2a2023-05-15 13:14:1089 RTC_DCHECK_RUN_ON(signaling_thread());
90 channel_usage_ = channel_usage;
91 pc_->OnSctpDataChannelStateChanged(channel_id, state);
92 }));
Tommid2afbaf2023-03-02 09:51:1693}
94
Victor Boiviefea41f52024-03-11 15:43:3195size_t DataChannelController::buffered_amount(StreamId sid) const {
96 RTC_DCHECK_RUN_ON(network_thread());
97 if (!data_channel_transport_) {
98 return 0;
99 }
100 return data_channel_transport_->buffered_amount(sid.stream_id_int());
101}
102
Victor Boiviecdecc4e2024-03-18 12:47:34103size_t DataChannelController::buffered_amount_low_threshold(
104 StreamId sid) const {
105 RTC_DCHECK_RUN_ON(network_thread());
106 if (!data_channel_transport_) {
107 return 0;
108 }
109 return data_channel_transport_->buffered_amount_low_threshold(
110 sid.stream_id_int());
111}
112
113void DataChannelController::SetBufferedAmountLowThreshold(StreamId sid,
114 size_t bytes) {
115 RTC_DCHECK_RUN_ON(network_thread());
116 if (!data_channel_transport_) {
117 return;
118 }
119 data_channel_transport_->SetBufferedAmountLowThreshold(sid.stream_id_int(),
120 bytes);
121}
122
Harald Alvestrand05e4d082019-12-03 13:04:21123void DataChannelController::OnDataReceived(
Harald Alvestrand00cf34c2019-12-02 08:56:02124 int channel_id,
125 DataMessageType type,
126 const rtc::CopyOnWriteBuffer& buffer) {
127 RTC_DCHECK_RUN_ON(network_thread());
Tommi5bbfb002023-03-04 15:47:53128
Tommi4e1c9572023-03-15 11:36:20129 if (HandleOpenMessage_n(channel_id, type, buffer))
Tommi5bbfb002023-03-04 15:47:53130 return;
131
Tommif9e13f82023-04-06 19:21:45132 auto it = absl::c_find_if(sctp_data_channels_n_, [&](const auto& c) {
Victor Boiviecd3d29b2024-03-09 20:50:42133 return c->sid_n().has_value() && c->sid_n()->stream_id_int() == channel_id;
Tommif9e13f82023-04-06 19:21:45134 });
135
136 if (it != sctp_data_channels_n_.end())
137 (*it)->OnDataReceived(type, buffer);
Harald Alvestrand00cf34c2019-12-02 08:56:02138}
139
Harald Alvestrand05e4d082019-12-03 13:04:21140void DataChannelController::OnChannelClosing(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 08:56:02141 RTC_DCHECK_RUN_ON(network_thread());
Tommif9e13f82023-04-06 19:21:45142 auto it = absl::c_find_if(sctp_data_channels_n_, [&](const auto& c) {
Victor Boiviecd3d29b2024-03-09 20:50:42143 return c->sid_n().has_value() && c->sid_n()->stream_id_int() == channel_id;
Tommif9e13f82023-04-06 19:21:45144 });
145
146 if (it != sctp_data_channels_n_.end())
147 (*it)->OnClosingProcedureStartedRemotely();
Harald Alvestrand00cf34c2019-12-02 08:56:02148}
149
Harald Alvestrand05e4d082019-12-03 13:04:21150void DataChannelController::OnChannelClosed(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 08:56:02151 RTC_DCHECK_RUN_ON(network_thread());
Tommi4f7ade52023-03-29 18:46:59152 StreamId sid(channel_id);
153 sid_allocator_.ReleaseSid(sid);
154 auto it = absl::c_find_if(sctp_data_channels_n_,
Tommi1158bde2023-03-30 10:01:56155 [&](const auto& c) { return c->sid_n() == sid; });
Tommi51edb562023-03-14 08:23:51156
Tommif9e13f82023-04-06 19:21:45157 if (it != sctp_data_channels_n_.end()) {
158 rtc::scoped_refptr<SctpDataChannel> channel = std::move(*it);
Tommi4f7ade52023-03-29 18:46:59159 sctp_data_channels_n_.erase(it);
Tommif9e13f82023-04-06 19:21:45160 channel->OnClosingProcedureComplete();
161 }
Harald Alvestrand00cf34c2019-12-02 08:56:02162}
163
Harald Alvestrand05e4d082019-12-03 13:04:21164void DataChannelController::OnReadyToSend() {
Harald Alvestrand00cf34c2019-12-02 08:56:02165 RTC_DCHECK_RUN_ON(network_thread());
Tommif9e13f82023-04-06 19:21:45166 auto copy = sctp_data_channels_n_;
167 for (const auto& channel : copy) {
Victor Boiviecd3d29b2024-03-09 20:50:42168 if (channel->sid_n().has_value()) {
Tommie9aa8672023-03-20 13:43:09169 channel->OnTransportReady();
Tommif9e13f82023-04-06 19:21:45170 } else {
171 // This happens for role==SSL_SERVER channels when we get notified by
172 // the transport *before* the SDP code calls `AllocateSctpSids` to
173 // trigger assignment of sids. In this case OnTransportReady() will be
174 // called from within `AllocateSctpSids` below.
175 RTC_LOG(LS_INFO) << "OnReadyToSend: Still waiting for an id for channel.";
176 }
177 }
Harald Alvestrand00cf34c2019-12-02 08:56:02178}
179
Florent Castellidcb9ffc2021-06-29 12:58:23180void DataChannelController::OnTransportClosed(RTCError error) {
Harald Alvestrand2697ac12019-12-16 09:37:04181 RTC_DCHECK_RUN_ON(network_thread());
Tommib00d63c2023-04-12 17:49:53182
Tommif9e13f82023-04-06 19:21:45183 // This loop will close all data channels and trigger a callback to
Tommib00d63c2023-04-12 17:49:53184 // `OnSctpDataChannelClosed`. We'll empty `sctp_data_channels_n_`, first
185 // and `OnSctpDataChannelClosed` will become a noop but we'll release the
186 // StreamId here.
187 std::vector<rtc::scoped_refptr<SctpDataChannel>> temp_sctp_dcs;
188 temp_sctp_dcs.swap(sctp_data_channels_n_);
189 for (const auto& channel : temp_sctp_dcs) {
Tommif9e13f82023-04-06 19:21:45190 channel->OnTransportChannelClosed(error);
Victor Boiviecd3d29b2024-03-09 20:50:42191 if (channel->sid_n().has_value()) {
192 sid_allocator_.ReleaseSid(*channel->sid_n());
193 }
Tommib00d63c2023-04-12 17:49:53194 }
Harald Alvestrand2697ac12019-12-16 09:37:04195}
196
Victor Boiviecdecc4e2024-03-18 12:47:34197void DataChannelController::OnBufferedAmountLow(int channel_id) {
198 RTC_DCHECK_RUN_ON(network_thread());
199 auto it = absl::c_find_if(sctp_data_channels_n_, [&](const auto& c) {
200 return c->sid_n().has_value() && c->sid_n()->stream_id_int() == channel_id;
201 });
202
203 if (it != sctp_data_channels_n_.end())
204 (*it)->OnBufferedAmountLow();
205}
206
Tommiaa3c9f22023-04-18 10:19:19207void DataChannelController::SetupDataChannelTransport_n(
208 DataChannelTransportInterface* transport) {
Harald Alvestrand00cf34c2019-12-02 08:56:02209 RTC_DCHECK_RUN_ON(network_thread());
Tommiaa3c9f22023-04-18 10:19:19210 RTC_DCHECK(transport);
211 set_data_channel_transport(transport);
Harald Alvestrand00cf34c2019-12-02 08:56:02212}
213
Tommi1f708ef2023-03-31 16:40:50214void DataChannelController::PrepareForShutdown() {
215 RTC_DCHECK_RUN_ON(signaling_thread());
Tommi52719652023-04-04 09:59:55216 signaling_safety_.reset(PendingTaskSafetyFlag::CreateDetachedInactive());
Tommi44ebe2a2023-05-15 13:14:10217 if (channel_usage_ != DataChannelUsage::kNeverUsed)
218 channel_usage_ = DataChannelUsage::kHaveBeenUsed;
Tommi1f708ef2023-03-31 16:40:50219}
220
Tommib00d63c2023-04-12 17:49:53221void DataChannelController::TeardownDataChannelTransport_n(RTCError error) {
Harald Alvestrand00cf34c2019-12-02 08:56:02222 RTC_DCHECK_RUN_ON(network_thread());
Mirko Bonadei29831352023-04-14 17:03:47223 OnTransportClosed(error);
Tommiaa3c9f22023-04-18 10:19:19224 set_data_channel_transport(nullptr);
Tommib00d63c2023-04-12 17:49:53225 RTC_DCHECK(sctp_data_channels_n_.empty());
Tommif9e13f82023-04-06 19:21:45226 weak_factory_.InvalidateWeakPtrs();
Harald Alvestrand00cf34c2019-12-02 08:56:02227}
228
Harald Alvestrand05e4d082019-12-03 13:04:21229void DataChannelController::OnTransportChanged(
Harald Alvestrand00cf34c2019-12-02 08:56:02230 DataChannelTransportInterface* new_data_channel_transport) {
231 RTC_DCHECK_RUN_ON(network_thread());
Tommiadd7ac02023-04-12 10:01:10232 if (data_channel_transport_ &&
233 data_channel_transport_ != new_data_channel_transport) {
Artem Titov880fa812021-07-30 20:30:23234 // Changed which data channel transport is used for `sctp_mid_` (eg. now
Harald Alvestrand00cf34c2019-12-02 08:56:02235 // it's bundled).
Harald Alvestrand00cf34c2019-12-02 08:56:02236 set_data_channel_transport(new_data_channel_transport);
Harald Alvestrand00cf34c2019-12-02 08:56:02237 }
238}
239
Taylor Brandstetter3a034e12020-07-09 22:32:34240std::vector<DataChannelStats> DataChannelController::GetDataChannelStats()
Tomas Gunnarsson2e94de52020-06-16 14:54:10241 const {
Tommif9e13f82023-04-06 19:21:45242 RTC_DCHECK_RUN_ON(network_thread());
Taylor Brandstetter3a034e12020-07-09 22:32:34243 std::vector<DataChannelStats> stats;
Tommif9e13f82023-04-06 19:21:45244 stats.reserve(sctp_data_channels_n_.size());
245 for (const auto& channel : sctp_data_channels_n_)
Tomas Gunnarsson2e94de52020-06-16 14:54:10246 stats.push_back(channel->GetStats());
247 return stats;
248}
249
Tommi5bbfb002023-03-04 15:47:53250bool DataChannelController::HandleOpenMessage_n(
Tommi4e1c9572023-03-15 11:36:20251 int channel_id,
252 DataMessageType type,
Harald Alvestrand00cf34c2019-12-02 08:56:02253 const rtc::CopyOnWriteBuffer& buffer) {
Tommi4e1c9572023-03-15 11:36:20254 if (type != DataMessageType::kControl || !IsOpenMessage(buffer))
Tommi5bbfb002023-03-04 15:47:53255 return false;
256
257 // Received OPEN message; parse and signal that a new data channel should
258 // be created.
259 std::string label;
260 InternalDataChannelInit config;
Tommi4e1c9572023-03-15 11:36:20261 config.id = channel_id;
Tommi5bbfb002023-03-04 15:47:53262 if (!ParseDataChannelOpenMessage(buffer, &label, &config)) {
263 RTC_LOG(LS_WARNING) << "Failed to parse the OPEN message for sid "
Tommi4e1c9572023-03-15 11:36:20264 << channel_id;
Tommi5bbfb002023-03-04 15:47:53265 } else {
Harald Alvestrand00cf34c2019-12-02 08:56:02266 config.open_handshake_role = InternalDataChannelInit::kAcker;
Tommif9e13f82023-04-06 19:21:45267 auto channel_or_error = CreateDataChannel(label, config);
268 if (channel_or_error.ok()) {
269 signaling_thread()->PostTask(SafeTask(
270 signaling_safety_.flag(),
271 [this, channel = channel_or_error.MoveValue(),
272 ready_to_send = data_channel_transport_->IsReadyToSend()] {
273 RTC_DCHECK_RUN_ON(signaling_thread());
274 OnDataChannelOpenMessage(std::move(channel), ready_to_send);
275 }));
276 } else {
277 RTC_LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."
278 << ToString(channel_or_error.error().type());
279 }
Harald Alvestrand00cf34c2019-12-02 08:56:02280 }
Tommi5bbfb002023-03-04 15:47:53281 return true;
Harald Alvestrand00cf34c2019-12-02 08:56:02282}
283
Harald Alvestrand05e4d082019-12-03 13:04:21284void DataChannelController::OnDataChannelOpenMessage(
Tommif9e13f82023-04-06 19:21:45285 rtc::scoped_refptr<SctpDataChannel> channel,
286 bool ready_to_send) {
Tommi44ebe2a2023-05-15 13:14:10287 channel_usage_ = DataChannelUsage::kInUse;
Tommif9e13f82023-04-06 19:21:45288 auto proxy = SctpDataChannel::CreateProxy(channel, signaling_safety_.flag());
Andrey Logvin7f16fcd2023-04-05 08:53:13289
Tommif9e13f82023-04-06 19:21:45290 pc_->Observer()->OnDataChannel(proxy);
Andrey Logvin7f16fcd2023-04-05 08:53:13291 pc_->NoteDataAddedEvent();
Tommif9e13f82023-04-06 19:21:45292
293 if (ready_to_send) {
294 network_thread()->PostTask([channel = std::move(channel)] {
295 if (channel->state() != DataChannelInterface::DataState::kClosed)
296 channel->OnTransportReady();
297 });
298 }
Harald Alvestrand00cf34c2019-12-02 08:56:02299}
300
Tommi4f7ade52023-03-29 18:46:59301// RTC_RUN_ON(network_thread())
302RTCError DataChannelController::ReserveOrAllocateSid(
Victor Boiviecd3d29b2024-03-09 20:50:42303 absl::optional<StreamId>& sid,
Tommi4f7ade52023-03-29 18:46:59304 absl::optional<rtc::SSLRole> fallback_ssl_role) {
Victor Boiviecd3d29b2024-03-09 20:50:42305 if (sid.has_value()) {
306 return sid_allocator_.ReserveSid(*sid)
Tommi4f7ade52023-03-29 18:46:59307 ? RTCError::OK()
Victor Boiviecd3d29b2024-03-09 20:50:42308 : RTCError(RTCErrorType::INVALID_RANGE, "StreamId reserved.");
Tommi4f7ade52023-03-29 18:46:59309 }
310
311 // Attempt to allocate an ID based on the negotiated role.
312 absl::optional<rtc::SSLRole> role = pc_->GetSctpSslRole_n();
313 if (!role)
314 role = fallback_ssl_role;
315 if (role) {
316 sid = sid_allocator_.AllocateSid(*role);
Victor Boiviecd3d29b2024-03-09 20:50:42317 if (!sid.has_value())
Tommi4f7ade52023-03-29 18:46:59318 return RTCError(RTCErrorType::RESOURCE_EXHAUSTED);
319 }
320 // When we get here, we may still not have an ID, but that's a supported case
321 // whereby an id will be assigned later.
Victor Boiviecd3d29b2024-03-09 20:50:42322 RTC_DCHECK(sid.has_value() || !role);
Tommi4f7ade52023-03-29 18:46:59323 return RTCError::OK();
324}
325
Tommif9e13f82023-04-06 19:21:45326// RTC_RUN_ON(network_thread())
327RTCErrorOr<rtc::scoped_refptr<SctpDataChannel>>
328DataChannelController::CreateDataChannel(const std::string& label,
329 InternalDataChannelInit& config) {
Victor Boiviecd3d29b2024-03-09 20:50:42330 absl::optional<StreamId> sid = absl::nullopt;
331 if (config.id != -1) {
332 if (config.id < 0 || config.id > cricket::kMaxSctpSid) {
333 return RTCError(RTCErrorType::INVALID_RANGE, "StreamId out of range.");
334 }
335 sid = StreamId(config.id);
336 }
337
Tommif9e13f82023-04-06 19:21:45338 RTCError err = ReserveOrAllocateSid(sid, config.fallback_ssl_role);
339 if (!err.ok())
340 return err;
341
342 // In case `sid` has changed. Update `config` accordingly.
Victor Boiviecd3d29b2024-03-09 20:50:42343 if (sid.has_value()) {
344 config.id = sid->stream_id_int();
345 }
Tommif9e13f82023-04-06 19:21:45346
347 rtc::scoped_refptr<SctpDataChannel> channel = SctpDataChannel::Create(
348 weak_factory_.GetWeakPtr(), label, data_channel_transport_ != nullptr,
349 config, signaling_thread(), network_thread());
350 RTC_DCHECK(channel);
351 sctp_data_channels_n_.push_back(channel);
352
353 // If we have an id already, notify the transport.
Victor Boiviecd3d29b2024-03-09 20:50:42354 if (sid.has_value())
Florent Castelli0012bfa2024-07-26 16:16:41355 AddSctpDataStream(*sid,
356 config.priority.value_or(PriorityValue(Priority::kLow)));
Tommif9e13f82023-04-06 19:21:45357
358 return channel;
359}
360
Tommi4f7ade52023-03-29 18:46:59361RTCErrorOr<rtc::scoped_refptr<DataChannelInterface>>
Taylor Brandstetter3a034e12020-07-09 22:32:34362DataChannelController::InternalCreateDataChannelWithProxy(
Harald Alvestrand00cf34c2019-12-02 08:56:02363 const std::string& label,
Tommi335d0842023-03-25 09:56:18364 const InternalDataChannelInit& config) {
Harald Alvestrand05e4d082019-12-03 13:04:21365 RTC_DCHECK_RUN_ON(signaling_thread());
Tommi4f7ade52023-03-29 18:46:59366 RTC_DCHECK(!pc_->IsClosed());
Tommi335d0842023-03-25 09:56:18367 if (!config.IsValid()) {
Tommi4f7ade52023-03-29 18:46:59368 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
369 "Invalid DataChannelInit");
Tommi9296a162023-03-21 15:28:52370 }
371
Tommi4f7ade52023-03-29 18:46:59372 bool ready_to_send = false;
Tommi335d0842023-03-25 09:56:18373 InternalDataChannelInit new_config = config;
Tommi4f7ade52023-03-29 18:46:59374 auto ret = network_thread()->BlockingCall(
375 [&]() -> RTCErrorOr<rtc::scoped_refptr<SctpDataChannel>> {
376 RTC_DCHECK_RUN_ON(network_thread());
Tommif9e13f82023-04-06 19:21:45377 auto channel = CreateDataChannel(label, new_config);
378 if (!channel.ok())
379 return channel;
Tommi4f7ade52023-03-29 18:46:59380 ready_to_send =
381 data_channel_transport_ && data_channel_transport_->IsReadyToSend();
Tommif9e13f82023-04-06 19:21:45382 if (ready_to_send) {
383 // If the transport is ready to send because the initial channel
384 // ready signal may have been sent before the DataChannel creation.
385 // This has to be done async because the upper layer objects (e.g.
386 // Chrome glue and WebKit) are not wired up properly until after
387 // `InternalCreateDataChannelWithProxy` returns.
388 network_thread()->PostTask([channel = channel.value()] {
389 if (channel->state() != DataChannelInterface::DataState::kClosed)
390 channel->OnTransportReady();
391 });
392 }
Tommi4f7ade52023-03-29 18:46:59393
394 return channel;
395 });
396
397 if (!ret.ok())
398 return ret.MoveError();
399
Tommi44ebe2a2023-05-15 13:14:10400 channel_usage_ = DataChannelUsage::kInUse;
Tommif9e13f82023-04-06 19:21:45401 return SctpDataChannel::CreateProxy(ret.MoveValue(),
402 signaling_safety_.flag());
Harald Alvestrand00cf34c2019-12-02 08:56:02403}
404
Harald Alvestrand05e4d082019-12-03 13:04:21405void DataChannelController::AllocateSctpSids(rtc::SSLRole role) {
Tommif9e13f82023-04-06 19:21:45406 RTC_DCHECK_RUN_ON(network_thread());
407
408 const bool ready_to_send =
409 data_channel_transport_ && data_channel_transport_->IsReadyToSend();
Tommi4f7ade52023-03-29 18:46:59410
411 std::vector<std::pair<SctpDataChannel*, StreamId>> channels_to_update;
Taylor Brandstetter3a034e12020-07-09 22:32:34412 std::vector<rtc::scoped_refptr<SctpDataChannel>> channels_to_close;
Tommif9e13f82023-04-06 19:21:45413 for (auto it = sctp_data_channels_n_.begin();
414 it != sctp_data_channels_n_.end();) {
Victor Boiviecd3d29b2024-03-09 20:50:42415 if (!(*it)->sid_n().has_value()) {
416 absl::optional<StreamId> sid = sid_allocator_.AllocateSid(role);
417 if (sid.has_value()) {
418 (*it)->SetSctpSid_n(*sid);
Florent Castelli0012bfa2024-07-26 16:16:41419 AddSctpDataStream(*sid, (*it)->priority());
Tommif9e13f82023-04-06 19:21:45420 if (ready_to_send) {
421 RTC_LOG(LS_INFO) << "AllocateSctpSids: Id assigned, ready to send.";
422 (*it)->OnTransportReady();
Tommi4f7ade52023-03-29 18:46:59423 }
Victor Boiviecd3d29b2024-03-09 20:50:42424 channels_to_update.push_back(std::make_pair((*it).get(), *sid));
Tommif9e13f82023-04-06 19:21:45425 } else {
426 channels_to_close.push_back(std::move(*it));
427 it = sctp_data_channels_n_.erase(it);
428 continue;
Harald Alvestrand00cf34c2019-12-02 08:56:02429 }
Harald Alvestrand00cf34c2019-12-02 08:56:02430 }
Tommif9e13f82023-04-06 19:21:45431 ++it;
432 }
Tommi4f7ade52023-03-29 18:46:59433
Harald Alvestrand00cf34c2019-12-02 08:56:02434 // Since closing modifies the list of channels, we have to do the actual
435 // closing outside the loop.
436 for (const auto& channel : channels_to_close) {
Harald Alvestranddfbfb462019-12-08 04:55:43437 channel->CloseAbruptlyWithDataChannelFailure("Failed to allocate SCTP SID");
Harald Alvestrand00cf34c2019-12-02 08:56:02438 }
439}
440
Taylor Brandstetter3a034e12020-07-09 22:32:34441void DataChannelController::OnSctpDataChannelClosed(SctpDataChannel* channel) {
Tommif9e13f82023-04-06 19:21:45442 RTC_DCHECK_RUN_ON(network_thread());
443 // After the closing procedure is done, it's safe to use this ID for
444 // another data channel.
Victor Boiviecd3d29b2024-03-09 20:50:42445 if (channel->sid_n().has_value()) {
446 sid_allocator_.ReleaseSid(*channel->sid_n());
Harald Alvestrand00cf34c2019-12-02 08:56:02447 }
Tommif9e13f82023-04-06 19:21:45448 auto it = absl::c_find_if(sctp_data_channels_n_,
449 [&](const auto& c) { return c.get() == channel; });
450 if (it != sctp_data_channels_n_.end())
451 sctp_data_channels_n_.erase(it);
Harald Alvestrand00cf34c2019-12-02 08:56:02452}
453
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:42454void DataChannelController::set_data_channel_transport(
455 DataChannelTransportInterface* transport) {
456 RTC_DCHECK_RUN_ON(network_thread());
Tommiaa3c9f22023-04-18 10:19:19457
458 if (data_channel_transport_)
459 data_channel_transport_->SetDataSink(nullptr);
460
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:42461 data_channel_transport_ = transport;
Tommiaa3c9f22023-04-18 10:19:19462
463 if (data_channel_transport_) {
464 // There's a new data channel transport. This needs to be signaled to the
465 // `sctp_data_channels_n_` so that they can reopen and reconnect. This is
466 // necessary when bundling is applied.
467 NotifyDataChannelsOfTransportCreated();
468 data_channel_transport_->SetDataSink(this);
469 }
Tomas Gunnarsson7d3cfbf2020-06-15 11:47:42470}
471
Tomas Gunnarsson2e94de52020-06-16 14:54:10472void DataChannelController::NotifyDataChannelsOfTransportCreated() {
473 RTC_DCHECK_RUN_ON(network_thread());
Tommiadd7ac02023-04-12 10:01:10474 RTC_DCHECK(data_channel_transport_);
Tommi4f7ade52023-03-29 18:46:59475
Tommi1158bde2023-03-30 10:01:56476 for (const auto& channel : sctp_data_channels_n_) {
Victor Boiviecd3d29b2024-03-09 20:50:42477 if (channel->sid_n().has_value())
Florent Castelli0012bfa2024-07-26 16:16:41478 AddSctpDataStream(*channel->sid_n(), channel->priority());
Tommif9e13f82023-04-06 19:21:45479 channel->OnTransportChannelCreated();
Tommi1158bde2023-03-30 10:01:56480 }
Tommidc90a9c2023-03-20 09:26:19481}
482
Harald Alvestrand05e4d082019-12-03 13:04:21483rtc::Thread* DataChannelController::network_thread() const {
484 return pc_->network_thread();
485}
Tommif9e13f82023-04-06 19:21:45486
Harald Alvestrand05e4d082019-12-03 13:04:21487rtc::Thread* DataChannelController::signaling_thread() const {
488 return pc_->signaling_thread();
489}
490
Harald Alvestrand00cf34c2019-12-02 08:56:02491} // namespace webrtc