blob: a9fa3dabb9b9125b23c32046aa71acac26d19bbe [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"
Niels Möller236e36c2021-03-23 09:23:10 +010021#include "rtc_base/task_utils/to_queued_task.h"
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010022
23namespace webrtc {
24
Harald Alvestrand05e4d082019-12-03 14:04:21 +010025bool DataChannelController::HasDataChannels() const {
26 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +000027 return !sctp_data_channels_.empty();
Harald Alvestrand05e4d082019-12-03 14:04:21 +010028}
29
Florent Castellid95b1492021-05-10 11:29:56 +020030bool DataChannelController::SendData(int sid,
31 const SendDataParams& params,
Harald Alvestrand05e4d082019-12-03 14:04:21 +010032 const rtc::CopyOnWriteBuffer& payload,
33 cricket::SendDataResult* result) {
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +020034 if (data_channel_transport())
Florent Castellid95b1492021-05-10 11:29:56 +020035 return DataChannelSendData(sid, params, payload, result);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010036 RTC_LOG(LS_ERROR) << "SendData called before transport is ready";
37 return false;
38}
39
Harald Alvestrand05e4d082019-12-03 14:04:21 +010040bool DataChannelController::ConnectDataChannel(
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070041 SctpDataChannel* webrtc_data_channel) {
42 RTC_DCHECK_RUN_ON(signaling_thread());
43 if (!data_channel_transport()) {
44 // Don't log an error here, because DataChannels are expected to call
45 // ConnectDataChannel in this state. It's the only way to initially tell
46 // whether or not the underlying transport is ready.
47 return false;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010048 }
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +000049 SignalDataChannelTransportWritable_s.connect(
50 webrtc_data_channel, &SctpDataChannel::OnTransportReady);
51 SignalDataChannelTransportReceivedData_s.connect(
52 webrtc_data_channel, &SctpDataChannel::OnDataReceived);
53 SignalDataChannelTransportChannelClosing_s.connect(
54 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureStartedRemotely);
55 SignalDataChannelTransportChannelClosed_s.connect(
56 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureComplete);
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070057 return true;
58}
59
60void DataChannelController::DisconnectDataChannel(
61 SctpDataChannel* webrtc_data_channel) {
62 RTC_DCHECK_RUN_ON(signaling_thread());
63 if (!data_channel_transport()) {
64 RTC_LOG(LS_ERROR)
65 << "DisconnectDataChannel called when sctp_transport_ is NULL.";
66 return;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010067 }
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +000068 SignalDataChannelTransportWritable_s.disconnect(webrtc_data_channel);
69 SignalDataChannelTransportReceivedData_s.disconnect(webrtc_data_channel);
70 SignalDataChannelTransportChannelClosing_s.disconnect(webrtc_data_channel);
71 SignalDataChannelTransportChannelClosed_s.disconnect(webrtc_data_channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010072}
73
Harald Alvestrand05e4d082019-12-03 14:04:21 +010074void DataChannelController::AddSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010075 if (data_channel_transport()) {
76 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
77 if (data_channel_transport()) {
78 data_channel_transport()->OpenChannel(sid);
79 }
80 });
81 }
82}
83
Harald Alvestrand05e4d082019-12-03 14:04:21 +010084void DataChannelController::RemoveSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010085 if (data_channel_transport()) {
86 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
87 if (data_channel_transport()) {
88 data_channel_transport()->CloseChannel(sid);
89 }
90 });
91 }
92}
93
Harald Alvestrand05e4d082019-12-03 14:04:21 +010094bool DataChannelController::ReadyToSendData() const {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010095 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +000096 return (data_channel_transport() && data_channel_transport_ready_to_send_);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010097}
98
Harald Alvestrand05e4d082019-12-03 14:04:21 +010099void DataChannelController::OnDataReceived(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100100 int channel_id,
101 DataMessageType type,
102 const rtc::CopyOnWriteBuffer& buffer) {
103 RTC_DCHECK_RUN_ON(network_thread());
104 cricket::ReceiveDataParams params;
105 params.sid = channel_id;
Florent Castellid95b1492021-05-10 11:29:56 +0200106 params.type = type;
Niels Möller236e36c2021-03-23 09:23:10 +0100107 signaling_thread()->PostTask(
108 ToQueuedTask([self = weak_factory_.GetWeakPtr(), params, buffer] {
109 if (self) {
110 RTC_DCHECK_RUN_ON(self->signaling_thread());
111 // TODO(bugs.webrtc.org/11547): The data being received should be
112 // delivered on the network thread. The way HandleOpenMessage_s works
113 // right now is that it's called for all types of buffers and operates
114 // as a selector function. Change this so that it's only called for
115 // buffers that it should be able to handle. Once we do that, we can
116 // deliver all other buffers on the network thread (change
117 // SignalDataChannelTransportReceivedData_s to
118 // SignalDataChannelTransportReceivedData_n).
119 if (!self->HandleOpenMessage_s(params, buffer)) {
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000120 self->SignalDataChannelTransportReceivedData_s(params, buffer);
Niels Möller236e36c2021-03-23 09:23:10 +0100121 }
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100122 }
Niels Möller236e36c2021-03-23 09:23:10 +0100123 }));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100124}
125
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100126void DataChannelController::OnChannelClosing(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100127 RTC_DCHECK_RUN_ON(network_thread());
Niels Möller236e36c2021-03-23 09:23:10 +0100128 signaling_thread()->PostTask(
129 ToQueuedTask([self = weak_factory_.GetWeakPtr(), channel_id] {
130 if (self) {
131 RTC_DCHECK_RUN_ON(self->signaling_thread());
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000132 self->SignalDataChannelTransportChannelClosing_s(channel_id);
Niels Möller236e36c2021-03-23 09:23:10 +0100133 }
134 }));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100135}
136
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100137void DataChannelController::OnChannelClosed(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100138 RTC_DCHECK_RUN_ON(network_thread());
Niels Möller236e36c2021-03-23 09:23:10 +0100139 signaling_thread()->PostTask(
140 ToQueuedTask([self = weak_factory_.GetWeakPtr(), channel_id] {
141 if (self) {
142 RTC_DCHECK_RUN_ON(self->signaling_thread());
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000143 self->SignalDataChannelTransportChannelClosed_s(channel_id);
Niels Möller236e36c2021-03-23 09:23:10 +0100144 }
145 }));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100146}
147
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100148void DataChannelController::OnReadyToSend() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100149 RTC_DCHECK_RUN_ON(network_thread());
Niels Möller236e36c2021-03-23 09:23:10 +0100150 signaling_thread()->PostTask(
151 ToQueuedTask([self = weak_factory_.GetWeakPtr()] {
152 if (self) {
153 RTC_DCHECK_RUN_ON(self->signaling_thread());
154 self->data_channel_transport_ready_to_send_ = true;
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000155 self->SignalDataChannelTransportWritable_s(
Niels Möller236e36c2021-03-23 09:23:10 +0100156 self->data_channel_transport_ready_to_send_);
157 }
158 }));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100159}
160
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200161void DataChannelController::OnTransportClosed(RTCError error) {
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100162 RTC_DCHECK_RUN_ON(network_thread());
Niels Möller236e36c2021-03-23 09:23:10 +0100163 signaling_thread()->PostTask(
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200164 ToQueuedTask([self = weak_factory_.GetWeakPtr(), error] {
Niels Möller236e36c2021-03-23 09:23:10 +0100165 if (self) {
166 RTC_DCHECK_RUN_ON(self->signaling_thread());
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200167 self->OnTransportChannelClosed(error);
Niels Möller236e36c2021-03-23 09:23:10 +0100168 }
169 }));
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100170}
171
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100172void DataChannelController::SetupDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100173 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200174
175 // There's a new data channel transport. This needs to be signaled to the
Artem Titov880fa812021-07-30 22:30:23 +0200176 // `sctp_data_channels_` so that they can reopen and reconnect. This is
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200177 // necessary when bundling is applied.
178 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100179}
180
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100181void DataChannelController::TeardownDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100182 RTC_DCHECK_RUN_ON(network_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100183 if (data_channel_transport()) {
184 data_channel_transport()->SetDataSink(nullptr);
185 }
186 set_data_channel_transport(nullptr);
187}
188
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100189void DataChannelController::OnTransportChanged(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100190 DataChannelTransportInterface* new_data_channel_transport) {
191 RTC_DCHECK_RUN_ON(network_thread());
192 if (data_channel_transport() &&
193 data_channel_transport() != new_data_channel_transport) {
Artem Titov880fa812021-07-30 22:30:23 +0200194 // Changed which data channel transport is used for `sctp_mid_` (eg. now
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100195 // it's bundled).
196 data_channel_transport()->SetDataSink(nullptr);
197 set_data_channel_transport(new_data_channel_transport);
198 if (new_data_channel_transport) {
199 new_data_channel_transport->SetDataSink(this);
200
201 // There's a new data channel transport. This needs to be signaled to the
Artem Titov880fa812021-07-30 22:30:23 +0200202 // `sctp_data_channels_` so that they can reopen and reconnect. This is
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100203 // necessary when bundling is applied.
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200204 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100205 }
206 }
207}
208
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700209std::vector<DataChannelStats> DataChannelController::GetDataChannelStats()
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200210 const {
211 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700212 std::vector<DataChannelStats> stats;
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200213 stats.reserve(sctp_data_channels_.size());
214 for (const auto& channel : sctp_data_channels_)
215 stats.push_back(channel->GetStats());
216 return stats;
217}
218
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100219bool DataChannelController::HandleOpenMessage_s(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100220 const cricket::ReceiveDataParams& params,
221 const rtc::CopyOnWriteBuffer& buffer) {
Florent Castellid95b1492021-05-10 11:29:56 +0200222 if (params.type == DataMessageType::kControl && IsOpenMessage(buffer)) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100223 // Received OPEN message; parse and signal that a new data channel should
224 // be created.
225 std::string label;
226 InternalDataChannelInit config;
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000227 config.id = params.sid;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100228 if (!ParseDataChannelOpenMessage(buffer, &label, &config)) {
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000229 RTC_LOG(LS_WARNING) << "Failed to parse the OPEN message for sid "
230 << params.sid;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100231 return true;
232 }
233 config.open_handshake_role = InternalDataChannelInit::kAcker;
234 OnDataChannelOpenMessage(label, config);
235 return true;
236 }
237 return false;
238}
239
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100240void DataChannelController::OnDataChannelOpenMessage(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100241 const std::string& label,
242 const InternalDataChannelInit& config) {
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700243 rtc::scoped_refptr<DataChannelInterface> channel(
244 InternalCreateDataChannelWithProxy(label, &config));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100245 if (!channel.get()) {
246 RTC_LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
247 return;
248 }
249
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700250 pc_->Observer()->OnDataChannel(std::move(channel));
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100251 pc_->NoteDataAddedEvent();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100252}
253
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700254rtc::scoped_refptr<DataChannelInterface>
255DataChannelController::InternalCreateDataChannelWithProxy(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100256 const std::string& label,
257 const InternalDataChannelInit* config) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100258 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100259 if (pc_->IsClosed()) {
260 return nullptr;
261 }
Florent Castelli516e2842021-04-19 15:29:50 +0200262
263 rtc::scoped_refptr<SctpDataChannel> channel =
264 InternalCreateSctpDataChannel(label, config);
265 if (channel) {
266 return SctpDataChannel::CreateProxy(channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100267 }
268
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700269 return nullptr;
270}
271
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700272rtc::scoped_refptr<SctpDataChannel>
273DataChannelController::InternalCreateSctpDataChannel(
274 const std::string& label,
275 const InternalDataChannelInit* config) {
276 RTC_DCHECK_RUN_ON(signaling_thread());
277 InternalDataChannelInit new_config =
278 config ? (*config) : InternalDataChannelInit();
279 if (new_config.id < 0) {
280 rtc::SSLRole role;
281 if ((pc_->GetSctpSslRole(&role)) &&
282 !sid_allocator_.AllocateSid(role, &new_config.id)) {
283 RTC_LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
284 return nullptr;
285 }
286 } else if (!sid_allocator_.ReserveSid(new_config.id)) {
287 RTC_LOG(LS_ERROR) << "Failed to create a SCTP data channel "
288 "because the id is already in use or out of range.";
289 return nullptr;
290 }
291 rtc::scoped_refptr<SctpDataChannel> channel(SctpDataChannel::Create(
292 this, label, new_config, signaling_thread(), network_thread()));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100293 if (!channel) {
294 sid_allocator_.ReleaseSid(new_config.id);
295 return nullptr;
296 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700297 sctp_data_channels_.push_back(channel);
Harald Alvestrand5b84f382022-02-08 10:49:09 +0000298 channel->SignalClosed.connect(
299 pc_, &PeerConnectionInternal::OnSctpDataChannelClosed);
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000300 SignalSctpDataChannelCreated_(channel.get());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100301 return channel;
302}
303
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100304void DataChannelController::AllocateSctpSids(rtc::SSLRole role) {
305 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700306 std::vector<rtc::scoped_refptr<SctpDataChannel>> channels_to_close;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100307 for (const auto& channel : sctp_data_channels_) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100308 if (channel->id() < 0) {
309 int sid;
310 if (!sid_allocator_.AllocateSid(role, &sid)) {
311 RTC_LOG(LS_ERROR) << "Failed to allocate SCTP sid, closing channel.";
312 channels_to_close.push_back(channel);
313 continue;
314 }
315 channel->SetSctpSid(sid);
316 }
317 }
318 // Since closing modifies the list of channels, we have to do the actual
319 // closing outside the loop.
320 for (const auto& channel : channels_to_close) {
Harald Alvestranddfbfb462019-12-08 05:55:43 +0100321 channel->CloseAbruptlyWithDataChannelFailure("Failed to allocate SCTP SID");
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100322 }
323}
324
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700325void DataChannelController::OnSctpDataChannelClosed(SctpDataChannel* channel) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100326 RTC_DCHECK_RUN_ON(signaling_thread());
327 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end();
328 ++it) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100329 if (it->get() == channel) {
330 if (channel->id() >= 0) {
331 // After the closing procedure is done, it's safe to use this ID for
332 // another data channel.
333 sid_allocator_.ReleaseSid(channel->id());
334 }
335 // Since this method is triggered by a signal from the DataChannel,
336 // we can't free it directly here; we need to free it asynchronously.
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100337 sctp_data_channels_to_free_.push_back(*it);
338 sctp_data_channels_.erase(it);
Harald Alvestrand246724b2019-12-03 22:31:42 +0100339 signaling_thread()->PostTask(
Niels Möller236e36c2021-03-23 09:23:10 +0100340 ToQueuedTask([self = weak_factory_.GetWeakPtr()] {
Harald Alvestrand246724b2019-12-03 22:31:42 +0100341 if (self) {
342 RTC_DCHECK_RUN_ON(self->signaling_thread());
343 self->sctp_data_channels_to_free_.clear();
344 }
Niels Möller236e36c2021-03-23 09:23:10 +0100345 }));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100346 return;
347 }
348 }
349}
350
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200351void DataChannelController::OnTransportChannelClosed(RTCError error) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100352 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000353 // Use a temporary copy of the SCTP DataChannel list because the
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100354 // DataChannel may callback to us and try to modify the list.
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700355 std::vector<rtc::scoped_refptr<SctpDataChannel>> temp_sctp_dcs;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100356 temp_sctp_dcs.swap(sctp_data_channels_);
357 for (const auto& channel : temp_sctp_dcs) {
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200358 channel->OnTransportChannelClosed(error);
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100359 }
360}
361
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200362DataChannelTransportInterface* DataChannelController::data_channel_transport()
363 const {
364 // TODO(bugs.webrtc.org/11547): Only allow this accessor to be called on the
365 // network thread.
366 // RTC_DCHECK_RUN_ON(network_thread());
367 return data_channel_transport_;
368}
369
370void DataChannelController::set_data_channel_transport(
371 DataChannelTransportInterface* transport) {
372 RTC_DCHECK_RUN_ON(network_thread());
373 data_channel_transport_ = transport;
374}
375
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200376bool DataChannelController::DataChannelSendData(
Florent Castellid95b1492021-05-10 11:29:56 +0200377 int sid,
378 const SendDataParams& params,
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200379 const rtc::CopyOnWriteBuffer& payload,
380 cricket::SendDataResult* result) {
381 // TODO(bugs.webrtc.org/11547): Expect method to be called on the network
382 // thread instead. Remove the Invoke() below and move assocated state to
383 // the network thread.
384 RTC_DCHECK_RUN_ON(signaling_thread());
385 RTC_DCHECK(data_channel_transport());
386
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200387 RTCError error = network_thread()->Invoke<RTCError>(
Florent Castellid95b1492021-05-10 11:29:56 +0200388 RTC_FROM_HERE, [this, sid, params, payload] {
389 return data_channel_transport()->SendData(sid, params, payload);
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200390 });
391
392 if (error.ok()) {
393 *result = cricket::SendDataResult::SDR_SUCCESS;
394 return true;
395 } else if (error.type() == RTCErrorType::RESOURCE_EXHAUSTED) {
396 // SCTP transport uses RESOURCE_EXHAUSTED when it's blocked.
397 // TODO(mellem): Stop using RTCError here and get rid of the mapping.
398 *result = cricket::SendDataResult::SDR_BLOCK;
399 return false;
400 }
401 *result = cricket::SendDataResult::SDR_ERROR;
402 return false;
403}
404
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200405void DataChannelController::NotifyDataChannelsOfTransportCreated() {
406 RTC_DCHECK_RUN_ON(network_thread());
Niels Möller236e36c2021-03-23 09:23:10 +0100407 signaling_thread()->PostTask(
408 ToQueuedTask([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 }
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200414 }
Niels Möller236e36c2021-03-23 09:23:10 +0100415 }));
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