blob: a8a1491b7f8dd6f3ba1ccff33d53bd209acf409c [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
15#include "pc/peer_connection.h"
16#include "pc/sctp_utils.h"
17
18namespace webrtc {
19
Harald Alvestrand05e4d082019-12-03 14:04:21 +010020bool DataChannelController::HasDataChannels() const {
21 RTC_DCHECK_RUN_ON(signaling_thread());
22 return !rtp_data_channels_.empty() || !sctp_data_channels_.empty();
23}
24
25bool DataChannelController::SendData(const cricket::SendDataParams& params,
26 const rtc::CopyOnWriteBuffer& payload,
27 cricket::SendDataResult* result) {
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +020028 if (data_channel_transport())
29 return DataChannelSendData(params, payload, result);
30 if (rtp_data_channel())
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010031 return rtp_data_channel()->SendData(params, payload, result);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010032 RTC_LOG(LS_ERROR) << "SendData called before transport is ready";
33 return false;
34}
35
Harald Alvestrand05e4d082019-12-03 14:04:21 +010036bool DataChannelController::ConnectDataChannel(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010037 DataChannel* webrtc_data_channel) {
38 RTC_DCHECK_RUN_ON(signaling_thread());
39 if (!rtp_data_channel() && !data_channel_transport()) {
40 // Don't log an error here, because DataChannels are expected to call
41 // ConnectDataChannel in this state. It's the only way to initially tell
42 // whether or not the underlying transport is ready.
43 return false;
44 }
45 if (data_channel_transport()) {
46 SignalDataChannelTransportWritable_s.connect(webrtc_data_channel,
47 &DataChannel::OnChannelReady);
48 SignalDataChannelTransportReceivedData_s.connect(
49 webrtc_data_channel, &DataChannel::OnDataReceived);
50 SignalDataChannelTransportChannelClosing_s.connect(
51 webrtc_data_channel, &DataChannel::OnClosingProcedureStartedRemotely);
52 SignalDataChannelTransportChannelClosed_s.connect(
53 webrtc_data_channel, &DataChannel::OnClosingProcedureComplete);
54 }
55 if (rtp_data_channel()) {
56 rtp_data_channel()->SignalReadyToSendData.connect(
57 webrtc_data_channel, &DataChannel::OnChannelReady);
58 rtp_data_channel()->SignalDataReceived.connect(
59 webrtc_data_channel, &DataChannel::OnDataReceived);
60 }
61 return true;
62}
63
Harald Alvestrand05e4d082019-12-03 14:04:21 +010064void DataChannelController::DisconnectDataChannel(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010065 DataChannel* webrtc_data_channel) {
66 RTC_DCHECK_RUN_ON(signaling_thread());
67 if (!rtp_data_channel() && !data_channel_transport()) {
68 RTC_LOG(LS_ERROR)
69 << "DisconnectDataChannel called when rtp_data_channel_ and "
70 "sctp_transport_ are NULL.";
71 return;
72 }
73 if (data_channel_transport()) {
74 SignalDataChannelTransportWritable_s.disconnect(webrtc_data_channel);
75 SignalDataChannelTransportReceivedData_s.disconnect(webrtc_data_channel);
76 SignalDataChannelTransportChannelClosing_s.disconnect(webrtc_data_channel);
77 SignalDataChannelTransportChannelClosed_s.disconnect(webrtc_data_channel);
78 }
79 if (rtp_data_channel()) {
80 rtp_data_channel()->SignalReadyToSendData.disconnect(webrtc_data_channel);
81 rtp_data_channel()->SignalDataReceived.disconnect(webrtc_data_channel);
82 }
83}
84
Harald Alvestrand05e4d082019-12-03 14:04:21 +010085void DataChannelController::AddSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010086 if (data_channel_transport()) {
87 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
88 if (data_channel_transport()) {
89 data_channel_transport()->OpenChannel(sid);
90 }
91 });
92 }
93}
94
Harald Alvestrand05e4d082019-12-03 14:04:21 +010095void DataChannelController::RemoveSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010096 if (data_channel_transport()) {
97 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
98 if (data_channel_transport()) {
99 data_channel_transport()->CloseChannel(sid);
100 }
101 });
102 }
103}
104
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100105bool DataChannelController::ReadyToSendData() const {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100106 RTC_DCHECK_RUN_ON(signaling_thread());
107 return (rtp_data_channel() && rtp_data_channel()->ready_to_send_data()) ||
108 (data_channel_transport() && data_channel_transport_ready_to_send_);
109}
110
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100111void DataChannelController::OnDataReceived(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100112 int channel_id,
113 DataMessageType type,
114 const rtc::CopyOnWriteBuffer& buffer) {
115 RTC_DCHECK_RUN_ON(network_thread());
116 cricket::ReceiveDataParams params;
117 params.sid = channel_id;
118 params.type = ToCricketDataMessageType(type);
119 data_channel_transport_invoker_->AsyncInvoke<void>(
120 RTC_FROM_HERE, signaling_thread(), [this, params, buffer] {
121 RTC_DCHECK_RUN_ON(signaling_thread());
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200122 // TODO(bugs.webrtc.org/11547): The data being received should be
123 // delivered on the network thread. The way HandleOpenMessage_s works
124 // right now is that it's called for all types of buffers and operates
125 // as a selector function. Change this so that it's only called for
126 // buffers that it should be able to handle. Once we do that, we can
127 // deliver all other buffers on the network thread (change
128 // SignalDataChannelTransportReceivedData_s to
129 // SignalDataChannelTransportReceivedData_n).
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100130 if (!HandleOpenMessage_s(params, buffer)) {
131 SignalDataChannelTransportReceivedData_s(params, buffer);
132 }
133 });
134}
135
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100136void DataChannelController::OnChannelClosing(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100137 RTC_DCHECK_RUN_ON(network_thread());
138 data_channel_transport_invoker_->AsyncInvoke<void>(
139 RTC_FROM_HERE, signaling_thread(), [this, channel_id] {
140 RTC_DCHECK_RUN_ON(signaling_thread());
141 SignalDataChannelTransportChannelClosing_s(channel_id);
142 });
143}
144
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100145void DataChannelController::OnChannelClosed(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100146 RTC_DCHECK_RUN_ON(network_thread());
147 data_channel_transport_invoker_->AsyncInvoke<void>(
148 RTC_FROM_HERE, signaling_thread(), [this, channel_id] {
149 RTC_DCHECK_RUN_ON(signaling_thread());
150 SignalDataChannelTransportChannelClosed_s(channel_id);
151 });
152}
153
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100154void DataChannelController::OnReadyToSend() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100155 RTC_DCHECK_RUN_ON(network_thread());
156 data_channel_transport_invoker_->AsyncInvoke<void>(
157 RTC_FROM_HERE, signaling_thread(), [this] {
158 RTC_DCHECK_RUN_ON(signaling_thread());
159 data_channel_transport_ready_to_send_ = true;
160 SignalDataChannelTransportWritable_s(
161 data_channel_transport_ready_to_send_);
162 });
163}
164
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100165void DataChannelController::OnTransportClosed() {
166 RTC_DCHECK_RUN_ON(network_thread());
167 data_channel_transport_invoker_->AsyncInvoke<void>(
168 RTC_FROM_HERE, signaling_thread(), [this] {
169 RTC_DCHECK_RUN_ON(signaling_thread());
170 OnTransportChannelClosed();
171 });
172}
173
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100174void DataChannelController::SetupDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100175 RTC_DCHECK_RUN_ON(network_thread());
176 data_channel_transport_invoker_ = std::make_unique<rtc::AsyncInvoker>();
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200177
178 // There's a new data channel transport. This needs to be signaled to the
179 // |sctp_data_channels_| so that they can reopen and reconnect. This is
180 // 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());
186 data_channel_transport_invoker_ = nullptr;
187 if (data_channel_transport()) {
188 data_channel_transport()->SetDataSink(nullptr);
189 }
190 set_data_channel_transport(nullptr);
191}
192
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100193void DataChannelController::OnTransportChanged(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100194 DataChannelTransportInterface* new_data_channel_transport) {
195 RTC_DCHECK_RUN_ON(network_thread());
196 if (data_channel_transport() &&
197 data_channel_transport() != new_data_channel_transport) {
198 // Changed which data channel transport is used for |sctp_mid_| (eg. now
199 // it's bundled).
200 data_channel_transport()->SetDataSink(nullptr);
201 set_data_channel_transport(new_data_channel_transport);
202 if (new_data_channel_transport) {
203 new_data_channel_transport->SetDataSink(this);
204
205 // There's a new data channel transport. This needs to be signaled to the
206 // |sctp_data_channels_| so that they can reopen and reconnect. This is
207 // necessary when bundling is applied.
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200208 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100209 }
210 }
211}
212
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200213std::vector<DataChannel::Stats> DataChannelController::GetDataChannelStats()
214 const {
215 RTC_DCHECK_RUN_ON(signaling_thread());
216 std::vector<DataChannel::Stats> stats;
217 stats.reserve(sctp_data_channels_.size());
218 for (const auto& channel : sctp_data_channels_)
219 stats.push_back(channel->GetStats());
220 return stats;
221}
222
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100223bool DataChannelController::HandleOpenMessage_s(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100224 const cricket::ReceiveDataParams& params,
225 const rtc::CopyOnWriteBuffer& buffer) {
226 if (params.type == cricket::DMT_CONTROL && IsOpenMessage(buffer)) {
227 // Received OPEN message; parse and signal that a new data channel should
228 // be created.
229 std::string label;
230 InternalDataChannelInit config;
231 config.id = params.ssrc;
232 if (!ParseDataChannelOpenMessage(buffer, &label, &config)) {
233 RTC_LOG(LS_WARNING) << "Failed to parse the OPEN message for ssrc "
234 << params.ssrc;
235 return true;
236 }
237 config.open_handshake_role = InternalDataChannelInit::kAcker;
238 OnDataChannelOpenMessage(label, config);
239 return true;
240 }
241 return false;
242}
243
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100244void DataChannelController::OnDataChannelOpenMessage(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100245 const std::string& label,
246 const InternalDataChannelInit& config) {
247 rtc::scoped_refptr<DataChannel> channel(
248 InternalCreateDataChannel(label, &config));
249 if (!channel.get()) {
250 RTC_LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
251 return;
252 }
253
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200254 // TODO(bugs.webrtc.org/11547): Inject the network thread as well.
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100255 rtc::scoped_refptr<DataChannelInterface> proxy_channel =
256 DataChannelProxy::Create(signaling_thread(), channel);
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100257 pc_->Observer()->OnDataChannel(std::move(proxy_channel));
258 pc_->NoteDataAddedEvent();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100259}
260
261rtc::scoped_refptr<DataChannel>
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100262DataChannelController::InternalCreateDataChannel(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100263 const std::string& label,
264 const InternalDataChannelInit* config) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100265 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100266 if (pc_->IsClosed()) {
267 return nullptr;
268 }
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100269 if (data_channel_type_ == cricket::DCT_NONE) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100270 RTC_LOG(LS_ERROR)
271 << "InternalCreateDataChannel: Data is not supported in this call.";
272 return nullptr;
273 }
274 InternalDataChannelInit new_config =
275 config ? (*config) : InternalDataChannelInit();
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100276 if (DataChannel::IsSctpLike(data_channel_type_)) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100277 if (new_config.id < 0) {
278 rtc::SSLRole role;
279 if ((pc_->GetSctpSslRole(&role)) &&
280 !sid_allocator_.AllocateSid(role, &new_config.id)) {
281 RTC_LOG(LS_ERROR)
282 << "No id can be allocated for the SCTP data channel.";
283 return nullptr;
284 }
285 } else if (!sid_allocator_.ReserveSid(new_config.id)) {
286 RTC_LOG(LS_ERROR) << "Failed to create a SCTP data channel "
287 "because the id is already in use or out of range.";
288 return nullptr;
289 }
290 }
291
292 rtc::scoped_refptr<DataChannel> channel(
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200293 DataChannel::Create(this, data_channel_type(), label, new_config,
294 signaling_thread(), network_thread()));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100295 if (!channel) {
296 sid_allocator_.ReleaseSid(new_config.id);
297 return nullptr;
298 }
299
300 if (channel->data_channel_type() == cricket::DCT_RTP) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100301 if (rtp_data_channels_.find(channel->label()) != rtp_data_channels_.end()) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100302 RTC_LOG(LS_ERROR) << "DataChannel with label " << channel->label()
303 << " already exists.";
304 return nullptr;
305 }
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100306 rtp_data_channels_[channel->label()] = channel;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100307 } else {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100308 RTC_DCHECK(DataChannel::IsSctpLike(data_channel_type_));
309 sctp_data_channels_.push_back(channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100310 channel->SignalClosed.connect(pc_,
311 &PeerConnection::OnSctpDataChannelClosed);
312 }
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100313 SignalDataChannelCreated_(channel.get());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100314 return channel;
315}
316
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100317void DataChannelController::AllocateSctpSids(rtc::SSLRole role) {
318 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100319 std::vector<rtc::scoped_refptr<DataChannel>> channels_to_close;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100320 for (const auto& channel : sctp_data_channels_) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100321 if (channel->id() < 0) {
322 int sid;
323 if (!sid_allocator_.AllocateSid(role, &sid)) {
324 RTC_LOG(LS_ERROR) << "Failed to allocate SCTP sid, closing channel.";
325 channels_to_close.push_back(channel);
326 continue;
327 }
328 channel->SetSctpSid(sid);
329 }
330 }
331 // Since closing modifies the list of channels, we have to do the actual
332 // closing outside the loop.
333 for (const auto& channel : channels_to_close) {
Harald Alvestranddfbfb462019-12-08 05:55:43 +0100334 channel->CloseAbruptlyWithDataChannelFailure("Failed to allocate SCTP SID");
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100335 }
336}
337
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100338void DataChannelController::OnSctpDataChannelClosed(DataChannel* channel) {
339 RTC_DCHECK_RUN_ON(signaling_thread());
340 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end();
341 ++it) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100342 if (it->get() == channel) {
343 if (channel->id() >= 0) {
344 // After the closing procedure is done, it's safe to use this ID for
345 // another data channel.
346 sid_allocator_.ReleaseSid(channel->id());
347 }
348 // Since this method is triggered by a signal from the DataChannel,
349 // we can't free it directly here; we need to free it asynchronously.
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100350 sctp_data_channels_to_free_.push_back(*it);
351 sctp_data_channels_.erase(it);
Harald Alvestrand246724b2019-12-03 22:31:42 +0100352 signaling_thread()->PostTask(
353 RTC_FROM_HERE, [self = weak_factory_.GetWeakPtr()] {
354 if (self) {
355 RTC_DCHECK_RUN_ON(self->signaling_thread());
356 self->sctp_data_channels_to_free_.clear();
357 }
358 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100359 return;
360 }
361 }
362}
363
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100364void DataChannelController::OnTransportChannelClosed() {
365 RTC_DCHECK_RUN_ON(signaling_thread());
366 // Use a temporary copy of the RTP/SCTP DataChannel list because the
367 // DataChannel may callback to us and try to modify the list.
368 std::map<std::string, rtc::scoped_refptr<DataChannel>> temp_rtp_dcs;
369 temp_rtp_dcs.swap(rtp_data_channels_);
370 for (const auto& kv : temp_rtp_dcs) {
371 kv.second->OnTransportChannelClosed();
372 }
373
374 std::vector<rtc::scoped_refptr<DataChannel>> temp_sctp_dcs;
375 temp_sctp_dcs.swap(sctp_data_channels_);
376 for (const auto& channel : temp_sctp_dcs) {
377 channel->OnTransportChannelClosed();
378 }
379}
380
381DataChannel* DataChannelController::FindDataChannelBySid(int sid) const {
382 RTC_DCHECK_RUN_ON(signaling_thread());
383 for (const auto& channel : sctp_data_channels_) {
384 if (channel->id() == sid) {
385 return channel;
386 }
387 }
388 return nullptr;
389}
390
391void DataChannelController::UpdateLocalRtpDataChannels(
392 const cricket::StreamParamsVec& streams) {
393 std::vector<std::string> existing_channels;
394
395 RTC_DCHECK_RUN_ON(signaling_thread());
396 // Find new and active data channels.
397 for (const cricket::StreamParams& params : streams) {
398 // |it->sync_label| is actually the data channel label. The reason is that
399 // we use the same naming of data channels as we do for
400 // MediaStreams and Tracks.
401 // For MediaStreams, the sync_label is the MediaStream label and the
402 // track label is the same as |streamid|.
403 const std::string& channel_label = params.first_stream_id();
404 auto data_channel_it = rtp_data_channels()->find(channel_label);
405 if (data_channel_it == rtp_data_channels()->end()) {
406 RTC_LOG(LS_ERROR) << "channel label not found";
407 continue;
408 }
409 // Set the SSRC the data channel should use for sending.
410 data_channel_it->second->SetSendSsrc(params.first_ssrc());
411 existing_channels.push_back(data_channel_it->first);
412 }
413
414 UpdateClosingRtpDataChannels(existing_channels, true);
415}
416
417void DataChannelController::UpdateRemoteRtpDataChannels(
418 const cricket::StreamParamsVec& streams) {
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200419 RTC_DCHECK_RUN_ON(signaling_thread());
420
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100421 std::vector<std::string> existing_channels;
422
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100423 // Find new and active data channels.
424 for (const cricket::StreamParams& params : streams) {
Artem Titovf0a34f22020-03-16 17:52:04 +0000425 // The data channel label is either the mslabel or the SSRC if the mslabel
426 // does not exist. Ex a=ssrc:444330170 mslabel:test1.
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100427 std::string label = params.first_stream_id().empty()
428 ? rtc::ToString(params.first_ssrc())
429 : params.first_stream_id();
430 auto data_channel_it = rtp_data_channels()->find(label);
431 if (data_channel_it == rtp_data_channels()->end()) {
432 // This is a new data channel.
433 CreateRemoteRtpDataChannel(label, params.first_ssrc());
434 } else {
435 data_channel_it->second->SetReceiveSsrc(params.first_ssrc());
436 }
437 existing_channels.push_back(label);
438 }
439
440 UpdateClosingRtpDataChannels(existing_channels, false);
441}
442
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200443cricket::DataChannelType DataChannelController::data_channel_type() const {
444 // TODO(bugs.webrtc.org/9987): Should be restricted to the signaling thread.
445 // RTC_DCHECK_RUN_ON(signaling_thread());
446 return data_channel_type_;
447}
448
449void DataChannelController::set_data_channel_type(
450 cricket::DataChannelType type) {
451 RTC_DCHECK_RUN_ON(signaling_thread());
452 data_channel_type_ = type;
453}
454
455DataChannelTransportInterface* DataChannelController::data_channel_transport()
456 const {
457 // TODO(bugs.webrtc.org/11547): Only allow this accessor to be called on the
458 // network thread.
459 // RTC_DCHECK_RUN_ON(network_thread());
460 return data_channel_transport_;
461}
462
463void DataChannelController::set_data_channel_transport(
464 DataChannelTransportInterface* transport) {
465 RTC_DCHECK_RUN_ON(network_thread());
466 data_channel_transport_ = transport;
467}
468
469const std::map<std::string, rtc::scoped_refptr<DataChannel>>*
470DataChannelController::rtp_data_channels() const {
471 RTC_DCHECK_RUN_ON(signaling_thread());
472 return &rtp_data_channels_;
473}
474
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100475void DataChannelController::UpdateClosingRtpDataChannels(
476 const std::vector<std::string>& active_channels,
477 bool is_local_update) {
478 auto it = rtp_data_channels_.begin();
479 while (it != rtp_data_channels_.end()) {
480 DataChannel* data_channel = it->second;
481 if (absl::c_linear_search(active_channels, data_channel->label())) {
482 ++it;
483 continue;
484 }
485
486 if (is_local_update) {
487 data_channel->SetSendSsrc(0);
488 } else {
489 data_channel->RemotePeerRequestClose();
490 }
491
492 if (data_channel->state() == DataChannel::kClosed) {
493 rtp_data_channels_.erase(it);
494 it = rtp_data_channels_.begin();
495 } else {
496 ++it;
497 }
498 }
499}
500
501void DataChannelController::CreateRemoteRtpDataChannel(const std::string& label,
502 uint32_t remote_ssrc) {
503 rtc::scoped_refptr<DataChannel> channel(
504 InternalCreateDataChannel(label, nullptr));
505 if (!channel.get()) {
506 RTC_LOG(LS_WARNING) << "Remote peer requested a DataChannel but"
507 "CreateDataChannel failed.";
508 return;
509 }
510 channel->SetReceiveSsrc(remote_ssrc);
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200511 // TODO(bugs.webrtc.org/11547): Inject the network thread as well.
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100512 rtc::scoped_refptr<DataChannelInterface> proxy_channel =
513 DataChannelProxy::Create(signaling_thread(), channel);
514 pc_->Observer()->OnDataChannel(std::move(proxy_channel));
515}
516
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200517bool DataChannelController::DataChannelSendData(
518 const cricket::SendDataParams& params,
519 const rtc::CopyOnWriteBuffer& payload,
520 cricket::SendDataResult* result) {
521 // TODO(bugs.webrtc.org/11547): Expect method to be called on the network
522 // thread instead. Remove the Invoke() below and move assocated state to
523 // the network thread.
524 RTC_DCHECK_RUN_ON(signaling_thread());
525 RTC_DCHECK(data_channel_transport());
526
527 SendDataParams send_params;
528 send_params.type = ToWebrtcDataMessageType(params.type);
529 send_params.ordered = params.ordered;
530 if (params.max_rtx_count >= 0) {
531 send_params.max_rtx_count = params.max_rtx_count;
532 } else if (params.max_rtx_ms >= 0) {
533 send_params.max_rtx_ms = params.max_rtx_ms;
534 }
535
536 RTCError error = network_thread()->Invoke<RTCError>(
537 RTC_FROM_HERE, [this, params, send_params, payload] {
538 return data_channel_transport()->SendData(params.sid, send_params,
539 payload);
540 });
541
542 if (error.ok()) {
543 *result = cricket::SendDataResult::SDR_SUCCESS;
544 return true;
545 } else if (error.type() == RTCErrorType::RESOURCE_EXHAUSTED) {
546 // SCTP transport uses RESOURCE_EXHAUSTED when it's blocked.
547 // TODO(mellem): Stop using RTCError here and get rid of the mapping.
548 *result = cricket::SendDataResult::SDR_BLOCK;
549 return false;
550 }
551 *result = cricket::SendDataResult::SDR_ERROR;
552 return false;
553}
554
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200555void DataChannelController::NotifyDataChannelsOfTransportCreated() {
556 RTC_DCHECK_RUN_ON(network_thread());
557 data_channel_transport_invoker_->AsyncInvoke<void>(
558 RTC_FROM_HERE, signaling_thread(), [this] {
559 RTC_DCHECK_RUN_ON(signaling_thread());
560 for (const auto& channel : sctp_data_channels_) {
561 channel->OnTransportChannelCreated();
562 }
563 });
564}
565
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100566rtc::Thread* DataChannelController::network_thread() const {
567 return pc_->network_thread();
568}
569rtc::Thread* DataChannelController::signaling_thread() const {
570 return pc_->signaling_thread();
571}
572
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100573} // namespace webrtc