blob: b1461cde9ad82f006dc060640f3d812dfb7bf13e [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"
Artem Titovc374d112022-06-16 21:27:45 +020017#include "api/task_queue/to_queued_task.h"
Harald Alvestrand5b84f382022-02-08 10:49:09 +000018#include "pc/peer_connection_internal.h"
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010019#include "pc/sctp_utils.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000020#include "rtc_base/location.h"
21#include "rtc_base/logging.h"
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010022
23namespace webrtc {
24
Harald Alvestrand9e5aeb92022-05-11 09:35:36 +000025DataChannelController::~DataChannelController() {
26 // Since channels may have multiple owners, we cannot guarantee that
27 // they will be deallocated before destroying the controller.
28 // Therefore, detach them from the controller.
29 for (auto channel : sctp_data_channels_) {
30 channel->DetachFromController();
31 }
32}
33
Harald Alvestrand05e4d082019-12-03 14:04:21 +010034bool DataChannelController::HasDataChannels() const {
35 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +000036 return !sctp_data_channels_.empty();
Harald Alvestrand05e4d082019-12-03 14:04:21 +010037}
38
Florent Castellid95b1492021-05-10 11:29:56 +020039bool DataChannelController::SendData(int sid,
40 const SendDataParams& params,
Harald Alvestrand05e4d082019-12-03 14:04:21 +010041 const rtc::CopyOnWriteBuffer& payload,
42 cricket::SendDataResult* result) {
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +020043 if (data_channel_transport())
Florent Castellid95b1492021-05-10 11:29:56 +020044 return DataChannelSendData(sid, params, payload, result);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010045 RTC_LOG(LS_ERROR) << "SendData called before transport is ready";
46 return false;
47}
48
Harald Alvestrand05e4d082019-12-03 14:04:21 +010049bool DataChannelController::ConnectDataChannel(
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070050 SctpDataChannel* webrtc_data_channel) {
51 RTC_DCHECK_RUN_ON(signaling_thread());
52 if (!data_channel_transport()) {
53 // Don't log an error here, because DataChannels are expected to call
54 // ConnectDataChannel in this state. It's the only way to initially tell
55 // whether or not the underlying transport is ready.
56 return false;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010057 }
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +000058 SignalDataChannelTransportWritable_s.connect(
59 webrtc_data_channel, &SctpDataChannel::OnTransportReady);
60 SignalDataChannelTransportReceivedData_s.connect(
61 webrtc_data_channel, &SctpDataChannel::OnDataReceived);
62 SignalDataChannelTransportChannelClosing_s.connect(
63 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureStartedRemotely);
64 SignalDataChannelTransportChannelClosed_s.connect(
65 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureComplete);
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070066 return true;
67}
68
69void DataChannelController::DisconnectDataChannel(
70 SctpDataChannel* webrtc_data_channel) {
71 RTC_DCHECK_RUN_ON(signaling_thread());
72 if (!data_channel_transport()) {
73 RTC_LOG(LS_ERROR)
74 << "DisconnectDataChannel called when sctp_transport_ is NULL.";
75 return;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010076 }
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +000077 SignalDataChannelTransportWritable_s.disconnect(webrtc_data_channel);
78 SignalDataChannelTransportReceivedData_s.disconnect(webrtc_data_channel);
79 SignalDataChannelTransportChannelClosing_s.disconnect(webrtc_data_channel);
80 SignalDataChannelTransportChannelClosed_s.disconnect(webrtc_data_channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010081}
82
Harald Alvestrand05e4d082019-12-03 14:04:21 +010083void DataChannelController::AddSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010084 if (data_channel_transport()) {
85 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
86 if (data_channel_transport()) {
87 data_channel_transport()->OpenChannel(sid);
88 }
89 });
90 }
91}
92
Harald Alvestrand05e4d082019-12-03 14:04:21 +010093void DataChannelController::RemoveSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010094 if (data_channel_transport()) {
95 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
96 if (data_channel_transport()) {
97 data_channel_transport()->CloseChannel(sid);
98 }
99 });
100 }
101}
102
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100103bool DataChannelController::ReadyToSendData() const {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100104 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000105 return (data_channel_transport() && data_channel_transport_ready_to_send_);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100106}
107
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100108void DataChannelController::OnDataReceived(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100109 int channel_id,
110 DataMessageType type,
111 const rtc::CopyOnWriteBuffer& buffer) {
112 RTC_DCHECK_RUN_ON(network_thread());
113 cricket::ReceiveDataParams params;
114 params.sid = channel_id;
Florent Castellid95b1492021-05-10 11:29:56 +0200115 params.type = type;
Niels Möller236e36c2021-03-23 09:23:10 +0100116 signaling_thread()->PostTask(
117 ToQueuedTask([self = weak_factory_.GetWeakPtr(), params, buffer] {
118 if (self) {
119 RTC_DCHECK_RUN_ON(self->signaling_thread());
120 // TODO(bugs.webrtc.org/11547): The data being received should be
121 // delivered on the network thread. The way HandleOpenMessage_s works
122 // right now is that it's called for all types of buffers and operates
123 // as a selector function. Change this so that it's only called for
124 // buffers that it should be able to handle. Once we do that, we can
125 // deliver all other buffers on the network thread (change
126 // SignalDataChannelTransportReceivedData_s to
127 // SignalDataChannelTransportReceivedData_n).
128 if (!self->HandleOpenMessage_s(params, buffer)) {
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000129 self->SignalDataChannelTransportReceivedData_s(params, buffer);
Niels Möller236e36c2021-03-23 09:23:10 +0100130 }
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100131 }
Niels Möller236e36c2021-03-23 09:23:10 +0100132 }));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100133}
134
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100135void DataChannelController::OnChannelClosing(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100136 RTC_DCHECK_RUN_ON(network_thread());
Niels Möller236e36c2021-03-23 09:23:10 +0100137 signaling_thread()->PostTask(
138 ToQueuedTask([self = weak_factory_.GetWeakPtr(), channel_id] {
139 if (self) {
140 RTC_DCHECK_RUN_ON(self->signaling_thread());
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000141 self->SignalDataChannelTransportChannelClosing_s(channel_id);
Niels Möller236e36c2021-03-23 09:23:10 +0100142 }
143 }));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100144}
145
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100146void DataChannelController::OnChannelClosed(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100147 RTC_DCHECK_RUN_ON(network_thread());
Niels Möller236e36c2021-03-23 09:23:10 +0100148 signaling_thread()->PostTask(
149 ToQueuedTask([self = weak_factory_.GetWeakPtr(), channel_id] {
150 if (self) {
151 RTC_DCHECK_RUN_ON(self->signaling_thread());
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000152 self->SignalDataChannelTransportChannelClosed_s(channel_id);
Niels Möller236e36c2021-03-23 09:23:10 +0100153 }
154 }));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100155}
156
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100157void DataChannelController::OnReadyToSend() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100158 RTC_DCHECK_RUN_ON(network_thread());
Niels Möller236e36c2021-03-23 09:23:10 +0100159 signaling_thread()->PostTask(
160 ToQueuedTask([self = weak_factory_.GetWeakPtr()] {
161 if (self) {
162 RTC_DCHECK_RUN_ON(self->signaling_thread());
163 self->data_channel_transport_ready_to_send_ = true;
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000164 self->SignalDataChannelTransportWritable_s(
Niels Möller236e36c2021-03-23 09:23:10 +0100165 self->data_channel_transport_ready_to_send_);
166 }
167 }));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100168}
169
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200170void DataChannelController::OnTransportClosed(RTCError error) {
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100171 RTC_DCHECK_RUN_ON(network_thread());
Niels Möller236e36c2021-03-23 09:23:10 +0100172 signaling_thread()->PostTask(
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200173 ToQueuedTask([self = weak_factory_.GetWeakPtr(), error] {
Niels Möller236e36c2021-03-23 09:23:10 +0100174 if (self) {
175 RTC_DCHECK_RUN_ON(self->signaling_thread());
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200176 self->OnTransportChannelClosed(error);
Niels Möller236e36c2021-03-23 09:23:10 +0100177 }
178 }));
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100179}
180
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100181void DataChannelController::SetupDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100182 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200183
184 // There's a new data channel transport. This needs to be signaled to the
Artem Titov880fa812021-07-30 22:30:23 +0200185 // `sctp_data_channels_` so that they can reopen and reconnect. This is
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200186 // necessary when bundling is applied.
187 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100188}
189
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100190void DataChannelController::TeardownDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100191 RTC_DCHECK_RUN_ON(network_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100192 if (data_channel_transport()) {
193 data_channel_transport()->SetDataSink(nullptr);
194 }
195 set_data_channel_transport(nullptr);
196}
197
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100198void DataChannelController::OnTransportChanged(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100199 DataChannelTransportInterface* new_data_channel_transport) {
200 RTC_DCHECK_RUN_ON(network_thread());
201 if (data_channel_transport() &&
202 data_channel_transport() != new_data_channel_transport) {
Artem Titov880fa812021-07-30 22:30:23 +0200203 // Changed which data channel transport is used for `sctp_mid_` (eg. now
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100204 // it's bundled).
205 data_channel_transport()->SetDataSink(nullptr);
206 set_data_channel_transport(new_data_channel_transport);
207 if (new_data_channel_transport) {
208 new_data_channel_transport->SetDataSink(this);
209
210 // There's a new data channel transport. This needs to be signaled to the
Artem Titov880fa812021-07-30 22:30:23 +0200211 // `sctp_data_channels_` so that they can reopen and reconnect. This is
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100212 // necessary when bundling is applied.
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200213 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100214 }
215 }
216}
217
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700218std::vector<DataChannelStats> DataChannelController::GetDataChannelStats()
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200219 const {
220 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700221 std::vector<DataChannelStats> stats;
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200222 stats.reserve(sctp_data_channels_.size());
223 for (const auto& channel : sctp_data_channels_)
224 stats.push_back(channel->GetStats());
225 return stats;
226}
227
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100228bool DataChannelController::HandleOpenMessage_s(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100229 const cricket::ReceiveDataParams& params,
230 const rtc::CopyOnWriteBuffer& buffer) {
Florent Castellid95b1492021-05-10 11:29:56 +0200231 if (params.type == DataMessageType::kControl && IsOpenMessage(buffer)) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100232 // Received OPEN message; parse and signal that a new data channel should
233 // be created.
234 std::string label;
235 InternalDataChannelInit config;
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000236 config.id = params.sid;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100237 if (!ParseDataChannelOpenMessage(buffer, &label, &config)) {
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000238 RTC_LOG(LS_WARNING) << "Failed to parse the OPEN message for sid "
239 << params.sid;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100240 return true;
241 }
242 config.open_handshake_role = InternalDataChannelInit::kAcker;
243 OnDataChannelOpenMessage(label, config);
244 return true;
245 }
246 return false;
247}
248
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100249void DataChannelController::OnDataChannelOpenMessage(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100250 const std::string& label,
251 const InternalDataChannelInit& config) {
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700252 rtc::scoped_refptr<DataChannelInterface> channel(
253 InternalCreateDataChannelWithProxy(label, &config));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100254 if (!channel.get()) {
255 RTC_LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
256 return;
257 }
258
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700259 pc_->Observer()->OnDataChannel(std::move(channel));
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100260 pc_->NoteDataAddedEvent();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100261}
262
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700263rtc::scoped_refptr<DataChannelInterface>
264DataChannelController::InternalCreateDataChannelWithProxy(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100265 const std::string& label,
266 const InternalDataChannelInit* config) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100267 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100268 if (pc_->IsClosed()) {
269 return nullptr;
270 }
Florent Castelli516e2842021-04-19 15:29:50 +0200271
272 rtc::scoped_refptr<SctpDataChannel> channel =
273 InternalCreateSctpDataChannel(label, config);
274 if (channel) {
275 return SctpDataChannel::CreateProxy(channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100276 }
277
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700278 return nullptr;
279}
280
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700281rtc::scoped_refptr<SctpDataChannel>
282DataChannelController::InternalCreateSctpDataChannel(
283 const std::string& label,
284 const InternalDataChannelInit* config) {
285 RTC_DCHECK_RUN_ON(signaling_thread());
286 InternalDataChannelInit new_config =
287 config ? (*config) : InternalDataChannelInit();
288 if (new_config.id < 0) {
289 rtc::SSLRole role;
290 if ((pc_->GetSctpSslRole(&role)) &&
291 !sid_allocator_.AllocateSid(role, &new_config.id)) {
292 RTC_LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
293 return nullptr;
294 }
295 } else if (!sid_allocator_.ReserveSid(new_config.id)) {
296 RTC_LOG(LS_ERROR) << "Failed to create a SCTP data channel "
297 "because the id is already in use or out of range.";
298 return nullptr;
299 }
300 rtc::scoped_refptr<SctpDataChannel> channel(SctpDataChannel::Create(
301 this, label, new_config, signaling_thread(), network_thread()));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100302 if (!channel) {
303 sid_allocator_.ReleaseSid(new_config.id);
304 return nullptr;
305 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700306 sctp_data_channels_.push_back(channel);
Harald Alvestrand5b84f382022-02-08 10:49:09 +0000307 channel->SignalClosed.connect(
308 pc_, &PeerConnectionInternal::OnSctpDataChannelClosed);
Mirko Bonadeie0bc8d22022-02-08 07:41:25 +0000309 SignalSctpDataChannelCreated_(channel.get());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100310 return channel;
311}
312
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100313void DataChannelController::AllocateSctpSids(rtc::SSLRole role) {
314 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700315 std::vector<rtc::scoped_refptr<SctpDataChannel>> channels_to_close;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100316 for (const auto& channel : sctp_data_channels_) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100317 if (channel->id() < 0) {
318 int sid;
319 if (!sid_allocator_.AllocateSid(role, &sid)) {
320 RTC_LOG(LS_ERROR) << "Failed to allocate SCTP sid, closing channel.";
321 channels_to_close.push_back(channel);
322 continue;
323 }
324 channel->SetSctpSid(sid);
325 }
326 }
327 // Since closing modifies the list of channels, we have to do the actual
328 // closing outside the loop.
329 for (const auto& channel : channels_to_close) {
Harald Alvestranddfbfb462019-12-08 05:55:43 +0100330 channel->CloseAbruptlyWithDataChannelFailure("Failed to allocate SCTP SID");
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100331 }
332}
333
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700334void DataChannelController::OnSctpDataChannelClosed(SctpDataChannel* channel) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100335 RTC_DCHECK_RUN_ON(signaling_thread());
336 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end();
337 ++it) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100338 if (it->get() == channel) {
339 if (channel->id() >= 0) {
340 // After the closing procedure is done, it's safe to use this ID for
341 // another data channel.
342 sid_allocator_.ReleaseSid(channel->id());
343 }
344 // Since this method is triggered by a signal from the DataChannel,
345 // we can't free it directly here; we need to free it asynchronously.
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100346 sctp_data_channels_to_free_.push_back(*it);
347 sctp_data_channels_.erase(it);
Harald Alvestrand246724b2019-12-03 22:31:42 +0100348 signaling_thread()->PostTask(
Niels Möller236e36c2021-03-23 09:23:10 +0100349 ToQueuedTask([self = weak_factory_.GetWeakPtr()] {
Harald Alvestrand246724b2019-12-03 22:31:42 +0100350 if (self) {
351 RTC_DCHECK_RUN_ON(self->signaling_thread());
352 self->sctp_data_channels_to_free_.clear();
353 }
Niels Möller236e36c2021-03-23 09:23:10 +0100354 }));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100355 return;
356 }
357 }
358}
359
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200360void DataChannelController::OnTransportChannelClosed(RTCError error) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100361 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand7af57c62021-04-16 11:12:14 +0000362 // Use a temporary copy of the SCTP DataChannel list because the
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100363 // DataChannel may callback to us and try to modify the list.
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700364 std::vector<rtc::scoped_refptr<SctpDataChannel>> temp_sctp_dcs;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100365 temp_sctp_dcs.swap(sctp_data_channels_);
366 for (const auto& channel : temp_sctp_dcs) {
Florent Castellidcb9ffc2021-06-29 14:58:23 +0200367 channel->OnTransportChannelClosed(error);
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100368 }
369}
370
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200371DataChannelTransportInterface* DataChannelController::data_channel_transport()
372 const {
373 // TODO(bugs.webrtc.org/11547): Only allow this accessor to be called on the
374 // network thread.
375 // RTC_DCHECK_RUN_ON(network_thread());
376 return data_channel_transport_;
377}
378
379void DataChannelController::set_data_channel_transport(
380 DataChannelTransportInterface* transport) {
381 RTC_DCHECK_RUN_ON(network_thread());
382 data_channel_transport_ = transport;
383}
384
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200385bool DataChannelController::DataChannelSendData(
Florent Castellid95b1492021-05-10 11:29:56 +0200386 int sid,
387 const SendDataParams& params,
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200388 const rtc::CopyOnWriteBuffer& payload,
389 cricket::SendDataResult* result) {
390 // TODO(bugs.webrtc.org/11547): Expect method to be called on the network
391 // thread instead. Remove the Invoke() below and move assocated state to
392 // the network thread.
393 RTC_DCHECK_RUN_ON(signaling_thread());
394 RTC_DCHECK(data_channel_transport());
395
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200396 RTCError error = network_thread()->Invoke<RTCError>(
Florent Castellid95b1492021-05-10 11:29:56 +0200397 RTC_FROM_HERE, [this, sid, params, payload] {
398 return data_channel_transport()->SendData(sid, params, payload);
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200399 });
400
401 if (error.ok()) {
402 *result = cricket::SendDataResult::SDR_SUCCESS;
403 return true;
404 } else if (error.type() == RTCErrorType::RESOURCE_EXHAUSTED) {
405 // SCTP transport uses RESOURCE_EXHAUSTED when it's blocked.
406 // TODO(mellem): Stop using RTCError here and get rid of the mapping.
407 *result = cricket::SendDataResult::SDR_BLOCK;
408 return false;
409 }
410 *result = cricket::SendDataResult::SDR_ERROR;
411 return false;
412}
413
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200414void DataChannelController::NotifyDataChannelsOfTransportCreated() {
415 RTC_DCHECK_RUN_ON(network_thread());
Niels Möller236e36c2021-03-23 09:23:10 +0100416 signaling_thread()->PostTask(
417 ToQueuedTask([self = weak_factory_.GetWeakPtr()] {
418 if (self) {
419 RTC_DCHECK_RUN_ON(self->signaling_thread());
420 for (const auto& channel : self->sctp_data_channels_) {
421 channel->OnTransportChannelCreated();
422 }
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200423 }
Niels Möller236e36c2021-03-23 09:23:10 +0100424 }));
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200425}
426
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100427rtc::Thread* DataChannelController::network_thread() const {
428 return pc_->network_thread();
429}
430rtc::Thread* DataChannelController::signaling_thread() const {
431 return pc_->signaling_thread();
432}
433
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100434} // namespace webrtc