blob: 9f0a490a0998d5e9b1e35c4a3f06d29a2854f174 [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
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000013#include <algorithm>
Harald Alvestrand05e4d082019-12-03 14:04:21 +010014#include <utility>
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010015
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000016#include "absl/algorithm/container.h"
17#include "absl/types/optional.h"
18#include "api/peer_connection_interface.h"
19#include "api/rtc_error.h"
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010020#include "pc/peer_connection.h"
21#include "pc/sctp_utils.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000022#include "rtc_base/location.h"
23#include "rtc_base/logging.h"
24#include "rtc_base/string_encode.h"
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010025
26namespace webrtc {
27
Harald Alvestrand05e4d082019-12-03 14:04:21 +010028bool DataChannelController::HasDataChannels() const {
29 RTC_DCHECK_RUN_ON(signaling_thread());
30 return !rtp_data_channels_.empty() || !sctp_data_channels_.empty();
31}
32
33bool DataChannelController::SendData(const cricket::SendDataParams& params,
34 const rtc::CopyOnWriteBuffer& payload,
35 cricket::SendDataResult* result) {
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +020036 if (data_channel_transport())
37 return DataChannelSendData(params, payload, result);
38 if (rtp_data_channel())
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010039 return rtp_data_channel()->SendData(params, payload, result);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010040 RTC_LOG(LS_ERROR) << "SendData called before transport is ready";
41 return false;
42}
43
Harald Alvestrand05e4d082019-12-03 14:04:21 +010044bool DataChannelController::ConnectDataChannel(
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070045 RtpDataChannel* webrtc_data_channel) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010046 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070047 if (!rtp_data_channel()) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010048 // Don't log an error here, because DataChannels are expected to call
49 // ConnectDataChannel in this state. It's the only way to initially tell
50 // whether or not the underlying transport is ready.
51 return false;
52 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070053 rtp_data_channel()->SignalReadyToSendData.connect(
54 webrtc_data_channel, &RtpDataChannel::OnChannelReady);
55 rtp_data_channel()->SignalDataReceived.connect(
56 webrtc_data_channel, &RtpDataChannel::OnDataReceived);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010057 return true;
58}
59
Harald Alvestrand05e4d082019-12-03 14:04:21 +010060void DataChannelController::DisconnectDataChannel(
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070061 RtpDataChannel* webrtc_data_channel) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010062 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070063 if (!rtp_data_channel()) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010064 RTC_LOG(LS_ERROR)
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070065 << "DisconnectDataChannel called when rtp_data_channel_ is NULL.";
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010066 return;
67 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070068 rtp_data_channel()->SignalReadyToSendData.disconnect(webrtc_data_channel);
69 rtp_data_channel()->SignalDataReceived.disconnect(webrtc_data_channel);
70}
71
72bool DataChannelController::ConnectDataChannel(
73 SctpDataChannel* webrtc_data_channel) {
74 RTC_DCHECK_RUN_ON(signaling_thread());
75 if (!data_channel_transport()) {
76 // Don't log an error here, because DataChannels are expected to call
77 // ConnectDataChannel in this state. It's the only way to initially tell
78 // whether or not the underlying transport is ready.
79 return false;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010080 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070081 SignalDataChannelTransportWritable_s.connect(
82 webrtc_data_channel, &SctpDataChannel::OnTransportReady);
83 SignalDataChannelTransportReceivedData_s.connect(
84 webrtc_data_channel, &SctpDataChannel::OnDataReceived);
85 SignalDataChannelTransportChannelClosing_s.connect(
86 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureStartedRemotely);
87 SignalDataChannelTransportChannelClosed_s.connect(
88 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureComplete);
89 return true;
90}
91
92void DataChannelController::DisconnectDataChannel(
93 SctpDataChannel* webrtc_data_channel) {
94 RTC_DCHECK_RUN_ON(signaling_thread());
95 if (!data_channel_transport()) {
96 RTC_LOG(LS_ERROR)
97 << "DisconnectDataChannel called when sctp_transport_ is NULL.";
98 return;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010099 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700100 SignalDataChannelTransportWritable_s.disconnect(webrtc_data_channel);
101 SignalDataChannelTransportReceivedData_s.disconnect(webrtc_data_channel);
102 SignalDataChannelTransportChannelClosing_s.disconnect(webrtc_data_channel);
103 SignalDataChannelTransportChannelClosed_s.disconnect(webrtc_data_channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100104}
105
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100106void DataChannelController::AddSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100107 if (data_channel_transport()) {
108 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
109 if (data_channel_transport()) {
110 data_channel_transport()->OpenChannel(sid);
111 }
112 });
113 }
114}
115
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100116void DataChannelController::RemoveSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100117 if (data_channel_transport()) {
118 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
119 if (data_channel_transport()) {
120 data_channel_transport()->CloseChannel(sid);
121 }
122 });
123 }
124}
125
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100126bool DataChannelController::ReadyToSendData() const {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100127 RTC_DCHECK_RUN_ON(signaling_thread());
128 return (rtp_data_channel() && rtp_data_channel()->ready_to_send_data()) ||
129 (data_channel_transport() && data_channel_transport_ready_to_send_);
130}
131
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100132void DataChannelController::OnDataReceived(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100133 int channel_id,
134 DataMessageType type,
135 const rtc::CopyOnWriteBuffer& buffer) {
136 RTC_DCHECK_RUN_ON(network_thread());
137 cricket::ReceiveDataParams params;
138 params.sid = channel_id;
139 params.type = ToCricketDataMessageType(type);
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200140 data_channel_transport_invoker_.AsyncInvoke<void>(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100141 RTC_FROM_HERE, signaling_thread(), [this, params, buffer] {
142 RTC_DCHECK_RUN_ON(signaling_thread());
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200143 // TODO(bugs.webrtc.org/11547): The data being received should be
144 // delivered on the network thread. The way HandleOpenMessage_s works
145 // right now is that it's called for all types of buffers and operates
146 // as a selector function. Change this so that it's only called for
147 // buffers that it should be able to handle. Once we do that, we can
148 // deliver all other buffers on the network thread (change
149 // SignalDataChannelTransportReceivedData_s to
150 // SignalDataChannelTransportReceivedData_n).
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100151 if (!HandleOpenMessage_s(params, buffer)) {
152 SignalDataChannelTransportReceivedData_s(params, buffer);
153 }
154 });
155}
156
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100157void DataChannelController::OnChannelClosing(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100158 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200159 data_channel_transport_invoker_.AsyncInvoke<void>(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100160 RTC_FROM_HERE, signaling_thread(), [this, channel_id] {
161 RTC_DCHECK_RUN_ON(signaling_thread());
162 SignalDataChannelTransportChannelClosing_s(channel_id);
163 });
164}
165
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100166void DataChannelController::OnChannelClosed(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100167 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200168 data_channel_transport_invoker_.AsyncInvoke<void>(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100169 RTC_FROM_HERE, signaling_thread(), [this, channel_id] {
170 RTC_DCHECK_RUN_ON(signaling_thread());
171 SignalDataChannelTransportChannelClosed_s(channel_id);
172 });
173}
174
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100175void DataChannelController::OnReadyToSend() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100176 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200177 data_channel_transport_invoker_.AsyncInvoke<void>(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100178 RTC_FROM_HERE, signaling_thread(), [this] {
179 RTC_DCHECK_RUN_ON(signaling_thread());
180 data_channel_transport_ready_to_send_ = true;
181 SignalDataChannelTransportWritable_s(
182 data_channel_transport_ready_to_send_);
183 });
184}
185
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100186void DataChannelController::OnTransportClosed() {
187 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200188 data_channel_transport_invoker_.AsyncInvoke<void>(
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100189 RTC_FROM_HERE, signaling_thread(), [this] {
190 RTC_DCHECK_RUN_ON(signaling_thread());
191 OnTransportChannelClosed();
192 });
193}
194
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100195void DataChannelController::SetupDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100196 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200197
198 // There's a new data channel transport. This needs to be signaled to the
199 // |sctp_data_channels_| so that they can reopen and reconnect. This is
200 // necessary when bundling is applied.
201 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100202}
203
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100204void DataChannelController::TeardownDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100205 RTC_DCHECK_RUN_ON(network_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100206 if (data_channel_transport()) {
207 data_channel_transport()->SetDataSink(nullptr);
208 }
209 set_data_channel_transport(nullptr);
210}
211
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100212void DataChannelController::OnTransportChanged(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100213 DataChannelTransportInterface* new_data_channel_transport) {
214 RTC_DCHECK_RUN_ON(network_thread());
215 if (data_channel_transport() &&
216 data_channel_transport() != new_data_channel_transport) {
217 // Changed which data channel transport is used for |sctp_mid_| (eg. now
218 // it's bundled).
219 data_channel_transport()->SetDataSink(nullptr);
220 set_data_channel_transport(new_data_channel_transport);
221 if (new_data_channel_transport) {
222 new_data_channel_transport->SetDataSink(this);
223
224 // There's a new data channel transport. This needs to be signaled to the
225 // |sctp_data_channels_| so that they can reopen and reconnect. This is
226 // necessary when bundling is applied.
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200227 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100228 }
229 }
230}
231
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700232std::vector<DataChannelStats> DataChannelController::GetDataChannelStats()
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200233 const {
234 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700235 std::vector<DataChannelStats> stats;
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200236 stats.reserve(sctp_data_channels_.size());
237 for (const auto& channel : sctp_data_channels_)
238 stats.push_back(channel->GetStats());
239 return stats;
240}
241
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100242bool DataChannelController::HandleOpenMessage_s(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100243 const cricket::ReceiveDataParams& params,
244 const rtc::CopyOnWriteBuffer& buffer) {
245 if (params.type == cricket::DMT_CONTROL && IsOpenMessage(buffer)) {
246 // Received OPEN message; parse and signal that a new data channel should
247 // be created.
248 std::string label;
249 InternalDataChannelInit config;
250 config.id = params.ssrc;
251 if (!ParseDataChannelOpenMessage(buffer, &label, &config)) {
252 RTC_LOG(LS_WARNING) << "Failed to parse the OPEN message for ssrc "
253 << params.ssrc;
254 return true;
255 }
256 config.open_handshake_role = InternalDataChannelInit::kAcker;
257 OnDataChannelOpenMessage(label, config);
258 return true;
259 }
260 return false;
261}
262
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100263void DataChannelController::OnDataChannelOpenMessage(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100264 const std::string& label,
265 const InternalDataChannelInit& config) {
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700266 rtc::scoped_refptr<DataChannelInterface> channel(
267 InternalCreateDataChannelWithProxy(label, &config));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100268 if (!channel.get()) {
269 RTC_LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
270 return;
271 }
272
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700273 pc_->Observer()->OnDataChannel(std::move(channel));
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100274 pc_->NoteDataAddedEvent();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100275}
276
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700277rtc::scoped_refptr<DataChannelInterface>
278DataChannelController::InternalCreateDataChannelWithProxy(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100279 const std::string& label,
280 const InternalDataChannelInit* config) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100281 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100282 if (pc_->IsClosed()) {
283 return nullptr;
284 }
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100285 if (data_channel_type_ == cricket::DCT_NONE) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100286 RTC_LOG(LS_ERROR)
287 << "InternalCreateDataChannel: Data is not supported in this call.";
288 return nullptr;
289 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700290 if (IsSctpLike(data_channel_type())) {
291 rtc::scoped_refptr<SctpDataChannel> channel =
292 InternalCreateSctpDataChannel(label, config);
293 if (channel) {
294 return SctpDataChannel::CreateProxy(channel);
295 }
296 } else if (data_channel_type() == cricket::DCT_RTP) {
297 rtc::scoped_refptr<RtpDataChannel> channel =
298 InternalCreateRtpDataChannel(label, config);
299 if (channel) {
300 return RtpDataChannel::CreateProxy(channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100301 }
302 }
303
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700304 return nullptr;
305}
306
307rtc::scoped_refptr<RtpDataChannel>
308DataChannelController::InternalCreateRtpDataChannel(
309 const std::string& label,
310 const DataChannelInit* config) {
311 RTC_DCHECK_RUN_ON(signaling_thread());
312 DataChannelInit new_config = config ? (*config) : DataChannelInit();
313 rtc::scoped_refptr<RtpDataChannel> channel(
314 RtpDataChannel::Create(this, label, new_config, signaling_thread()));
315 if (!channel) {
316 return nullptr;
317 }
318 if (rtp_data_channels_.find(channel->label()) != rtp_data_channels_.end()) {
319 RTC_LOG(LS_ERROR) << "DataChannel with label " << channel->label()
320 << " already exists.";
321 return nullptr;
322 }
323 rtp_data_channels_[channel->label()] = channel;
324 SignalRtpDataChannelCreated_(channel.get());
325 return channel;
326}
327
328rtc::scoped_refptr<SctpDataChannel>
329DataChannelController::InternalCreateSctpDataChannel(
330 const std::string& label,
331 const InternalDataChannelInit* config) {
332 RTC_DCHECK_RUN_ON(signaling_thread());
333 InternalDataChannelInit new_config =
334 config ? (*config) : InternalDataChannelInit();
335 if (new_config.id < 0) {
336 rtc::SSLRole role;
337 if ((pc_->GetSctpSslRole(&role)) &&
338 !sid_allocator_.AllocateSid(role, &new_config.id)) {
339 RTC_LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
340 return nullptr;
341 }
342 } else if (!sid_allocator_.ReserveSid(new_config.id)) {
343 RTC_LOG(LS_ERROR) << "Failed to create a SCTP data channel "
344 "because the id is already in use or out of range.";
345 return nullptr;
346 }
347 rtc::scoped_refptr<SctpDataChannel> channel(SctpDataChannel::Create(
348 this, label, new_config, signaling_thread(), network_thread()));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100349 if (!channel) {
350 sid_allocator_.ReleaseSid(new_config.id);
351 return nullptr;
352 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700353 sctp_data_channels_.push_back(channel);
354 channel->SignalClosed.connect(pc_, &PeerConnection::OnSctpDataChannelClosed);
355 SignalSctpDataChannelCreated_(channel.get());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100356 return channel;
357}
358
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100359void DataChannelController::AllocateSctpSids(rtc::SSLRole role) {
360 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700361 std::vector<rtc::scoped_refptr<SctpDataChannel>> channels_to_close;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100362 for (const auto& channel : sctp_data_channels_) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100363 if (channel->id() < 0) {
364 int sid;
365 if (!sid_allocator_.AllocateSid(role, &sid)) {
366 RTC_LOG(LS_ERROR) << "Failed to allocate SCTP sid, closing channel.";
367 channels_to_close.push_back(channel);
368 continue;
369 }
370 channel->SetSctpSid(sid);
371 }
372 }
373 // Since closing modifies the list of channels, we have to do the actual
374 // closing outside the loop.
375 for (const auto& channel : channels_to_close) {
Harald Alvestranddfbfb462019-12-08 05:55:43 +0100376 channel->CloseAbruptlyWithDataChannelFailure("Failed to allocate SCTP SID");
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100377 }
378}
379
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700380void DataChannelController::OnSctpDataChannelClosed(SctpDataChannel* channel) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100381 RTC_DCHECK_RUN_ON(signaling_thread());
382 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end();
383 ++it) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100384 if (it->get() == channel) {
385 if (channel->id() >= 0) {
386 // After the closing procedure is done, it's safe to use this ID for
387 // another data channel.
388 sid_allocator_.ReleaseSid(channel->id());
389 }
390 // Since this method is triggered by a signal from the DataChannel,
391 // we can't free it directly here; we need to free it asynchronously.
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100392 sctp_data_channels_to_free_.push_back(*it);
393 sctp_data_channels_.erase(it);
Harald Alvestrand246724b2019-12-03 22:31:42 +0100394 signaling_thread()->PostTask(
395 RTC_FROM_HERE, [self = weak_factory_.GetWeakPtr()] {
396 if (self) {
397 RTC_DCHECK_RUN_ON(self->signaling_thread());
398 self->sctp_data_channels_to_free_.clear();
399 }
400 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100401 return;
402 }
403 }
404}
405
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100406void DataChannelController::OnTransportChannelClosed() {
407 RTC_DCHECK_RUN_ON(signaling_thread());
408 // Use a temporary copy of the RTP/SCTP DataChannel list because the
409 // DataChannel may callback to us and try to modify the list.
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700410 std::map<std::string, rtc::scoped_refptr<RtpDataChannel>> temp_rtp_dcs;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100411 temp_rtp_dcs.swap(rtp_data_channels_);
412 for (const auto& kv : temp_rtp_dcs) {
413 kv.second->OnTransportChannelClosed();
414 }
415
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700416 std::vector<rtc::scoped_refptr<SctpDataChannel>> temp_sctp_dcs;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100417 temp_sctp_dcs.swap(sctp_data_channels_);
418 for (const auto& channel : temp_sctp_dcs) {
419 channel->OnTransportChannelClosed();
420 }
421}
422
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700423SctpDataChannel* DataChannelController::FindDataChannelBySid(int sid) const {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100424 RTC_DCHECK_RUN_ON(signaling_thread());
425 for (const auto& channel : sctp_data_channels_) {
426 if (channel->id() == sid) {
427 return channel;
428 }
429 }
430 return nullptr;
431}
432
433void DataChannelController::UpdateLocalRtpDataChannels(
434 const cricket::StreamParamsVec& streams) {
435 std::vector<std::string> existing_channels;
436
437 RTC_DCHECK_RUN_ON(signaling_thread());
438 // Find new and active data channels.
439 for (const cricket::StreamParams& params : streams) {
440 // |it->sync_label| is actually the data channel label. The reason is that
441 // we use the same naming of data channels as we do for
442 // MediaStreams and Tracks.
443 // For MediaStreams, the sync_label is the MediaStream label and the
444 // track label is the same as |streamid|.
445 const std::string& channel_label = params.first_stream_id();
446 auto data_channel_it = rtp_data_channels()->find(channel_label);
447 if (data_channel_it == rtp_data_channels()->end()) {
448 RTC_LOG(LS_ERROR) << "channel label not found";
449 continue;
450 }
451 // Set the SSRC the data channel should use for sending.
452 data_channel_it->second->SetSendSsrc(params.first_ssrc());
453 existing_channels.push_back(data_channel_it->first);
454 }
455
456 UpdateClosingRtpDataChannels(existing_channels, true);
457}
458
459void DataChannelController::UpdateRemoteRtpDataChannels(
460 const cricket::StreamParamsVec& streams) {
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200461 RTC_DCHECK_RUN_ON(signaling_thread());
462
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100463 std::vector<std::string> existing_channels;
464
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100465 // Find new and active data channels.
466 for (const cricket::StreamParams& params : streams) {
Artem Titovf0a34f22020-03-16 17:52:04 +0000467 // The data channel label is either the mslabel or the SSRC if the mslabel
468 // does not exist. Ex a=ssrc:444330170 mslabel:test1.
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100469 std::string label = params.first_stream_id().empty()
470 ? rtc::ToString(params.first_ssrc())
471 : params.first_stream_id();
472 auto data_channel_it = rtp_data_channels()->find(label);
473 if (data_channel_it == rtp_data_channels()->end()) {
474 // This is a new data channel.
475 CreateRemoteRtpDataChannel(label, params.first_ssrc());
476 } else {
477 data_channel_it->second->SetReceiveSsrc(params.first_ssrc());
478 }
479 existing_channels.push_back(label);
480 }
481
482 UpdateClosingRtpDataChannels(existing_channels, false);
483}
484
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200485cricket::DataChannelType DataChannelController::data_channel_type() const {
486 // TODO(bugs.webrtc.org/9987): Should be restricted to the signaling thread.
487 // RTC_DCHECK_RUN_ON(signaling_thread());
488 return data_channel_type_;
489}
490
491void DataChannelController::set_data_channel_type(
492 cricket::DataChannelType type) {
493 RTC_DCHECK_RUN_ON(signaling_thread());
494 data_channel_type_ = type;
495}
496
497DataChannelTransportInterface* DataChannelController::data_channel_transport()
498 const {
499 // TODO(bugs.webrtc.org/11547): Only allow this accessor to be called on the
500 // network thread.
501 // RTC_DCHECK_RUN_ON(network_thread());
502 return data_channel_transport_;
503}
504
505void DataChannelController::set_data_channel_transport(
506 DataChannelTransportInterface* transport) {
507 RTC_DCHECK_RUN_ON(network_thread());
508 data_channel_transport_ = transport;
509}
510
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700511const std::map<std::string, rtc::scoped_refptr<RtpDataChannel>>*
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200512DataChannelController::rtp_data_channels() const {
513 RTC_DCHECK_RUN_ON(signaling_thread());
514 return &rtp_data_channels_;
515}
516
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100517void DataChannelController::UpdateClosingRtpDataChannels(
518 const std::vector<std::string>& active_channels,
519 bool is_local_update) {
520 auto it = rtp_data_channels_.begin();
521 while (it != rtp_data_channels_.end()) {
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700522 RtpDataChannel* data_channel = it->second;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100523 if (absl::c_linear_search(active_channels, data_channel->label())) {
524 ++it;
525 continue;
526 }
527
528 if (is_local_update) {
529 data_channel->SetSendSsrc(0);
530 } else {
531 data_channel->RemotePeerRequestClose();
532 }
533
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700534 if (data_channel->state() == RtpDataChannel::kClosed) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100535 rtp_data_channels_.erase(it);
536 it = rtp_data_channels_.begin();
537 } else {
538 ++it;
539 }
540 }
541}
542
543void DataChannelController::CreateRemoteRtpDataChannel(const std::string& label,
544 uint32_t remote_ssrc) {
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700545 if (data_channel_type() != cricket::DCT_RTP) {
546 return;
547 }
548 rtc::scoped_refptr<RtpDataChannel> channel(
549 InternalCreateRtpDataChannel(label, nullptr));
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100550 if (!channel.get()) {
551 RTC_LOG(LS_WARNING) << "Remote peer requested a DataChannel but"
552 "CreateDataChannel failed.";
553 return;
554 }
555 channel->SetReceiveSsrc(remote_ssrc);
556 rtc::scoped_refptr<DataChannelInterface> proxy_channel =
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700557 RtpDataChannel::CreateProxy(std::move(channel));
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100558 pc_->Observer()->OnDataChannel(std::move(proxy_channel));
559}
560
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200561bool DataChannelController::DataChannelSendData(
562 const cricket::SendDataParams& params,
563 const rtc::CopyOnWriteBuffer& payload,
564 cricket::SendDataResult* result) {
565 // TODO(bugs.webrtc.org/11547): Expect method to be called on the network
566 // thread instead. Remove the Invoke() below and move assocated state to
567 // the network thread.
568 RTC_DCHECK_RUN_ON(signaling_thread());
569 RTC_DCHECK(data_channel_transport());
570
571 SendDataParams send_params;
572 send_params.type = ToWebrtcDataMessageType(params.type);
573 send_params.ordered = params.ordered;
574 if (params.max_rtx_count >= 0) {
575 send_params.max_rtx_count = params.max_rtx_count;
576 } else if (params.max_rtx_ms >= 0) {
577 send_params.max_rtx_ms = params.max_rtx_ms;
578 }
579
580 RTCError error = network_thread()->Invoke<RTCError>(
581 RTC_FROM_HERE, [this, params, send_params, payload] {
582 return data_channel_transport()->SendData(params.sid, send_params,
583 payload);
584 });
585
586 if (error.ok()) {
587 *result = cricket::SendDataResult::SDR_SUCCESS;
588 return true;
589 } else if (error.type() == RTCErrorType::RESOURCE_EXHAUSTED) {
590 // SCTP transport uses RESOURCE_EXHAUSTED when it's blocked.
591 // TODO(mellem): Stop using RTCError here and get rid of the mapping.
592 *result = cricket::SendDataResult::SDR_BLOCK;
593 return false;
594 }
595 *result = cricket::SendDataResult::SDR_ERROR;
596 return false;
597}
598
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200599void DataChannelController::NotifyDataChannelsOfTransportCreated() {
600 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200601 data_channel_transport_invoker_.AsyncInvoke<void>(
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200602 RTC_FROM_HERE, signaling_thread(), [this] {
603 RTC_DCHECK_RUN_ON(signaling_thread());
604 for (const auto& channel : sctp_data_channels_) {
605 channel->OnTransportChannelCreated();
606 }
607 });
608}
609
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100610rtc::Thread* DataChannelController::network_thread() const {
611 return pc_->network_thread();
612}
613rtc::Thread* DataChannelController::signaling_thread() const {
614 return pc_->signaling_thread();
615}
616
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100617} // namespace webrtc