blob: 9fabe13cc78d6ee218684d9ac6b2074b2132047e [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(
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070037 RtpDataChannel* webrtc_data_channel) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010038 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070039 if (!rtp_data_channel()) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010040 // 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 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070045 rtp_data_channel()->SignalReadyToSendData.connect(
46 webrtc_data_channel, &RtpDataChannel::OnChannelReady);
47 rtp_data_channel()->SignalDataReceived.connect(
48 webrtc_data_channel, &RtpDataChannel::OnDataReceived);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010049 return true;
50}
51
Harald Alvestrand05e4d082019-12-03 14:04:21 +010052void DataChannelController::DisconnectDataChannel(
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070053 RtpDataChannel* webrtc_data_channel) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010054 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070055 if (!rtp_data_channel()) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010056 RTC_LOG(LS_ERROR)
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070057 << "DisconnectDataChannel called when rtp_data_channel_ is NULL.";
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010058 return;
59 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070060 rtp_data_channel()->SignalReadyToSendData.disconnect(webrtc_data_channel);
61 rtp_data_channel()->SignalDataReceived.disconnect(webrtc_data_channel);
62}
63
64bool DataChannelController::ConnectDataChannel(
65 SctpDataChannel* webrtc_data_channel) {
66 RTC_DCHECK_RUN_ON(signaling_thread());
67 if (!data_channel_transport()) {
68 // Don't log an error here, because DataChannels are expected to call
69 // ConnectDataChannel in this state. It's the only way to initially tell
70 // whether or not the underlying transport is ready.
71 return false;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010072 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070073 SignalDataChannelTransportWritable_s.connect(
74 webrtc_data_channel, &SctpDataChannel::OnTransportReady);
75 SignalDataChannelTransportReceivedData_s.connect(
76 webrtc_data_channel, &SctpDataChannel::OnDataReceived);
77 SignalDataChannelTransportChannelClosing_s.connect(
78 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureStartedRemotely);
79 SignalDataChannelTransportChannelClosed_s.connect(
80 webrtc_data_channel, &SctpDataChannel::OnClosingProcedureComplete);
81 return true;
82}
83
84void DataChannelController::DisconnectDataChannel(
85 SctpDataChannel* webrtc_data_channel) {
86 RTC_DCHECK_RUN_ON(signaling_thread());
87 if (!data_channel_transport()) {
88 RTC_LOG(LS_ERROR)
89 << "DisconnectDataChannel called when sctp_transport_ is NULL.";
90 return;
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010091 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -070092 SignalDataChannelTransportWritable_s.disconnect(webrtc_data_channel);
93 SignalDataChannelTransportReceivedData_s.disconnect(webrtc_data_channel);
94 SignalDataChannelTransportChannelClosing_s.disconnect(webrtc_data_channel);
95 SignalDataChannelTransportChannelClosed_s.disconnect(webrtc_data_channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010096}
97
Harald Alvestrand05e4d082019-12-03 14:04:21 +010098void DataChannelController::AddSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +010099 if (data_channel_transport()) {
100 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
101 if (data_channel_transport()) {
102 data_channel_transport()->OpenChannel(sid);
103 }
104 });
105 }
106}
107
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100108void DataChannelController::RemoveSctpDataStream(int sid) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100109 if (data_channel_transport()) {
110 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
111 if (data_channel_transport()) {
112 data_channel_transport()->CloseChannel(sid);
113 }
114 });
115 }
116}
117
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100118bool DataChannelController::ReadyToSendData() const {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100119 RTC_DCHECK_RUN_ON(signaling_thread());
120 return (rtp_data_channel() && rtp_data_channel()->ready_to_send_data()) ||
121 (data_channel_transport() && data_channel_transport_ready_to_send_);
122}
123
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100124void DataChannelController::OnDataReceived(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100125 int channel_id,
126 DataMessageType type,
127 const rtc::CopyOnWriteBuffer& buffer) {
128 RTC_DCHECK_RUN_ON(network_thread());
129 cricket::ReceiveDataParams params;
130 params.sid = channel_id;
131 params.type = ToCricketDataMessageType(type);
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200132 data_channel_transport_invoker_.AsyncInvoke<void>(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100133 RTC_FROM_HERE, signaling_thread(), [this, params, buffer] {
134 RTC_DCHECK_RUN_ON(signaling_thread());
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200135 // TODO(bugs.webrtc.org/11547): The data being received should be
136 // delivered on the network thread. The way HandleOpenMessage_s works
137 // right now is that it's called for all types of buffers and operates
138 // as a selector function. Change this so that it's only called for
139 // buffers that it should be able to handle. Once we do that, we can
140 // deliver all other buffers on the network thread (change
141 // SignalDataChannelTransportReceivedData_s to
142 // SignalDataChannelTransportReceivedData_n).
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100143 if (!HandleOpenMessage_s(params, buffer)) {
144 SignalDataChannelTransportReceivedData_s(params, buffer);
145 }
146 });
147}
148
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100149void DataChannelController::OnChannelClosing(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100150 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200151 data_channel_transport_invoker_.AsyncInvoke<void>(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100152 RTC_FROM_HERE, signaling_thread(), [this, channel_id] {
153 RTC_DCHECK_RUN_ON(signaling_thread());
154 SignalDataChannelTransportChannelClosing_s(channel_id);
155 });
156}
157
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100158void DataChannelController::OnChannelClosed(int channel_id) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100159 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200160 data_channel_transport_invoker_.AsyncInvoke<void>(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100161 RTC_FROM_HERE, signaling_thread(), [this, channel_id] {
162 RTC_DCHECK_RUN_ON(signaling_thread());
163 SignalDataChannelTransportChannelClosed_s(channel_id);
164 });
165}
166
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100167void DataChannelController::OnReadyToSend() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100168 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200169 data_channel_transport_invoker_.AsyncInvoke<void>(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100170 RTC_FROM_HERE, signaling_thread(), [this] {
171 RTC_DCHECK_RUN_ON(signaling_thread());
172 data_channel_transport_ready_to_send_ = true;
173 SignalDataChannelTransportWritable_s(
174 data_channel_transport_ready_to_send_);
175 });
176}
177
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100178void DataChannelController::OnTransportClosed() {
179 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200180 data_channel_transport_invoker_.AsyncInvoke<void>(
Harald Alvestrand2697ac12019-12-16 10:37:04 +0100181 RTC_FROM_HERE, signaling_thread(), [this] {
182 RTC_DCHECK_RUN_ON(signaling_thread());
183 OnTransportChannelClosed();
184 });
185}
186
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100187void DataChannelController::SetupDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100188 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200189
190 // There's a new data channel transport. This needs to be signaled to the
191 // |sctp_data_channels_| so that they can reopen and reconnect. This is
192 // necessary when bundling is applied.
193 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100194}
195
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100196void DataChannelController::TeardownDataChannelTransport_n() {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100197 RTC_DCHECK_RUN_ON(network_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100198 if (data_channel_transport()) {
199 data_channel_transport()->SetDataSink(nullptr);
200 }
201 set_data_channel_transport(nullptr);
202}
203
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100204void DataChannelController::OnTransportChanged(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100205 DataChannelTransportInterface* new_data_channel_transport) {
206 RTC_DCHECK_RUN_ON(network_thread());
207 if (data_channel_transport() &&
208 data_channel_transport() != new_data_channel_transport) {
209 // Changed which data channel transport is used for |sctp_mid_| (eg. now
210 // it's bundled).
211 data_channel_transport()->SetDataSink(nullptr);
212 set_data_channel_transport(new_data_channel_transport);
213 if (new_data_channel_transport) {
214 new_data_channel_transport->SetDataSink(this);
215
216 // There's a new data channel transport. This needs to be signaled to the
217 // |sctp_data_channels_| so that they can reopen and reconnect. This is
218 // necessary when bundling is applied.
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200219 NotifyDataChannelsOfTransportCreated();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100220 }
221 }
222}
223
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700224std::vector<DataChannelStats> DataChannelController::GetDataChannelStats()
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200225 const {
226 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700227 std::vector<DataChannelStats> stats;
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200228 stats.reserve(sctp_data_channels_.size());
229 for (const auto& channel : sctp_data_channels_)
230 stats.push_back(channel->GetStats());
231 return stats;
232}
233
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100234bool DataChannelController::HandleOpenMessage_s(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100235 const cricket::ReceiveDataParams& params,
236 const rtc::CopyOnWriteBuffer& buffer) {
237 if (params.type == cricket::DMT_CONTROL && IsOpenMessage(buffer)) {
238 // Received OPEN message; parse and signal that a new data channel should
239 // be created.
240 std::string label;
241 InternalDataChannelInit config;
242 config.id = params.ssrc;
243 if (!ParseDataChannelOpenMessage(buffer, &label, &config)) {
244 RTC_LOG(LS_WARNING) << "Failed to parse the OPEN message for ssrc "
245 << params.ssrc;
246 return true;
247 }
248 config.open_handshake_role = InternalDataChannelInit::kAcker;
249 OnDataChannelOpenMessage(label, config);
250 return true;
251 }
252 return false;
253}
254
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100255void DataChannelController::OnDataChannelOpenMessage(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100256 const std::string& label,
257 const InternalDataChannelInit& config) {
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700258 rtc::scoped_refptr<DataChannelInterface> channel(
259 InternalCreateDataChannelWithProxy(label, &config));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100260 if (!channel.get()) {
261 RTC_LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
262 return;
263 }
264
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700265 pc_->Observer()->OnDataChannel(std::move(channel));
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100266 pc_->NoteDataAddedEvent();
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100267}
268
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700269rtc::scoped_refptr<DataChannelInterface>
270DataChannelController::InternalCreateDataChannelWithProxy(
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100271 const std::string& label,
272 const InternalDataChannelInit* config) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100273 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100274 if (pc_->IsClosed()) {
275 return nullptr;
276 }
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100277 if (data_channel_type_ == cricket::DCT_NONE) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100278 RTC_LOG(LS_ERROR)
279 << "InternalCreateDataChannel: Data is not supported in this call.";
280 return nullptr;
281 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700282 if (IsSctpLike(data_channel_type())) {
283 rtc::scoped_refptr<SctpDataChannel> channel =
284 InternalCreateSctpDataChannel(label, config);
285 if (channel) {
286 return SctpDataChannel::CreateProxy(channel);
287 }
288 } else if (data_channel_type() == cricket::DCT_RTP) {
289 rtc::scoped_refptr<RtpDataChannel> channel =
290 InternalCreateRtpDataChannel(label, config);
291 if (channel) {
292 return RtpDataChannel::CreateProxy(channel);
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100293 }
294 }
295
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700296 return nullptr;
297}
298
299rtc::scoped_refptr<RtpDataChannel>
300DataChannelController::InternalCreateRtpDataChannel(
301 const std::string& label,
302 const DataChannelInit* config) {
303 RTC_DCHECK_RUN_ON(signaling_thread());
304 DataChannelInit new_config = config ? (*config) : DataChannelInit();
305 rtc::scoped_refptr<RtpDataChannel> channel(
306 RtpDataChannel::Create(this, label, new_config, signaling_thread()));
307 if (!channel) {
308 return nullptr;
309 }
310 if (rtp_data_channels_.find(channel->label()) != rtp_data_channels_.end()) {
311 RTC_LOG(LS_ERROR) << "DataChannel with label " << channel->label()
312 << " already exists.";
313 return nullptr;
314 }
315 rtp_data_channels_[channel->label()] = channel;
316 SignalRtpDataChannelCreated_(channel.get());
317 return channel;
318}
319
320rtc::scoped_refptr<SctpDataChannel>
321DataChannelController::InternalCreateSctpDataChannel(
322 const std::string& label,
323 const InternalDataChannelInit* config) {
324 RTC_DCHECK_RUN_ON(signaling_thread());
325 InternalDataChannelInit new_config =
326 config ? (*config) : InternalDataChannelInit();
327 if (new_config.id < 0) {
328 rtc::SSLRole role;
329 if ((pc_->GetSctpSslRole(&role)) &&
330 !sid_allocator_.AllocateSid(role, &new_config.id)) {
331 RTC_LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
332 return nullptr;
333 }
334 } else if (!sid_allocator_.ReserveSid(new_config.id)) {
335 RTC_LOG(LS_ERROR) << "Failed to create a SCTP data channel "
336 "because the id is already in use or out of range.";
337 return nullptr;
338 }
339 rtc::scoped_refptr<SctpDataChannel> channel(SctpDataChannel::Create(
340 this, label, new_config, signaling_thread(), network_thread()));
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100341 if (!channel) {
342 sid_allocator_.ReleaseSid(new_config.id);
343 return nullptr;
344 }
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700345 sctp_data_channels_.push_back(channel);
346 channel->SignalClosed.connect(pc_, &PeerConnection::OnSctpDataChannelClosed);
347 SignalSctpDataChannelCreated_(channel.get());
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100348 return channel;
349}
350
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100351void DataChannelController::AllocateSctpSids(rtc::SSLRole role) {
352 RTC_DCHECK_RUN_ON(signaling_thread());
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700353 std::vector<rtc::scoped_refptr<SctpDataChannel>> channels_to_close;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100354 for (const auto& channel : sctp_data_channels_) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100355 if (channel->id() < 0) {
356 int sid;
357 if (!sid_allocator_.AllocateSid(role, &sid)) {
358 RTC_LOG(LS_ERROR) << "Failed to allocate SCTP sid, closing channel.";
359 channels_to_close.push_back(channel);
360 continue;
361 }
362 channel->SetSctpSid(sid);
363 }
364 }
365 // Since closing modifies the list of channels, we have to do the actual
366 // closing outside the loop.
367 for (const auto& channel : channels_to_close) {
Harald Alvestranddfbfb462019-12-08 05:55:43 +0100368 channel->CloseAbruptlyWithDataChannelFailure("Failed to allocate SCTP SID");
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100369 }
370}
371
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700372void DataChannelController::OnSctpDataChannelClosed(SctpDataChannel* channel) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100373 RTC_DCHECK_RUN_ON(signaling_thread());
374 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end();
375 ++it) {
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100376 if (it->get() == channel) {
377 if (channel->id() >= 0) {
378 // After the closing procedure is done, it's safe to use this ID for
379 // another data channel.
380 sid_allocator_.ReleaseSid(channel->id());
381 }
382 // Since this method is triggered by a signal from the DataChannel,
383 // we can't free it directly here; we need to free it asynchronously.
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100384 sctp_data_channels_to_free_.push_back(*it);
385 sctp_data_channels_.erase(it);
Harald Alvestrand246724b2019-12-03 22:31:42 +0100386 signaling_thread()->PostTask(
387 RTC_FROM_HERE, [self = weak_factory_.GetWeakPtr()] {
388 if (self) {
389 RTC_DCHECK_RUN_ON(self->signaling_thread());
390 self->sctp_data_channels_to_free_.clear();
391 }
392 });
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100393 return;
394 }
395 }
396}
397
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100398void DataChannelController::OnTransportChannelClosed() {
399 RTC_DCHECK_RUN_ON(signaling_thread());
400 // Use a temporary copy of the RTP/SCTP DataChannel list because the
401 // DataChannel may callback to us and try to modify the list.
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700402 std::map<std::string, rtc::scoped_refptr<RtpDataChannel>> temp_rtp_dcs;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100403 temp_rtp_dcs.swap(rtp_data_channels_);
404 for (const auto& kv : temp_rtp_dcs) {
405 kv.second->OnTransportChannelClosed();
406 }
407
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700408 std::vector<rtc::scoped_refptr<SctpDataChannel>> temp_sctp_dcs;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100409 temp_sctp_dcs.swap(sctp_data_channels_);
410 for (const auto& channel : temp_sctp_dcs) {
411 channel->OnTransportChannelClosed();
412 }
413}
414
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700415SctpDataChannel* DataChannelController::FindDataChannelBySid(int sid) const {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100416 RTC_DCHECK_RUN_ON(signaling_thread());
417 for (const auto& channel : sctp_data_channels_) {
418 if (channel->id() == sid) {
419 return channel;
420 }
421 }
422 return nullptr;
423}
424
425void DataChannelController::UpdateLocalRtpDataChannels(
426 const cricket::StreamParamsVec& streams) {
427 std::vector<std::string> existing_channels;
428
429 RTC_DCHECK_RUN_ON(signaling_thread());
430 // Find new and active data channels.
431 for (const cricket::StreamParams& params : streams) {
432 // |it->sync_label| is actually the data channel label. The reason is that
433 // we use the same naming of data channels as we do for
434 // MediaStreams and Tracks.
435 // For MediaStreams, the sync_label is the MediaStream label and the
436 // track label is the same as |streamid|.
437 const std::string& channel_label = params.first_stream_id();
438 auto data_channel_it = rtp_data_channels()->find(channel_label);
439 if (data_channel_it == rtp_data_channels()->end()) {
440 RTC_LOG(LS_ERROR) << "channel label not found";
441 continue;
442 }
443 // Set the SSRC the data channel should use for sending.
444 data_channel_it->second->SetSendSsrc(params.first_ssrc());
445 existing_channels.push_back(data_channel_it->first);
446 }
447
448 UpdateClosingRtpDataChannels(existing_channels, true);
449}
450
451void DataChannelController::UpdateRemoteRtpDataChannels(
452 const cricket::StreamParamsVec& streams) {
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200453 RTC_DCHECK_RUN_ON(signaling_thread());
454
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100455 std::vector<std::string> existing_channels;
456
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100457 // Find new and active data channels.
458 for (const cricket::StreamParams& params : streams) {
Artem Titovf0a34f22020-03-16 17:52:04 +0000459 // The data channel label is either the mslabel or the SSRC if the mslabel
460 // does not exist. Ex a=ssrc:444330170 mslabel:test1.
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100461 std::string label = params.first_stream_id().empty()
462 ? rtc::ToString(params.first_ssrc())
463 : params.first_stream_id();
464 auto data_channel_it = rtp_data_channels()->find(label);
465 if (data_channel_it == rtp_data_channels()->end()) {
466 // This is a new data channel.
467 CreateRemoteRtpDataChannel(label, params.first_ssrc());
468 } else {
469 data_channel_it->second->SetReceiveSsrc(params.first_ssrc());
470 }
471 existing_channels.push_back(label);
472 }
473
474 UpdateClosingRtpDataChannels(existing_channels, false);
475}
476
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200477cricket::DataChannelType DataChannelController::data_channel_type() const {
478 // TODO(bugs.webrtc.org/9987): Should be restricted to the signaling thread.
479 // RTC_DCHECK_RUN_ON(signaling_thread());
480 return data_channel_type_;
481}
482
483void DataChannelController::set_data_channel_type(
484 cricket::DataChannelType type) {
485 RTC_DCHECK_RUN_ON(signaling_thread());
486 data_channel_type_ = type;
487}
488
489DataChannelTransportInterface* DataChannelController::data_channel_transport()
490 const {
491 // TODO(bugs.webrtc.org/11547): Only allow this accessor to be called on the
492 // network thread.
493 // RTC_DCHECK_RUN_ON(network_thread());
494 return data_channel_transport_;
495}
496
497void DataChannelController::set_data_channel_transport(
498 DataChannelTransportInterface* transport) {
499 RTC_DCHECK_RUN_ON(network_thread());
500 data_channel_transport_ = transport;
501}
502
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700503const std::map<std::string, rtc::scoped_refptr<RtpDataChannel>>*
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200504DataChannelController::rtp_data_channels() const {
505 RTC_DCHECK_RUN_ON(signaling_thread());
506 return &rtp_data_channels_;
507}
508
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100509void DataChannelController::UpdateClosingRtpDataChannels(
510 const std::vector<std::string>& active_channels,
511 bool is_local_update) {
512 auto it = rtp_data_channels_.begin();
513 while (it != rtp_data_channels_.end()) {
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700514 RtpDataChannel* data_channel = it->second;
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100515 if (absl::c_linear_search(active_channels, data_channel->label())) {
516 ++it;
517 continue;
518 }
519
520 if (is_local_update) {
521 data_channel->SetSendSsrc(0);
522 } else {
523 data_channel->RemotePeerRequestClose();
524 }
525
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700526 if (data_channel->state() == RtpDataChannel::kClosed) {
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100527 rtp_data_channels_.erase(it);
528 it = rtp_data_channels_.begin();
529 } else {
530 ++it;
531 }
532 }
533}
534
535void DataChannelController::CreateRemoteRtpDataChannel(const std::string& label,
536 uint32_t remote_ssrc) {
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700537 if (data_channel_type() != cricket::DCT_RTP) {
538 return;
539 }
540 rtc::scoped_refptr<RtpDataChannel> channel(
541 InternalCreateRtpDataChannel(label, nullptr));
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100542 if (!channel.get()) {
543 RTC_LOG(LS_WARNING) << "Remote peer requested a DataChannel but"
544 "CreateDataChannel failed.";
545 return;
546 }
547 channel->SetReceiveSsrc(remote_ssrc);
548 rtc::scoped_refptr<DataChannelInterface> proxy_channel =
Taylor Brandstetter3a034e12020-07-09 15:32:34 -0700549 RtpDataChannel::CreateProxy(std::move(channel));
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100550 pc_->Observer()->OnDataChannel(std::move(proxy_channel));
551}
552
Tomas Gunnarsson7d3cfbf2020-06-15 13:47:42 +0200553bool DataChannelController::DataChannelSendData(
554 const cricket::SendDataParams& params,
555 const rtc::CopyOnWriteBuffer& payload,
556 cricket::SendDataResult* result) {
557 // TODO(bugs.webrtc.org/11547): Expect method to be called on the network
558 // thread instead. Remove the Invoke() below and move assocated state to
559 // the network thread.
560 RTC_DCHECK_RUN_ON(signaling_thread());
561 RTC_DCHECK(data_channel_transport());
562
563 SendDataParams send_params;
564 send_params.type = ToWebrtcDataMessageType(params.type);
565 send_params.ordered = params.ordered;
566 if (params.max_rtx_count >= 0) {
567 send_params.max_rtx_count = params.max_rtx_count;
568 } else if (params.max_rtx_ms >= 0) {
569 send_params.max_rtx_ms = params.max_rtx_ms;
570 }
571
572 RTCError error = network_thread()->Invoke<RTCError>(
573 RTC_FROM_HERE, [this, params, send_params, payload] {
574 return data_channel_transport()->SendData(params.sid, send_params,
575 payload);
576 });
577
578 if (error.ok()) {
579 *result = cricket::SendDataResult::SDR_SUCCESS;
580 return true;
581 } else if (error.type() == RTCErrorType::RESOURCE_EXHAUSTED) {
582 // SCTP transport uses RESOURCE_EXHAUSTED when it's blocked.
583 // TODO(mellem): Stop using RTCError here and get rid of the mapping.
584 *result = cricket::SendDataResult::SDR_BLOCK;
585 return false;
586 }
587 *result = cricket::SendDataResult::SDR_ERROR;
588 return false;
589}
590
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200591void DataChannelController::NotifyDataChannelsOfTransportCreated() {
592 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson6da27182020-09-12 23:10:17 +0200593 data_channel_transport_invoker_.AsyncInvoke<void>(
Tomas Gunnarsson2e94de52020-06-16 16:54:10 +0200594 RTC_FROM_HERE, signaling_thread(), [this] {
595 RTC_DCHECK_RUN_ON(signaling_thread());
596 for (const auto& channel : sctp_data_channels_) {
597 channel->OnTransportChannelCreated();
598 }
599 });
600}
601
Harald Alvestrand05e4d082019-12-03 14:04:21 +0100602rtc::Thread* DataChannelController::network_thread() const {
603 return pc_->network_thread();
604}
605rtc::Thread* DataChannelController::signaling_thread() const {
606 return pc_->signaling_thread();
607}
608
Harald Alvestrand00cf34c2019-12-02 09:56:02 +0100609} // namespace webrtc