blob: b655b530a5620e44904efac47bc6ce974c1ec918 [file] [log] [blame]
Harald Alvestrand00cf34c2019-12-02 09:56:02 +01001/*
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 14:04:21 +010011#include "pc/data_channel_controller.h"
12
13#include <utility>
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010014
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000015#include "api/peer_connection_interface.h"
16#include "api/rtc_error.h"
Harald Alvestrand5b84f382022-02-08 10:49:09 +000017#include "pc/peer_connection_internal.h"
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010018#include "pc/sctp_utils.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000019#include "rtc_base/location.h"
20#include "rtc_base/logging.h"
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010021
22namespace webrtc {
23
Harald Alvestrand9e5aeb92022-05-11 09:35:36 +000024DataChannelController::~DataChannelController() {
25 // Since channels may have multiple owners, we cannot guarantee that
26 // they will be deallocated before destroying the controller.
27 // Therefore, detach them from the controller.
28 for (auto channel : sctp_data_channels_) {
29 channel->DetachFromController();
30 }
31}
32
Harald Alvestrand05e4d082019-12-03 14:04:21 +010033bool DataChannelController::HasDataChannels() const {
34 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +000035 return !sctp_data_channels_.empty();
Harald Alvestrand05e4d082019-12-03 14:04:21 +010036}
37
Florent Castellid95b1492021-05-10 11:29:56 +020038bool DataChannelController::SendData(int sid,
39 const SendDataParams& params,
Harald Alvestrand05e4d082019-12-03 14:04:21 +010040 const rtc::CopyOnWriteBuffer& payload,
41 cricket::SendDataResult* result) {
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +020042 if (data_channel_transport())
Florent Castellid95b1492021-05-10 11:29:56 +020043 return DataChannelSendData(sid, params, payload, result);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010044 RTC_LOG(LS_ERROR) << "SendData called before transport is ready";
45 return false;
46}
47
Harald Alvestrand05e4d082019-12-03 14:04:21 +010048bool DataChannelController::ConnectDataChannel(
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070049 SctpDataChannel* webrtc_data_channel) {
50 RTC_DCHECK_RUN_ON(signaling_thread());
51 if (!data_channel_transport()) {
52 // Don't log an error here, because DataChannels are expected to call
53 // ConnectDataChannel in this state. It's the only way to initially tell
54 // whether or not the underlying transport is ready.
55 return false;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010056 }
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +000057 SignalDataChannelTransportWritable_s.connect(
58 webrtc_data_channel, &SctpDataChannel::OnTransportReady);
59 SignalDataChannelTransportReceivedData_s.connect(
60 webrtc_data_channel, &SctpDataChannel::OnDataReceived);
61 SignalDataChannelTransportChannelClosing_s.connect(
62 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureStartedRemotely);
63 SignalDataChannelTransportChannelClosed_s.connect(
64 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureComplete);
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070065 return true;
66}
67
68void DataChannelController::DisconnectDataChannel(
69 SctpDataChannel* webrtc_data_channel) {
70 RTC_DCHECK_RUN_ON(signaling_thread());
71 if (!data_channel_transport()) {
72 RTC_LOG(LS_ERROR)
73 << "DisconnectDataChannel called when sctp_transport_ is NULL.";
74 return;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010075 }
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +000076 SignalDataChannelTransportWritable_s.disconnect(webrtc_data_channel);
77 SignalDataChannelTransportReceivedData_s.disconnect(webrtc_data_channel);
78 SignalDataChannelTransportChannelClosing_s.disconnect(webrtc_data_channel);
79 SignalDataChannelTransportChannelClosed_s.disconnect(webrtc_data_channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010080}
81
Harald Alvestrand05e4d082019-12-03 14:04:21 +010082void DataChannelController::AddSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010083 if (data_channel_transport()) {
84 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
85 if (data_channel_transport()) {
86 data_channel_transport()->OpenChannel(sid);
87 }
88 });
89 }
90}
91
Harald Alvestrand05e4d082019-12-03 14:04:21 +010092void DataChannelController::RemoveSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010093 if (data_channel_transport()) {
94 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
95 if (data_channel_transport()) {
96 data_channel_transport()->CloseChannel(sid);
97 }
98 });
99 }
100}
101
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100102bool DataChannelController::ReadyToSendData() const {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100103 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000104 return (data_channel_transport() && data_channel_transport_ready_to_send_);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100105}
106
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100107void DataChannelController::OnDataReceived(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100108 int channel_id,
109 DataMessageType type,
110 const rtc::CopyOnWriteBuffer& buffer) {
111 RTC_DCHECK_RUN_ON(network_thread());
112 cricket::ReceiveDataParams params;
113 params.sid = channel_id;
Florent Castellid95b1492021-05-10 11:29:56 +0200114 params.type = type;
Niels Möller236e36c2021-03-23 09:23:10 +0100115 signaling_thread()->PostTask(
Danil Chapovalova30439b2022-07-07 10:08:49 +0200116 [self = weak_factory_.GetWeakPtr(), params, buffer] {
Niels Möller236e36c2021-03-23 09:23:10 +0100117 if (self) {
118 RTC_DCHECK_RUN_ON(self->signaling_thread());
119 // TODO(bugs.webrtc.org/11547): The data being received should be
120 // delivered on the network thread. The way HandleOpenMessage_s works
121 // right now is that it's called for all types of buffers and operates
122 // as a selector function. Change this so that it's only called for
123 // buffers that it should be able to handle. Once we do that, we can
124 // deliver all other buffers on the network thread (change
125 // SignalDataChannelTransportReceivedData_s to
126 // SignalDataChannelTransportReceivedData_n).
127 if (!self->HandleOpenMessage_s(params, buffer)) {
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000128 self->SignalDataChannelTransportReceivedData_s(params, buffer);
Niels Möller236e36c2021-03-23 09:23:10 +0100129 }
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100130 }
Danil Chapovalova30439b2022-07-07 10:08:49 +0200131 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100132}
133
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100134void DataChannelController::OnChannelClosing(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100135 RTC_DCHECK_RUN_ON(network_thread());
Danil Chapovalova30439b2022-07-07 10:08:49 +0200136 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr(), channel_id] {
137 if (self) {
138 RTC_DCHECK_RUN_ON(self->signaling_thread());
139 self->SignalDataChannelTransportChannelClosing_s(channel_id);
140 }
141 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100142}
143
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100144void DataChannelController::OnChannelClosed(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100145 RTC_DCHECK_RUN_ON(network_thread());
Danil Chapovalova30439b2022-07-07 10:08:49 +0200146 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr(), channel_id] {
147 if (self) {
148 RTC_DCHECK_RUN_ON(self->signaling_thread());
149 self->SignalDataChannelTransportChannelClosed_s(channel_id);
150 }
151 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100152}
153
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100154void DataChannelController::OnReadyToSend() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100155 RTC_DCHECK_RUN_ON(network_thread());
Danil Chapovalova30439b2022-07-07 10:08:49 +0200156 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr()] {
157 if (self) {
158 RTC_DCHECK_RUN_ON(self->signaling_thread());
159 self->data_channel_transport_ready_to_send_ = true;
160 self->SignalDataChannelTransportWritable_s(
161 self->data_channel_transport_ready_to_send_);
162 }
163 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100164}
165
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200166void DataChannelController::OnTransportClosed(RTCError error) {
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100167 RTC_DCHECK_RUN_ON(network_thread());
Danil Chapovalova30439b2022-07-07 10:08:49 +0200168 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr(), error] {
169 if (self) {
170 RTC_DCHECK_RUN_ON(self->signaling_thread());
171 self->OnTransportChannelClosed(error);
172 }
173 });
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100174}
175
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100176void DataChannelController::SetupDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100177 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200178
179 // There's a new data channel transport. This needs to be signaled to the
Artem Titov880fa812021-07-30 22:30:23 +0200180 // `sctp_data_channels_` so that they can reopen and reconnect. This is
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200181 // necessary when bundling is applied.
182 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100183}
184
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100185void DataChannelController::TeardownDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100186 RTC_DCHECK_RUN_ON(network_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100187 if (data_channel_transport()) {
188 data_channel_transport()->SetDataSink(nullptr);
189 }
190 set_data_channel_transport(nullptr);
191}
192
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100193void DataChannelController::OnTransportChanged(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100194 DataChannelTransportInterface* new_data_channel_transport) {
195 RTC_DCHECK_RUN_ON(network_thread());
196 if (data_channel_transport() &&
197 data_channel_transport() != new_data_channel_transport) {
Artem Titov880fa812021-07-30 22:30:23 +0200198 // Changed which data channel transport is used for `sctp_mid_` (eg. now
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100199 // it's bundled).
200 data_channel_transport()->SetDataSink(nullptr);
201 set_data_channel_transport(new_data_channel_transport);
202 if (new_data_channel_transport) {
203 new_data_channel_transport->SetDataSink(this);
204
205 // There's a new data channel transport. This needs to be signaled to the
Artem Titov880fa812021-07-30 22:30:23 +0200206 // `sctp_data_channels_` so that they can reopen and reconnect. This is
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100207 // necessary when bundling is applied.
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200208 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100209 }
210 }
211}
212
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700213std::vector<DataChannelStats> DataChannelController::GetDataChannelStats()
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200214 const {
215 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700216 std::vector<DataChannelStats> stats;
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200217 stats.reserve(sctp_data_channels_.size());
218 for (const auto& channel : sctp_data_channels_)
219 stats.push_back(channel->GetStats());
220 return stats;
221}
222
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100223bool DataChannelController::HandleOpenMessage_s(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100224 const cricket::ReceiveDataParams& params,
225 const rtc::CopyOnWriteBuffer& buffer) {
Florent Castellid95b1492021-05-10 11:29:56 +0200226 if (params.type == DataMessageType::kControl && IsOpenMessage(buffer)) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100227 // Received OPEN message; parse and signal that a new data channel should
228 // be created.
229 std::string label;
230 InternalDataChannelInit config;
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000231 config.id = params.sid;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100232 if (!ParseDataChannelOpenMessage(buffer, &label, &config)) {
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000233 RTC_LOG(LS_WARNING) << "Failed to parse the OPEN message for sid "
234 << params.sid;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100235 return true;
236 }
237 config.open_handshake_role = InternalDataChannelInit::kAcker;
238 OnDataChannelOpenMessage(label, config);
239 return true;
240 }
241 return false;
242}
243
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100244void DataChannelController::OnDataChannelOpenMessage(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100245 const std::string& label,
246 const InternalDataChannelInit& config) {
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700247 rtc::scoped_refptr<DataChannelInterface> channel(
248 InternalCreateDataChannelWithProxy(label, &config));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100249 if (!channel.get()) {
250 RTC_LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
251 return;
252 }
253
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700254 pc_->Observer()->OnDataChannel(std::move(channel));
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100255 pc_->NoteDataAddedEvent();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100256}
257
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700258rtc::scoped_refptr<DataChannelInterface>
259DataChannelController::InternalCreateDataChannelWithProxy(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100260 const std::string& label,
261 const InternalDataChannelInit* config) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100262 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100263 if (pc_->IsClosed()) {
264 return nullptr;
265 }
Florent Castelli516e2842021-04-19 15:29:50 +0200266
267 rtc::scoped_refptr<SctpDataChannel> channel =
268 InternalCreateSctpDataChannel(label, config);
269 if (channel) {
270 return SctpDataChannel::CreateProxy(channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100271 }
272
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700273 return nullptr;
274}
275
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700276rtc::scoped_refptr<SctpDataChannel>
277DataChannelController::InternalCreateSctpDataChannel(
278 const std::string& label,
279 const InternalDataChannelInit* config) {
280 RTC_DCHECK_RUN_ON(signaling_thread());
281 InternalDataChannelInit new_config =
282 config ? (*config) : InternalDataChannelInit();
283 if (new_config.id < 0) {
284 rtc::SSLRole role;
285 if ((pc_->GetSctpSslRole(&role)) &&
286 !sid_allocator_.AllocateSid(role, &new_config.id)) {
287 RTC_LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
288 return nullptr;
289 }
290 } else if (!sid_allocator_.ReserveSid(new_config.id)) {
291 RTC_LOG(LS_ERROR) << "Failed to create a SCTP data channel "
292 "because the id is already in use or out of range.";
293 return nullptr;
294 }
295 rtc::scoped_refptr<SctpDataChannel> channel(SctpDataChannel::Create(
296 this, label, new_config, signaling_thread(), network_thread()));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100297 if (!channel) {
298 sid_allocator_.ReleaseSid(new_config.id);
299 return nullptr;
300 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700301 sctp_data_channels_.push_back(channel);
Harald Alvestrand5b84f382022-02-08 10:49:09 +0000302 channel->SignalClosed.connect(
303 pc_, &PeerConnectionInternal::OnSctpDataChannelClosed);
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000304 SignalSctpDataChannelCreated_(channel.get());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100305 return channel;
306}
307
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100308void DataChannelController::AllocateSctpSids(rtc::SSLRole role) {
309 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700310 std::vector<rtc::scoped_refptr<SctpDataChannel>> channels_to_close;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100311 for (const auto& channel : sctp_data_channels_) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100312 if (channel->id() < 0) {
313 int sid;
314 if (!sid_allocator_.AllocateSid(role, &sid)) {
315 RTC_LOG(LS_ERROR) << "Failed to allocate SCTP sid, closing channel.";
316 channels_to_close.push_back(channel);
317 continue;
318 }
319 channel->SetSctpSid(sid);
320 }
321 }
322 // Since closing modifies the list of channels, we have to do the actual
323 // closing outside the loop.
324 for (const auto& channel : channels_to_close) {
Harald Alvestranddfbfb462019-12-08 05:55:43 +0100325 channel->CloseAbruptlyWithDataChannelFailure("Failed to allocate SCTP SID");
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100326 }
327}
328
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700329void DataChannelController::OnSctpDataChannelClosed(SctpDataChannel* channel) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100330 RTC_DCHECK_RUN_ON(signaling_thread());
331 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end();
332 ++it) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100333 if (it->get() == channel) {
334 if (channel->id() >= 0) {
335 // After the closing procedure is done, it's safe to use this ID for
336 // another data channel.
337 sid_allocator_.ReleaseSid(channel->id());
338 }
339 // Since this method is triggered by a signal from the DataChannel,
340 // we can't free it directly here; we need to free it asynchronously.
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100341 sctp_data_channels_to_free_.push_back(*it);
342 sctp_data_channels_.erase(it);
Danil Chapovalova30439b2022-07-07 10:08:49 +0200343 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr()] {
344 if (self) {
345 RTC_DCHECK_RUN_ON(self->signaling_thread());
346 self->sctp_data_channels_to_free_.clear();
347 }
348 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100349 return;
350 }
351 }
352}
353
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200354void DataChannelController::OnTransportChannelClosed(RTCError error) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100355 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000356 // Use a temporary copy of the SCTP DataChannel list because the
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100357 // DataChannel may callback to us and try to modify the list.
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700358 std::vector<rtc::scoped_refptr<SctpDataChannel>> temp_sctp_dcs;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100359 temp_sctp_dcs.swap(sctp_data_channels_);
360 for (const auto& channel : temp_sctp_dcs) {
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200361 channel->OnTransportChannelClosed(error);
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100362 }
363}
364
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200365DataChannelTransportInterface* DataChannelController::data_channel_transport()
366 const {
367 // TODO(bugs.webrtc.org/11547): Only allow this accessor to be called on the
368 // network thread.
369 // RTC_DCHECK_RUN_ON(network_thread());
370 return data_channel_transport_;
371}
372
373void DataChannelController::set_data_channel_transport(
374 DataChannelTransportInterface* transport) {
375 RTC_DCHECK_RUN_ON(network_thread());
376 data_channel_transport_ = transport;
377}
378
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200379bool DataChannelController::DataChannelSendData(
Florent Castellid95b1492021-05-10 11:29:56 +0200380 int sid,
381 const SendDataParams& params,
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200382 const rtc::CopyOnWriteBuffer& payload,
383 cricket::SendDataResult* result) {
384 // TODO(bugs.webrtc.org/11547): Expect method to be called on the network
385 // thread instead. Remove the Invoke() below and move assocated state to
386 // the network thread.
387 RTC_DCHECK_RUN_ON(signaling_thread());
388 RTC_DCHECK(data_channel_transport());
389
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200390 RTCError error = network_thread()->Invoke<RTCError>(
Florent Castellid95b1492021-05-10 11:29:56 +0200391 RTC_FROM_HERE, [this, sid, params, payload] {
392 return data_channel_transport()->SendData(sid, params, payload);
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200393 });
394
395 if (error.ok()) {
396 *result = cricket::SendDataResult::SDR_SUCCESS;
397 return true;
398 } else if (error.type() == RTCErrorType::RESOURCE_EXHAUSTED) {
399 // SCTP transport uses RESOURCE_EXHAUSTED when it's blocked.
400 // TODO(mellem): Stop using RTCError here and get rid of the mapping.
401 *result = cricket::SendDataResult::SDR_BLOCK;
402 return false;
403 }
404 *result = cricket::SendDataResult::SDR_ERROR;
405 return false;
406}
407
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200408void DataChannelController::NotifyDataChannelsOfTransportCreated() {
409 RTC_DCHECK_RUN_ON(network_thread());
Danil Chapovalova30439b2022-07-07 10:08:49 +0200410 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr()] {
411 if (self) {
412 RTC_DCHECK_RUN_ON(self->signaling_thread());
413 for (const auto& channel : self->sctp_data_channels_) {
414 channel->OnTransportChannelCreated();
415 }
416 }
417 });
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200418}
419
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100420rtc::Thread* DataChannelController::network_thread() const {
421 return pc_->network_thread();
422}
423rtc::Thread* DataChannelController::signaling_thread() const {
424 return pc_->signaling_thread();
425}
426
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100427} // namespace webrtc