blob: 36f11fe12ecc9c96621e14b324c2cf6979465ecd [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/logging.h"
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010020
21namespace webrtc {
22
Harald Alvestrand9e5aeb92022-05-11 09:35:36 +000023DataChannelController::~DataChannelController() {
24 // Since channels may have multiple owners, we cannot guarantee that
25 // they will be deallocated before destroying the controller.
26 // Therefore, detach them from the controller.
27 for (auto channel : sctp_data_channels_) {
28 channel->DetachFromController();
29 }
30}
31
Harald Alvestrand05e4d082019-12-03 14:04:21 +010032bool DataChannelController::HasDataChannels() const {
33 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +000034 return !sctp_data_channels_.empty();
Harald Alvestrand05e4d082019-12-03 14:04:21 +010035}
36
Florent Castellid95b1492021-05-10 11:29:56 +020037bool DataChannelController::SendData(int sid,
38 const SendDataParams& params,
Harald Alvestrand05e4d082019-12-03 14:04:21 +010039 const rtc::CopyOnWriteBuffer& payload,
40 cricket::SendDataResult* result) {
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +020041 if (data_channel_transport())
Florent Castellid95b1492021-05-10 11:29:56 +020042 return DataChannelSendData(sid, params, payload, result);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010043 RTC_LOG(LS_ERROR) << "SendData called before transport is ready";
44 return false;
45}
46
Harald Alvestrand05e4d082019-12-03 14:04:21 +010047bool DataChannelController::ConnectDataChannel(
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070048 SctpDataChannel* webrtc_data_channel) {
49 RTC_DCHECK_RUN_ON(signaling_thread());
50 if (!data_channel_transport()) {
51 // Don't log an error here, because DataChannels are expected to call
52 // ConnectDataChannel in this state. It's the only way to initially tell
53 // whether or not the underlying transport is ready.
54 return false;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010055 }
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +000056 SignalDataChannelTransportWritable_s.connect(
57 webrtc_data_channel, &SctpDataChannel::OnTransportReady);
58 SignalDataChannelTransportReceivedData_s.connect(
59 webrtc_data_channel, &SctpDataChannel::OnDataReceived);
60 SignalDataChannelTransportChannelClosing_s.connect(
61 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureStartedRemotely);
62 SignalDataChannelTransportChannelClosed_s.connect(
63 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureComplete);
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070064 return true;
65}
66
67void DataChannelController::DisconnectDataChannel(
68 SctpDataChannel* webrtc_data_channel) {
69 RTC_DCHECK_RUN_ON(signaling_thread());
70 if (!data_channel_transport()) {
71 RTC_LOG(LS_ERROR)
72 << "DisconnectDataChannel called when sctp_transport_ is NULL.";
73 return;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010074 }
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +000075 SignalDataChannelTransportWritable_s.disconnect(webrtc_data_channel);
76 SignalDataChannelTransportReceivedData_s.disconnect(webrtc_data_channel);
77 SignalDataChannelTransportChannelClosing_s.disconnect(webrtc_data_channel);
78 SignalDataChannelTransportChannelClosed_s.disconnect(webrtc_data_channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010079}
80
Harald Alvestrand05e4d082019-12-03 14:04:21 +010081void DataChannelController::AddSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010082 if (data_channel_transport()) {
Danil Chapovalov9e09a1f2022-09-08 18:38:10 +020083 network_thread()->BlockingCall([this, sid] {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010084 if (data_channel_transport()) {
85 data_channel_transport()->OpenChannel(sid);
86 }
87 });
88 }
89}
90
Harald Alvestrand05e4d082019-12-03 14:04:21 +010091void DataChannelController::RemoveSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010092 if (data_channel_transport()) {
Danil Chapovalov9e09a1f2022-09-08 18:38:10 +020093 network_thread()->BlockingCall([this, sid] {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010094 if (data_channel_transport()) {
95 data_channel_transport()->CloseChannel(sid);
96 }
97 });
98 }
99}
100
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100101bool DataChannelController::ReadyToSendData() const {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100102 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000103 return (data_channel_transport() && data_channel_transport_ready_to_send_);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100104}
105
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100106void DataChannelController::OnDataReceived(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100107 int channel_id,
108 DataMessageType type,
109 const rtc::CopyOnWriteBuffer& buffer) {
110 RTC_DCHECK_RUN_ON(network_thread());
111 cricket::ReceiveDataParams params;
112 params.sid = channel_id;
Florent Castellid95b1492021-05-10 11:29:56 +0200113 params.type = type;
Niels Möller236e36c2021-03-23 09:23:10 +0100114 signaling_thread()->PostTask(
Danil Chapovalova30439b2022-07-07 10:08:49 +0200115 [self = weak_factory_.GetWeakPtr(), params, buffer] {
Niels Möller236e36c2021-03-23 09:23:10 +0100116 if (self) {
117 RTC_DCHECK_RUN_ON(self->signaling_thread());
118 // TODO(bugs.webrtc.org/11547): The data being received should be
119 // delivered on the network thread. The way HandleOpenMessage_s works
120 // right now is that it's called for all types of buffers and operates
121 // as a selector function. Change this so that it's only called for
122 // buffers that it should be able to handle. Once we do that, we can
123 // deliver all other buffers on the network thread (change
124 // SignalDataChannelTransportReceivedData_s to
125 // SignalDataChannelTransportReceivedData_n).
126 if (!self->HandleOpenMessage_s(params, buffer)) {
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000127 self->SignalDataChannelTransportReceivedData_s(params, buffer);
Niels Möller236e36c2021-03-23 09:23:10 +0100128 }
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100129 }
Danil Chapovalova30439b2022-07-07 10:08:49 +0200130 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100131}
132
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100133void DataChannelController::OnChannelClosing(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100134 RTC_DCHECK_RUN_ON(network_thread());
Danil Chapovalova30439b2022-07-07 10:08:49 +0200135 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr(), channel_id] {
136 if (self) {
137 RTC_DCHECK_RUN_ON(self->signaling_thread());
138 self->SignalDataChannelTransportChannelClosing_s(channel_id);
139 }
140 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100141}
142
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100143void DataChannelController::OnChannelClosed(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100144 RTC_DCHECK_RUN_ON(network_thread());
Danil Chapovalova30439b2022-07-07 10:08:49 +0200145 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr(), channel_id] {
146 if (self) {
147 RTC_DCHECK_RUN_ON(self->signaling_thread());
148 self->SignalDataChannelTransportChannelClosed_s(channel_id);
149 }
150 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100151}
152
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100153void DataChannelController::OnReadyToSend() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100154 RTC_DCHECK_RUN_ON(network_thread());
Danil Chapovalova30439b2022-07-07 10:08:49 +0200155 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr()] {
156 if (self) {
157 RTC_DCHECK_RUN_ON(self->signaling_thread());
158 self->data_channel_transport_ready_to_send_ = true;
159 self->SignalDataChannelTransportWritable_s(
160 self->data_channel_transport_ready_to_send_);
161 }
162 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100163}
164
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200165void DataChannelController::OnTransportClosed(RTCError error) {
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100166 RTC_DCHECK_RUN_ON(network_thread());
Danil Chapovalova30439b2022-07-07 10:08:49 +0200167 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr(), error] {
168 if (self) {
169 RTC_DCHECK_RUN_ON(self->signaling_thread());
170 self->OnTransportChannelClosed(error);
171 }
172 });
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100173}
174
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100175void DataChannelController::SetupDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100176 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200177
178 // There's a new data channel transport. This needs to be signaled to the
Artem Titov880fa812021-07-30 22:30:23 +0200179 // `sctp_data_channels_` so that they can reopen and reconnect. This is
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200180 // necessary when bundling is applied.
181 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100182}
183
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100184void DataChannelController::TeardownDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100185 RTC_DCHECK_RUN_ON(network_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100186 if (data_channel_transport()) {
187 data_channel_transport()->SetDataSink(nullptr);
188 }
189 set_data_channel_transport(nullptr);
190}
191
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100192void DataChannelController::OnTransportChanged(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100193 DataChannelTransportInterface* new_data_channel_transport) {
194 RTC_DCHECK_RUN_ON(network_thread());
195 if (data_channel_transport() &&
196 data_channel_transport() != new_data_channel_transport) {
Artem Titov880fa812021-07-30 22:30:23 +0200197 // Changed which data channel transport is used for `sctp_mid_` (eg. now
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100198 // it's bundled).
199 data_channel_transport()->SetDataSink(nullptr);
200 set_data_channel_transport(new_data_channel_transport);
201 if (new_data_channel_transport) {
202 new_data_channel_transport->SetDataSink(this);
203
204 // There's a new data channel transport. This needs to be signaled to the
Artem Titov880fa812021-07-30 22:30:23 +0200205 // `sctp_data_channels_` so that they can reopen and reconnect. This is
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100206 // necessary when bundling is applied.
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200207 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100208 }
209 }
210}
211
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700212std::vector<DataChannelStats> DataChannelController::GetDataChannelStats()
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200213 const {
214 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700215 std::vector<DataChannelStats> stats;
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200216 stats.reserve(sctp_data_channels_.size());
217 for (const auto& channel : sctp_data_channels_)
218 stats.push_back(channel->GetStats());
219 return stats;
220}
221
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100222bool DataChannelController::HandleOpenMessage_s(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100223 const cricket::ReceiveDataParams& params,
224 const rtc::CopyOnWriteBuffer& buffer) {
Florent Castellid95b1492021-05-10 11:29:56 +0200225 if (params.type == DataMessageType::kControl && IsOpenMessage(buffer)) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100226 // Received OPEN message; parse and signal that a new data channel should
227 // be created.
228 std::string label;
229 InternalDataChannelInit config;
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000230 config.id = params.sid;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100231 if (!ParseDataChannelOpenMessage(buffer, &label, &config)) {
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000232 RTC_LOG(LS_WARNING) << "Failed to parse the OPEN message for sid "
233 << params.sid;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100234 return true;
235 }
236 config.open_handshake_role = InternalDataChannelInit::kAcker;
237 OnDataChannelOpenMessage(label, config);
238 return true;
239 }
240 return false;
241}
242
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100243void DataChannelController::OnDataChannelOpenMessage(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100244 const std::string& label,
245 const InternalDataChannelInit& config) {
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700246 rtc::scoped_refptr<DataChannelInterface> channel(
247 InternalCreateDataChannelWithProxy(label, &config));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100248 if (!channel.get()) {
249 RTC_LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
250 return;
251 }
252
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700253 pc_->Observer()->OnDataChannel(std::move(channel));
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100254 pc_->NoteDataAddedEvent();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100255}
256
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700257rtc::scoped_refptr<DataChannelInterface>
258DataChannelController::InternalCreateDataChannelWithProxy(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100259 const std::string& label,
260 const InternalDataChannelInit* config) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100261 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100262 if (pc_->IsClosed()) {
263 return nullptr;
264 }
Florent Castelli516e2842021-04-19 15:29:50 +0200265
266 rtc::scoped_refptr<SctpDataChannel> channel =
267 InternalCreateSctpDataChannel(label, config);
268 if (channel) {
269 return SctpDataChannel::CreateProxy(channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100270 }
271
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700272 return nullptr;
273}
274
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700275rtc::scoped_refptr<SctpDataChannel>
276DataChannelController::InternalCreateSctpDataChannel(
277 const std::string& label,
278 const InternalDataChannelInit* config) {
279 RTC_DCHECK_RUN_ON(signaling_thread());
280 InternalDataChannelInit new_config =
281 config ? (*config) : InternalDataChannelInit();
282 if (new_config.id < 0) {
283 rtc::SSLRole role;
284 if ((pc_->GetSctpSslRole(&role)) &&
285 !sid_allocator_.AllocateSid(role, &new_config.id)) {
286 RTC_LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
287 return nullptr;
288 }
289 } else if (!sid_allocator_.ReserveSid(new_config.id)) {
290 RTC_LOG(LS_ERROR) << "Failed to create a SCTP data channel "
291 "because the id is already in use or out of range.";
292 return nullptr;
293 }
294 rtc::scoped_refptr<SctpDataChannel> channel(SctpDataChannel::Create(
295 this, label, new_config, signaling_thread(), network_thread()));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100296 if (!channel) {
297 sid_allocator_.ReleaseSid(new_config.id);
298 return nullptr;
299 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700300 sctp_data_channels_.push_back(channel);
Harald Alvestrand5b84f382022-02-08 10:49:09 +0000301 channel->SignalClosed.connect(
302 pc_, &PeerConnectionInternal::OnSctpDataChannelClosed);
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000303 SignalSctpDataChannelCreated_(channel.get());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100304 return channel;
305}
306
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100307void DataChannelController::AllocateSctpSids(rtc::SSLRole role) {
308 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700309 std::vector<rtc::scoped_refptr<SctpDataChannel>> channels_to_close;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100310 for (const auto& channel : sctp_data_channels_) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100311 if (channel->id() < 0) {
312 int sid;
313 if (!sid_allocator_.AllocateSid(role, &sid)) {
314 RTC_LOG(LS_ERROR) << "Failed to allocate SCTP sid, closing channel.";
315 channels_to_close.push_back(channel);
316 continue;
317 }
318 channel->SetSctpSid(sid);
319 }
320 }
321 // Since closing modifies the list of channels, we have to do the actual
322 // closing outside the loop.
323 for (const auto& channel : channels_to_close) {
Harald Alvestranddfbfb462019-12-08 05:55:43 +0100324 channel->CloseAbruptlyWithDataChannelFailure("Failed to allocate SCTP SID");
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100325 }
326}
327
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700328void DataChannelController::OnSctpDataChannelClosed(SctpDataChannel* channel) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100329 RTC_DCHECK_RUN_ON(signaling_thread());
330 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end();
331 ++it) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100332 if (it->get() == channel) {
333 if (channel->id() >= 0) {
334 // After the closing procedure is done, it's safe to use this ID for
335 // another data channel.
336 sid_allocator_.ReleaseSid(channel->id());
337 }
338 // Since this method is triggered by a signal from the DataChannel,
339 // we can't free it directly here; we need to free it asynchronously.
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100340 sctp_data_channels_to_free_.push_back(*it);
341 sctp_data_channels_.erase(it);
Danil Chapovalova30439b2022-07-07 10:08:49 +0200342 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr()] {
343 if (self) {
344 RTC_DCHECK_RUN_ON(self->signaling_thread());
345 self->sctp_data_channels_to_free_.clear();
346 }
347 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100348 return;
349 }
350 }
351}
352
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200353void DataChannelController::OnTransportChannelClosed(RTCError error) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100354 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000355 // Use a temporary copy of the SCTP DataChannel list because the
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100356 // DataChannel may callback to us and try to modify the list.
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700357 std::vector<rtc::scoped_refptr<SctpDataChannel>> temp_sctp_dcs;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100358 temp_sctp_dcs.swap(sctp_data_channels_);
359 for (const auto& channel : temp_sctp_dcs) {
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200360 channel->OnTransportChannelClosed(error);
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100361 }
362}
363
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200364DataChannelTransportInterface* DataChannelController::data_channel_transport()
365 const {
366 // TODO(bugs.webrtc.org/11547): Only allow this accessor to be called on the
367 // network thread.
368 // RTC_DCHECK_RUN_ON(network_thread());
369 return data_channel_transport_;
370}
371
372void DataChannelController::set_data_channel_transport(
373 DataChannelTransportInterface* transport) {
374 RTC_DCHECK_RUN_ON(network_thread());
375 data_channel_transport_ = transport;
376}
377
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200378bool DataChannelController::DataChannelSendData(
Florent Castellid95b1492021-05-10 11:29:56 +0200379 int sid,
380 const SendDataParams& params,
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200381 const rtc::CopyOnWriteBuffer& payload,
382 cricket::SendDataResult* result) {
383 // TODO(bugs.webrtc.org/11547): Expect method to be called on the network
Danil Chapovalov9e09a1f2022-09-08 18:38:10 +0200384 // thread instead. Remove the BlockingCall() below and move assocated state to
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200385 // the network thread.
386 RTC_DCHECK_RUN_ON(signaling_thread());
387 RTC_DCHECK(data_channel_transport());
388
Danil Chapovalov9e09a1f2022-09-08 18:38:10 +0200389 RTCError error = network_thread()->BlockingCall([this, sid, params, payload] {
390 return data_channel_transport()->SendData(sid, params, payload);
391 });
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200392
393 if (error.ok()) {
394 *result = cricket::SendDataResult::SDR_SUCCESS;
395 return true;
396 } else if (error.type() == RTCErrorType::RESOURCE_EXHAUSTED) {
397 // SCTP transport uses RESOURCE_EXHAUSTED when it's blocked.
398 // TODO(mellem): Stop using RTCError here and get rid of the mapping.
399 *result = cricket::SendDataResult::SDR_BLOCK;
400 return false;
401 }
402 *result = cricket::SendDataResult::SDR_ERROR;
403 return false;
404}
405
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200406void DataChannelController::NotifyDataChannelsOfTransportCreated() {
407 RTC_DCHECK_RUN_ON(network_thread());
Danil Chapovalova30439b2022-07-07 10:08:49 +0200408 signaling_thread()->PostTask([self = weak_factory_.GetWeakPtr()] {
409 if (self) {
410 RTC_DCHECK_RUN_ON(self->signaling_thread());
411 for (const auto& channel : self->sctp_data_channels_) {
412 channel->OnTransportChannelCreated();
413 }
414 }
415 });
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200416}
417
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100418rtc::Thread* DataChannelController::network_thread() const {
419 return pc_->network_thread();
420}
421rtc::Thread* DataChannelController::signaling_thread() const {
422 return pc_->signaling_thread();
423}
424
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100425} // namespace webrtc