blob: a7ec6680a4837dd403dbbd3d064326380a893733 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander65c7f672016-02-12 00:05:01 -08002 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander65c7f672016-02-12 00:05:01 -08004 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
jbauch5869f502017-06-29 12:31:36 -070011#include <algorithm>
12#include <iterator>
kwiberg0eb15ed2015-12-17 03:04:15 -080013#include <utility>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "pc/channel.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "api/call/audio_sink.h"
18#include "media/base/mediaconstants.h"
19#include "media/base/rtputils.h"
20#include "rtc_base/bind.h"
21#include "rtc_base/byteorder.h"
22#include "rtc_base/checks.h"
23#include "rtc_base/copyonwritebuffer.h"
24#include "rtc_base/dscp.h"
25#include "rtc_base/logging.h"
26#include "rtc_base/networkroute.h"
27#include "rtc_base/ptr_util.h"
28#include "rtc_base/trace_event.h"
Patrik Höglund42805f32018-01-18 19:15:38 +000029// Adding 'nogncheck' to disable the gn include headers check to support modular
30// WebRTC build targets.
31#include "media/engine/webrtcvoiceengine.h" // nogncheck
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020032#include "p2p/base/packettransportinternal.h"
33#include "pc/channelmanager.h"
Steve Anton4e70a722017-11-28 14:57:10 -080034#include "pc/rtpmediautils.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035
36namespace cricket {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000037using rtc::Bind;
Steve Anton3828c062017-12-06 10:34:51 -080038using webrtc::SdpType;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000039
deadbeef2d110be2016-01-13 12:00:26 -080040namespace {
Danil Chapovalov33b01f22016-05-11 19:55:27 +020041
42struct SendPacketMessageData : public rtc::MessageData {
43 rtc::CopyOnWriteBuffer packet;
44 rtc::PacketOptions options;
45};
46
deadbeef2d110be2016-01-13 12:00:26 -080047} // namespace
48
henrike@webrtc.org28e20752013-07-10 00:45:36 +000049enum {
Steve Anton0807d152018-03-05 11:23:09 -080050 MSG_SEND_RTP_PACKET = 1,
Danil Chapovalov33b01f22016-05-11 19:55:27 +020051 MSG_SEND_RTCP_PACKET,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000052 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000053 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000054 MSG_FIRSTPACKETRECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000055};
56
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000057static void SafeSetError(const std::string& message, std::string* error_desc) {
58 if (error_desc) {
59 *error_desc = message;
60 }
61}
62
jbaucheec21bd2016-03-20 06:15:43 -070063static bool ValidPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064 // Check the packet size. We could check the header too if needed.
zstein3dcf0e92017-06-01 13:22:42 -070065 return packet && IsValidRtpRtcpPacketSize(rtcp, packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066}
67
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070068template <class Codec>
69void RtpParametersFromMediaDescription(
70 const MediaContentDescriptionImpl<Codec>* desc,
jbauch5869f502017-06-29 12:31:36 -070071 const RtpHeaderExtensions& extensions,
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070072 RtpParameters<Codec>* params) {
73 // TODO(pthatcher): Remove this once we're sure no one will give us
Zhi Huang801b8682017-11-15 11:36:43 -080074 // a description without codecs. Currently the ORTC implementation is relying
75 // on this.
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070076 if (desc->has_codecs()) {
77 params->codecs = desc->codecs();
78 }
79 // TODO(pthatcher): See if we really need
80 // rtp_header_extensions_set() and remove it if we don't.
81 if (desc->rtp_header_extensions_set()) {
jbauch5869f502017-06-29 12:31:36 -070082 params->extensions = extensions;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070083 }
deadbeef13871492015-12-09 12:37:51 -080084 params->rtcp.reduced_size = desc->rtcp_reduced_size();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070085}
86
nisse05103312016-03-16 02:22:50 -070087template <class Codec>
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070088void RtpSendParametersFromMediaDescription(
89 const MediaContentDescriptionImpl<Codec>* desc,
jbauch5869f502017-06-29 12:31:36 -070090 const RtpHeaderExtensions& extensions,
nisse05103312016-03-16 02:22:50 -070091 RtpSendParameters<Codec>* send_params) {
jbauch5869f502017-06-29 12:31:36 -070092 RtpParametersFromMediaDescription(desc, extensions, send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070093 send_params->max_bandwidth_bps = desc->bandwidth();
94}
95
Danil Chapovalov33b01f22016-05-11 19:55:27 +020096BaseChannel::BaseChannel(rtc::Thread* worker_thread,
97 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -080098 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -080099 std::unique_ptr<MediaChannel> media_channel,
deadbeefcbecd352015-09-23 11:50:27 -0700100 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -0800101 bool rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -0800102 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200103 : worker_thread_(worker_thread),
104 network_thread_(network_thread),
zhihuangf5b251b2017-01-12 19:37:48 -0800105 signaling_thread_(signaling_thread),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000106 content_name_(content_name),
zstein56162b92017-04-24 16:54:35 -0700107 rtcp_mux_required_(rtcp_mux_required),
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800108 unencrypted_rtp_transport_(
109 rtc::MakeUnique<webrtc::RtpTransport>(rtcp_mux_required)),
deadbeef7af91dd2016-12-13 11:29:11 -0800110 srtp_required_(srtp_required),
Zhi Huang1d88d742017-11-15 15:58:49 -0800111 media_channel_(std::move(media_channel)) {
Steve Anton8699a322017-11-06 15:53:33 -0800112 RTC_DCHECK_RUN_ON(worker_thread_);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800113 rtp_transport_ = unencrypted_rtp_transport_.get();
114 ConnectToRtpTransport();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100115 RTC_LOG(LS_INFO) << "Created channel for " << content_name;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000116}
117
118BaseChannel::~BaseChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800119 TRACE_EVENT0("webrtc", "BaseChannel::~BaseChannel");
Steve Anton8699a322017-11-06 15:53:33 -0800120 RTC_DCHECK_RUN_ON(worker_thread_);
wu@webrtc.org78187522013-10-07 23:32:02 +0000121 Deinit();
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200122 // Eats any outstanding messages or packets.
123 worker_thread_->Clear(&invoker_);
124 worker_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000125 // We must destroy the media channel before the transport channel, otherwise
126 // the media channel may try to send on the dead transport channel. NULLing
127 // is not an effective strategy since the sends will come on another thread.
Steve Anton8699a322017-11-06 15:53:33 -0800128 media_channel_.reset();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100129 RTC_LOG(LS_INFO) << "Destroyed channel: " << content_name_;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200130}
131
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800132void BaseChannel::ConnectToRtpTransport() {
133 RTC_DCHECK(rtp_transport_);
134 rtp_transport_->SignalReadyToSend.connect(
135 this, &BaseChannel::OnTransportReadyToSend);
136 // TODO(zstein): RtpTransport::SignalPacketReceived will probably be replaced
137 // with a callback interface later so that the demuxer can select which
138 // channel to signal.
139 rtp_transport_->SignalPacketReceived.connect(this,
140 &BaseChannel::OnPacketReceived);
141 rtp_transport_->SignalNetworkRouteChanged.connect(
142 this, &BaseChannel::OnNetworkRouteChanged);
143 rtp_transport_->SignalWritableState.connect(this,
144 &BaseChannel::OnWritableState);
145 rtp_transport_->SignalSentPacket.connect(this,
146 &BaseChannel::SignalSentPacket_n);
Steve Antondb67ba12018-03-19 17:41:42 -0700147 // TODO(bugs.webrtc.org/8587): Set the metrics observer through
148 // JsepTransportController once it takes responsibility for creating
149 // RtpTransports.
150 if (metrics_observer_) {
151 rtp_transport_->SetMetricsObserver(metrics_observer_);
152 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800153}
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200154
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800155void BaseChannel::DisconnectFromRtpTransport() {
156 RTC_DCHECK(rtp_transport_);
157 rtp_transport_->SignalReadyToSend.disconnect(this);
158 rtp_transport_->SignalPacketReceived.disconnect(this);
159 rtp_transport_->SignalNetworkRouteChanged.disconnect(this);
160 rtp_transport_->SignalWritableState.disconnect(this);
161 rtp_transport_->SignalSentPacket.disconnect(this);
Steve Antondb67ba12018-03-19 17:41:42 -0700162 rtp_transport_->SetMetricsObserver(nullptr);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200163}
164
Steve Anton8699a322017-11-06 15:53:33 -0800165void BaseChannel::Init_w(DtlsTransportInternal* rtp_dtls_transport,
deadbeeff5346592017-01-24 21:51:21 -0800166 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800167 rtc::PacketTransportInternal* rtp_packet_transport,
168 rtc::PacketTransportInternal* rtcp_packet_transport) {
Steve Anton8699a322017-11-06 15:53:33 -0800169 RTC_DCHECK_RUN_ON(worker_thread_);
170 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800171 SetTransports_n(rtp_dtls_transport, rtcp_dtls_transport,
172 rtp_packet_transport, rtcp_packet_transport);
173
174 if (rtcp_mux_required_) {
175 rtcp_mux_filter_.SetActive();
176 }
Steve Anton8699a322017-11-06 15:53:33 -0800177 });
178
deadbeeff5346592017-01-24 21:51:21 -0800179 // Both RTP and RTCP channels should be set, we can call SetInterface on
180 // the media channel and it can set network options.
wu@webrtc.orgde305012013-10-31 15:40:38 +0000181 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000182}
183
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800184void BaseChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) {
185 RTC_DCHECK_RUN_ON(worker_thread_);
186 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
187 SetRtpTransport(rtp_transport);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200188
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800189 if (rtcp_mux_required_) {
190 rtcp_mux_filter_.SetActive();
191 }
192 });
193
194 // Both RTP and RTCP channels should be set, we can call SetInterface on
195 // the media channel and it can set network options.
196 media_channel_->SetInterface(this);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200197}
198
wu@webrtc.org78187522013-10-07 23:32:02 +0000199void BaseChannel::Deinit() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200200 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.org78187522013-10-07 23:32:02 +0000201 media_channel_->SetInterface(NULL);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200202 // Packets arrive on the network thread, processing packets calls virtual
203 // functions, so need to stop this process in Deinit that is called in
204 // derived classes destructor.
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800205 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
206 FlushRtcpMessages_n();
207
208 if (dtls_srtp_transport_) {
209 dtls_srtp_transport_->SetDtlsTransports(nullptr, nullptr);
210 } else {
211 rtp_transport_->SetRtpPacketTransport(nullptr);
212 rtp_transport_->SetRtcpPacketTransport(nullptr);
213 }
214 // Clear pending read packets/messages.
215 network_thread_->Clear(&invoker_);
216 network_thread_->Clear(this);
217 });
wu@webrtc.org78187522013-10-07 23:32:02 +0000218}
219
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800220void BaseChannel::SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) {
221 if (!network_thread_->IsCurrent()) {
222 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
223 SetRtpTransport(rtp_transport);
224 return;
225 });
226 }
227
228 RTC_DCHECK(rtp_transport);
229
230 if (rtp_transport_) {
231 DisconnectFromRtpTransport();
232 }
233 rtp_transport_ = rtp_transport;
234 RTC_LOG(LS_INFO) << "Setting the RtpTransport for " << content_name();
235 ConnectToRtpTransport();
236
237 UpdateWritableState_n();
238}
239
zhihuangb2cdd932017-01-19 16:54:25 -0800240void BaseChannel::SetTransports(DtlsTransportInternal* rtp_dtls_transport,
241 DtlsTransportInternal* rtcp_dtls_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800242 network_thread_->Invoke<void>(
243 RTC_FROM_HERE,
244 Bind(&BaseChannel::SetTransports_n, this, rtp_dtls_transport,
245 rtcp_dtls_transport, rtp_dtls_transport, rtcp_dtls_transport));
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000246}
247
deadbeeff5346592017-01-24 21:51:21 -0800248void BaseChannel::SetTransports(
deadbeef5bd5ca32017-02-10 11:31:50 -0800249 rtc::PacketTransportInternal* rtp_packet_transport,
250 rtc::PacketTransportInternal* rtcp_packet_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800251 network_thread_->Invoke<void>(
252 RTC_FROM_HERE, Bind(&BaseChannel::SetTransports_n, this, nullptr, nullptr,
253 rtp_packet_transport, rtcp_packet_transport));
254}
zhihuangf5b251b2017-01-12 19:37:48 -0800255
deadbeeff5346592017-01-24 21:51:21 -0800256void BaseChannel::SetTransports_n(
257 DtlsTransportInternal* rtp_dtls_transport,
258 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800259 rtc::PacketTransportInternal* rtp_packet_transport,
260 rtc::PacketTransportInternal* rtcp_packet_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800261 RTC_DCHECK(network_thread_->IsCurrent());
262 // Validate some assertions about the input.
263 RTC_DCHECK(rtp_packet_transport);
264 RTC_DCHECK_EQ(NeedsRtcpTransport(), rtcp_packet_transport != nullptr);
265 if (rtp_dtls_transport || rtcp_dtls_transport) {
266 // DTLS/non-DTLS pointers should be to the same object.
267 RTC_DCHECK(rtp_dtls_transport == rtp_packet_transport);
268 RTC_DCHECK(rtcp_dtls_transport == rtcp_packet_transport);
269 // Can't go from non-DTLS to DTLS.
zsteine8ab5432017-07-12 11:48:11 -0700270 RTC_DCHECK(!rtp_transport_->rtp_packet_transport() || rtp_dtls_transport_);
deadbeeff5346592017-01-24 21:51:21 -0800271 } else {
272 // Can't go from DTLS to non-DTLS.
273 RTC_DCHECK(!rtp_dtls_transport_);
274 }
275 // Transport names should be the same.
zhihuangb2cdd932017-01-19 16:54:25 -0800276 if (rtp_dtls_transport && rtcp_dtls_transport) {
277 RTC_DCHECK(rtp_dtls_transport->transport_name() ==
278 rtcp_dtls_transport->transport_name());
zhihuangb2cdd932017-01-19 16:54:25 -0800279 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800280
281 if (rtp_packet_transport == rtp_transport_->rtp_packet_transport()) {
282 // Nothing to do if transport isn't changing.
283 return;
284 }
285
deadbeeff5346592017-01-24 21:51:21 -0800286 std::string debug_name;
287 if (rtp_dtls_transport) {
288 transport_name_ = rtp_dtls_transport->transport_name();
289 debug_name = transport_name_;
290 } else {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800291 debug_name = rtp_packet_transport->transport_name();
deadbeeff5346592017-01-24 21:51:21 -0800292 }
deadbeefac22f702017-01-12 21:59:29 -0800293 // If this BaseChannel doesn't require RTCP mux and we haven't fully
294 // negotiated RTCP mux, we need an RTCP transport.
deadbeeff5346592017-01-24 21:51:21 -0800295 if (rtcp_packet_transport) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100296 RTC_LOG(LS_INFO) << "Setting RTCP Transport for " << content_name()
297 << " on " << debug_name << " transport "
298 << rtcp_packet_transport;
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800299 SetTransport_n(/*rtcp=*/true, rtcp_dtls_transport, rtcp_packet_transport);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000300 }
301
Mirko Bonadei675513b2017-11-09 11:09:25 +0100302 RTC_LOG(LS_INFO) << "Setting RTP Transport for " << content_name() << " on "
303 << debug_name << " transport " << rtp_packet_transport;
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800304 SetTransport_n(/*rtcp=*/false, rtp_dtls_transport, rtp_packet_transport);
305
306 // Set DtlsTransport/PacketTransport for RTP-level transport.
307 if ((rtp_dtls_transport_ || rtcp_dtls_transport_) && dtls_srtp_transport_) {
308 // When setting the transport with non-null |dtls_srtp_transport_|, we are
309 // using DTLS-SRTP. This could happen for bundling. If the
310 // |dtls_srtp_transport| is null, we cannot tell if it doing DTLS-SRTP or
311 // SDES until the description is set. So don't call |EnableDtlsSrtp_n| here.
312 dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport,
313 rtcp_dtls_transport);
314 } else {
315 rtp_transport_->SetRtpPacketTransport(rtp_packet_transport);
316 rtp_transport_->SetRtcpPacketTransport(rtcp_packet_transport);
317 }
guoweis46383312015-12-17 16:45:59 -0800318
deadbeefcbecd352015-09-23 11:50:27 -0700319 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700320 // setting new transport channels.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200321 UpdateWritableState_n();
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000322}
323
deadbeeff5346592017-01-24 21:51:21 -0800324void BaseChannel::SetTransport_n(
325 bool rtcp,
326 DtlsTransportInternal* new_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800327 rtc::PacketTransportInternal* new_packet_transport) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200328 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huang942bc2e2017-11-13 13:26:07 -0800329 if (new_dtls_transport) {
330 RTC_DCHECK(new_dtls_transport == new_packet_transport);
331 }
deadbeeff5346592017-01-24 21:51:21 -0800332 DtlsTransportInternal*& old_dtls_transport =
zhihuangb2cdd932017-01-19 16:54:25 -0800333 rtcp ? rtcp_dtls_transport_ : rtp_dtls_transport_;
zsteind48dbda2017-04-04 19:45:57 -0700334 rtc::PacketTransportInternal* old_packet_transport =
zsteine8ab5432017-07-12 11:48:11 -0700335 rtcp ? rtp_transport_->rtcp_packet_transport()
336 : rtp_transport_->rtp_packet_transport();
zhihuangb2cdd932017-01-19 16:54:25 -0800337
deadbeeff5346592017-01-24 21:51:21 -0800338 if (!old_packet_transport && !new_packet_transport) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700339 // Nothing to do.
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000340 return;
341 }
zhihuangb2cdd932017-01-19 16:54:25 -0800342
deadbeeff5346592017-01-24 21:51:21 -0800343 RTC_DCHECK(old_packet_transport != new_packet_transport);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000344
deadbeeff5346592017-01-24 21:51:21 -0800345 old_dtls_transport = new_dtls_transport;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000346
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800347 // If there's no new transport, we're done.
deadbeeff5346592017-01-24 21:51:21 -0800348 if (!new_packet_transport) {
349 return;
350 }
351
352 if (rtcp && new_dtls_transport) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700353 RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_active()))
354 << "Setting RTCP for DTLS/SRTP after the DTLS is active "
deadbeeff5346592017-01-24 21:51:21 -0800355 << "should never happen.";
356 }
zstein56162b92017-04-24 16:54:35 -0700357
deadbeeff5346592017-01-24 21:51:21 -0800358 auto& socket_options = rtcp ? rtcp_socket_options_ : socket_options_;
359 for (const auto& pair : socket_options) {
360 new_packet_transport->SetOption(pair.first, pair.second);
guoweis46383312015-12-17 16:45:59 -0800361 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000362}
363
Steve Antondb67ba12018-03-19 17:41:42 -0700364void BaseChannel::SetMetricsObserver(
365 rtc::scoped_refptr<webrtc::MetricsObserverInterface> metrics_observer) {
366 metrics_observer_ = metrics_observer;
367 if (rtp_transport_) {
368 rtp_transport_->SetMetricsObserver(metrics_observer);
369 }
370}
371
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000372bool BaseChannel::Enable(bool enable) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700373 worker_thread_->Invoke<void>(
374 RTC_FROM_HERE,
375 Bind(enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
376 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000377 return true;
378}
379
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000380bool BaseChannel::AddRecvStream(const StreamParams& sp) {
stefanf79ade12017-06-02 06:44:03 -0700381 return InvokeOnWorker<bool>(RTC_FROM_HERE,
382 Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000383}
384
Peter Boström0c4e06b2015-10-07 12:23:21 +0200385bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
stefanf79ade12017-06-02 06:44:03 -0700386 return InvokeOnWorker<bool>(
387 RTC_FROM_HERE, Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000388}
389
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000390bool BaseChannel::AddSendStream(const StreamParams& sp) {
stefanf79ade12017-06-02 06:44:03 -0700391 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700392 RTC_FROM_HERE, Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000393}
394
Peter Boström0c4e06b2015-10-07 12:23:21 +0200395bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
stefanf79ade12017-06-02 06:44:03 -0700396 return InvokeOnWorker<bool>(
397 RTC_FROM_HERE,
398 Bind(&MediaChannel::RemoveSendStream, media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000399}
400
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000401bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800402 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000403 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100404 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
stefanf79ade12017-06-02 06:44:03 -0700405 return InvokeOnWorker<bool>(
406 RTC_FROM_HERE,
Steve Anton3828c062017-12-06 10:34:51 -0800407 Bind(&BaseChannel::SetLocalContent_w, this, content, type, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000408}
409
410bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800411 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000412 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100413 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
stefanf79ade12017-06-02 06:44:03 -0700414 return InvokeOnWorker<bool>(
Steve Anton3828c062017-12-06 10:34:51 -0800415 RTC_FROM_HERE,
416 Bind(&BaseChannel::SetRemoteContent_w, this, content, type, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000417}
418
zhihuangf5b251b2017-01-12 19:37:48 -0800419bool BaseChannel::NeedsRtcpTransport() {
deadbeefac22f702017-01-12 21:59:29 -0800420 // If this BaseChannel doesn't require RTCP mux and we haven't fully
421 // negotiated RTCP mux, we need an RTCP transport.
zstein56162b92017-04-24 16:54:35 -0700422 return !rtcp_mux_required_ && !rtcp_mux_filter_.IsFullyActive();
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000423}
424
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700425bool BaseChannel::IsReadyToReceiveMedia_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000426 // Receive data if we are enabled and have local content,
Steve Anton4e70a722017-11-28 14:57:10 -0800427 return enabled() &&
428 webrtc::RtpTransceiverDirectionHasRecv(local_content_direction_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000429}
430
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700431bool BaseChannel::IsReadyToSendMedia_w() const {
432 // Need to access some state updated on the network thread.
433 return network_thread_->Invoke<bool>(
434 RTC_FROM_HERE, Bind(&BaseChannel::IsReadyToSendMedia_n, this));
435}
436
437bool BaseChannel::IsReadyToSendMedia_n() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000438 // Send outgoing data if we are enabled, have local and remote content,
439 // and we have had some form of connectivity.
Steve Anton4e70a722017-11-28 14:57:10 -0800440 return enabled() &&
441 webrtc::RtpTransceiverDirectionHasRecv(remote_content_direction_) &&
442 webrtc::RtpTransceiverDirectionHasSend(local_content_direction_) &&
Zhi Huangcf990f52017-09-22 12:12:30 -0700443 was_ever_writable() && (srtp_active() || !ShouldSetupDtlsSrtp_n());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000444}
445
jbaucheec21bd2016-03-20 06:15:43 -0700446bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700447 const rtc::PacketOptions& options) {
448 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000449}
450
jbaucheec21bd2016-03-20 06:15:43 -0700451bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700452 const rtc::PacketOptions& options) {
453 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000454}
455
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000456int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000457 int value) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200458 return network_thread_->Invoke<int>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700459 RTC_FROM_HERE, Bind(&BaseChannel::SetOption_n, this, type, opt, value));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200460}
461
462int BaseChannel::SetOption_n(SocketType type,
463 rtc::Socket::Option opt,
464 int value) {
465 RTC_DCHECK(network_thread_->IsCurrent());
deadbeef5bd5ca32017-02-10 11:31:50 -0800466 rtc::PacketTransportInternal* transport = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000467 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000468 case ST_RTP:
zsteine8ab5432017-07-12 11:48:11 -0700469 transport = rtp_transport_->rtp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700470 socket_options_.push_back(
471 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000472 break;
473 case ST_RTCP:
zsteine8ab5432017-07-12 11:48:11 -0700474 transport = rtp_transport_->rtcp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700475 rtcp_socket_options_.push_back(
476 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000477 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000478 }
deadbeeff5346592017-01-24 21:51:21 -0800479 return transport ? transport->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000480}
481
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800482void BaseChannel::OnWritableState(bool writable) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200483 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800484 if (writable) {
485 // This is used to cover the scenario when the DTLS handshake is completed
486 // and DtlsTransport becomes writable before the remote description is set.
487 if (ShouldSetupDtlsSrtp_n()) {
488 EnableDtlsSrtp_n();
Zhi Huangcf990f52017-09-22 12:12:30 -0700489 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800490 ChannelWritable_n();
491 } else {
492 ChannelNotWritable_n();
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800493 }
494}
495
Zhi Huang942bc2e2017-11-13 13:26:07 -0800496void BaseChannel::OnNetworkRouteChanged(
497 rtc::Optional<rtc::NetworkRoute> network_route) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200498 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huang942bc2e2017-11-13 13:26:07 -0800499 rtc::NetworkRoute new_route;
500 if (network_route) {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800501 new_route = *(network_route);
Zhi Huang8c316c12017-11-13 21:13:45 +0000502 }
Zhi Huang942bc2e2017-11-13 13:26:07 -0800503 // Note: When the RTCP-muxing is not enabled, RTCP transport and RTP transport
504 // use the same transport name and MediaChannel::OnNetworkRouteChanged cannot
505 // work correctly. Intentionally leave it broken to simplify the code and
506 // encourage the users to stop using non-muxing RTCP.
Steve Anton8699a322017-11-06 15:53:33 -0800507 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_, [=] {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800508 media_channel_->OnNetworkRouteChanged(transport_name_, new_route);
Steve Anton8699a322017-11-06 15:53:33 -0800509 });
Honghai Zhangcc411c02016-03-29 17:27:21 -0700510}
511
zstein56162b92017-04-24 16:54:35 -0700512void BaseChannel::OnTransportReadyToSend(bool ready) {
Steve Anton8699a322017-11-06 15:53:33 -0800513 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
514 [=] { media_channel_->OnReadyToSend(ready); });
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000515}
516
stefanc1aeaf02015-10-15 07:26:07 -0700517bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700518 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700519 const rtc::PacketOptions& options) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200520 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
521 // If the thread is not our network thread, we will post to our network
522 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000523 // synchronize access to all the pieces of the send path, including
524 // SRTP and the inner workings of the transport channels.
525 // The only downside is that we can't return a proper failure code if
526 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200527 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200529 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
530 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800531 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700532 data->options = options;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700533 network_thread_->Post(RTC_FROM_HERE, this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000534 return true;
535 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200536 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000537
538 // Now that we are on the correct thread, ensure we have a place to send this
539 // packet before doing anything. (We might get RTCP packets that we don't
540 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
541 // transport.
zsteine8ab5432017-07-12 11:48:11 -0700542 if (!rtp_transport_->IsWritable(rtcp)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000543 return false;
544 }
545
546 // Protect ourselves against crazy data.
547 if (!ValidPacket(rtcp, packet)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100548 RTC_LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
549 << RtpRtcpStringLiteral(rtcp)
550 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000551 return false;
552 }
553
Zhi Huangcf990f52017-09-22 12:12:30 -0700554 if (!srtp_active()) {
555 if (srtp_required_) {
556 // The audio/video engines may attempt to send RTCP packets as soon as the
557 // streams are created, so don't treat this as an error for RTCP.
558 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6809
559 if (rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000560 return false;
561 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700562 // However, there shouldn't be any RTP packets sent before SRTP is set up
563 // (and SetSend(true) is called).
Mirko Bonadei675513b2017-11-09 11:09:25 +0100564 RTC_LOG(LS_ERROR)
565 << "Can't send outgoing RTP packet when SRTP is inactive"
566 << " and crypto is required";
Zhi Huangcf990f52017-09-22 12:12:30 -0700567 RTC_NOTREACHED();
deadbeef8f425f92016-12-01 12:26:27 -0800568 return false;
569 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800570
571 std::string packet_type = rtcp ? "RTCP" : "RTP";
572 RTC_LOG(LS_WARNING) << "Sending an " << packet_type
573 << " packet without encryption.";
574 } else {
575 // Make sure we didn't accidentally send any packets without encryption.
576 RTC_DCHECK(rtp_transport_ == sdes_transport_.get() ||
577 rtp_transport_ == dtls_srtp_transport_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000578 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000579 // Bon voyage.
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800580 return rtcp ? rtp_transport_->SendRtcpPacket(packet, options, PF_SRTP_BYPASS)
581 : rtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000582}
583
zstein3dcf0e92017-06-01 13:22:42 -0700584bool BaseChannel::HandlesPayloadType(int packet_type) const {
zsteine8ab5432017-07-12 11:48:11 -0700585 return rtp_transport_->HandlesPayloadType(packet_type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000586}
587
zstein3dcf0e92017-06-01 13:22:42 -0700588void BaseChannel::OnPacketReceived(bool rtcp,
zstein634977b2017-07-14 12:30:04 -0700589 rtc::CopyOnWriteBuffer* packet,
zstein3dcf0e92017-06-01 13:22:42 -0700590 const rtc::PacketTime& packet_time) {
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000591 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000592 has_received_packet_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700593 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000594 }
595
Zhi Huangcf990f52017-09-22 12:12:30 -0700596 if (!srtp_active() && srtp_required_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000597 // Our session description indicates that SRTP is required, but we got a
598 // packet before our SRTP filter is active. This means either that
599 // a) we got SRTP packets before we received the SDES keys, in which case
600 // we can't decrypt it anyway, or
601 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
zhihuangb2cdd932017-01-19 16:54:25 -0800602 // transports, so we haven't yet extracted keys, even if DTLS did
603 // complete on the transport that the packets are being sent on. It's
604 // really good practice to wait for both RTP and RTCP to be good to go
605 // before sending media, to prevent weird failure modes, so it's fine
606 // for us to just eat packets here. This is all sidestepped if RTCP mux
607 // is used anyway.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100608 RTC_LOG(LS_WARNING)
609 << "Can't process incoming " << RtpRtcpStringLiteral(rtcp)
610 << " packet when SRTP is inactive and crypto is required";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000611 return;
612 }
613
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200614 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700615 RTC_FROM_HERE, worker_thread_,
zstein634977b2017-07-14 12:30:04 -0700616 Bind(&BaseChannel::ProcessPacket, this, rtcp, *packet, packet_time));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200617}
618
zstein3dcf0e92017-06-01 13:22:42 -0700619void BaseChannel::ProcessPacket(bool rtcp,
620 const rtc::CopyOnWriteBuffer& packet,
621 const rtc::PacketTime& packet_time) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200622 RTC_DCHECK(worker_thread_->IsCurrent());
zstein3dcf0e92017-06-01 13:22:42 -0700623
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200624 // Need to copy variable because OnRtcpReceived/OnPacketReceived
625 // requires non-const pointer to buffer. This doesn't memcpy the actual data.
626 rtc::CopyOnWriteBuffer data(packet);
627 if (rtcp) {
628 media_channel_->OnRtcpReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000629 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200630 media_channel_->OnPacketReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000631 }
632}
633
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000634void BaseChannel::EnableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700635 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000636 if (enabled_)
637 return;
638
Mirko Bonadei675513b2017-11-09 11:09:25 +0100639 RTC_LOG(LS_INFO) << "Channel enabled";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000640 enabled_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700641 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000642}
643
644void BaseChannel::DisableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700645 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000646 if (!enabled_)
647 return;
648
Mirko Bonadei675513b2017-11-09 11:09:25 +0100649 RTC_LOG(LS_INFO) << "Channel disabled";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000650 enabled_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700651 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000652}
653
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200654void BaseChannel::UpdateWritableState_n() {
zsteind48dbda2017-04-04 19:45:57 -0700655 rtc::PacketTransportInternal* rtp_packet_transport =
zsteine8ab5432017-07-12 11:48:11 -0700656 rtp_transport_->rtp_packet_transport();
zsteind48dbda2017-04-04 19:45:57 -0700657 rtc::PacketTransportInternal* rtcp_packet_transport =
zsteine8ab5432017-07-12 11:48:11 -0700658 rtp_transport_->rtcp_packet_transport();
zsteind48dbda2017-04-04 19:45:57 -0700659 if (rtp_packet_transport && rtp_packet_transport->writable() &&
660 (!rtcp_packet_transport || rtcp_packet_transport->writable())) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200661 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700662 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200663 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700664 }
665}
666
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200667void BaseChannel::ChannelWritable_n() {
668 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800669 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000670 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800671 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000672
Mirko Bonadei675513b2017-11-09 11:09:25 +0100673 RTC_LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
674 << (was_ever_writable_ ? "" : " for the first time");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000675
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000676 was_ever_writable_ = true;
677 writable_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700678 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679}
680
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200681bool BaseChannel::ShouldSetupDtlsSrtp_n() const {
zhihuangb2cdd932017-01-19 16:54:25 -0800682 // Since DTLS is applied to all transports, checking RTP should be enough.
683 return rtp_dtls_transport_ && rtp_dtls_transport_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684}
685
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200686void BaseChannel::ChannelNotWritable_n() {
687 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688 if (!writable_)
689 return;
690
Mirko Bonadei675513b2017-11-09 11:09:25 +0100691 RTC_LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000692 writable_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700693 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000694}
695
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200696bool BaseChannel::SetRtpTransportParameters(
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700697 const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800698 SdpType type,
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700699 ContentSource src,
jbauch5869f502017-06-29 12:31:36 -0700700 const RtpHeaderExtensions& extensions,
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700701 std::string* error_desc) {
jbauch5869f502017-06-29 12:31:36 -0700702 std::vector<int> encrypted_extension_ids;
703 for (const webrtc::RtpExtension& extension : extensions) {
704 if (extension.encrypt) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100705 RTC_LOG(LS_INFO) << "Using " << (src == CS_LOCAL ? "local" : "remote")
706 << " encrypted extension: " << extension.ToString();
jbauch5869f502017-06-29 12:31:36 -0700707 encrypted_extension_ids.push_back(extension.id);
708 }
709 }
710
deadbeef7af91dd2016-12-13 11:29:11 -0800711 // Cache srtp_required_ for belt and suspenders check on SendPacket
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200712 return network_thread_->Invoke<bool>(
Steve Anton3828c062017-12-06 10:34:51 -0800713 RTC_FROM_HERE,
714 Bind(&BaseChannel::SetRtpTransportParameters_n, this, content, type, src,
715 encrypted_extension_ids, error_desc));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200716}
717
718bool BaseChannel::SetRtpTransportParameters_n(
719 const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800720 SdpType type,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200721 ContentSource src,
jbauch5869f502017-06-29 12:31:36 -0700722 const std::vector<int>& encrypted_extension_ids,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200723 std::string* error_desc) {
724 RTC_DCHECK(network_thread_->IsCurrent());
725
Steve Anton3828c062017-12-06 10:34:51 -0800726 if (!SetSrtp_n(content->cryptos(), type, src, encrypted_extension_ids,
727 error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700728 return false;
729 }
730
Steve Anton3828c062017-12-06 10:34:51 -0800731 if (!SetRtcpMux_n(content->rtcp_mux(), type, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700732 return false;
733 }
734
735 return true;
736}
737
zhihuangb2cdd932017-01-19 16:54:25 -0800738// |dtls| will be set to true if DTLS is active for transport and crypto is
739// empty.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200740bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
741 bool* dtls,
742 std::string* error_desc) {
deadbeeff5346592017-01-24 21:51:21 -0800743 *dtls = rtp_dtls_transport_ && rtp_dtls_transport_->IsDtlsActive();
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000744 if (*dtls && !cryptos.empty()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200745 SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000746 return false;
747 }
748 return true;
749}
750
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800751void BaseChannel::EnableSdes_n() {
752 if (sdes_transport_) {
753 return;
Zhi Huangcf990f52017-09-22 12:12:30 -0700754 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800755 // DtlsSrtpTransport and SrtpTransport shouldn't be enabled at the same
756 // time.
757 RTC_DCHECK(!dtls_srtp_transport_);
758 RTC_DCHECK(unencrypted_rtp_transport_);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800759 sdes_transport_ = rtc::MakeUnique<webrtc::SrtpTransport>(
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800760 std::move(unencrypted_rtp_transport_));
Zhi Huangd7455782017-11-30 14:50:52 -0800761#if defined(ENABLE_EXTERNAL_AUTH)
762 sdes_transport_->EnableExternalAuth();
763#endif
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800764 SetRtpTransport(sdes_transport_.get());
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800765 RTC_LOG(LS_INFO) << "Wrapping RtpTransport in SrtpTransport.";
766}
767
768void BaseChannel::EnableDtlsSrtp_n() {
769 if (dtls_srtp_transport_) {
770 return;
771 }
772 // DtlsSrtpTransport and SrtpTransport shouldn't be enabled at the same
773 // time.
774 RTC_DCHECK(!sdes_transport_);
775 RTC_DCHECK(unencrypted_rtp_transport_);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800776
777 auto srtp_transport = rtc::MakeUnique<webrtc::SrtpTransport>(
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800778 std::move(unencrypted_rtp_transport_));
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800779#if defined(ENABLE_EXTERNAL_AUTH)
780 srtp_transport->EnableExternalAuth();
781#endif
782 dtls_srtp_transport_ =
783 rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport));
784
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800785 SetRtpTransport(dtls_srtp_transport_.get());
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800786 if (cached_send_extension_ids_) {
787 dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
788 *cached_send_extension_ids_);
789 }
790 if (cached_recv_extension_ids_) {
791 dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
792 *cached_recv_extension_ids_);
793 }
794 // Set the DtlsTransport and the |dtls_srtp_transport_| will handle the DTLS
795 // relate signal internally.
796 RTC_DCHECK(rtp_dtls_transport_);
797 dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport_,
798 rtcp_dtls_transport_);
799
800 RTC_LOG(LS_INFO) << "Wrapping SrtpTransport in DtlsSrtpTransport.";
Zhi Huangcf990f52017-09-22 12:12:30 -0700801}
802
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200803bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
Steve Anton3828c062017-12-06 10:34:51 -0800804 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000805 ContentSource src,
jbauch5869f502017-06-29 12:31:36 -0700806 const std::vector<int>& encrypted_extension_ids,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000807 std::string* error_desc) {
Peter Boströmca8b4042016-03-08 14:24:13 -0800808 TRACE_EVENT0("webrtc", "BaseChannel::SetSrtp_w");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000809 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000810 bool dtls = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200811 ret = CheckSrtpConfig_n(cryptos, &dtls, error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000812 if (!ret) {
813 return false;
814 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700815
816 // If SRTP was not required, but we're setting a description that uses SDES,
817 // we need to upgrade to an SrtpTransport.
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800818 if (!sdes_transport_ && !dtls && !cryptos.empty()) {
819 EnableSdes_n();
Zhi Huangcf990f52017-09-22 12:12:30 -0700820 }
Zhi Huangc99b6c72017-11-10 16:44:46 -0800821
Steve Anton3828c062017-12-06 10:34:51 -0800822 if ((type == SdpType::kAnswer || type == SdpType::kPrAnswer) && dtls) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800823 EnableDtlsSrtp_n();
824 }
Zhi Huangc99b6c72017-11-10 16:44:46 -0800825
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800826 UpdateEncryptedHeaderExtensionIds(src, encrypted_extension_ids);
827
828 if (!dtls) {
Steve Anton3828c062017-12-06 10:34:51 -0800829 switch (type) {
830 case SdpType::kOffer:
Zhi Huangcf990f52017-09-22 12:12:30 -0700831 ret = sdes_negotiator_.SetOffer(cryptos, src);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800832 break;
Steve Anton3828c062017-12-06 10:34:51 -0800833 case SdpType::kPrAnswer:
Zhi Huangcf990f52017-09-22 12:12:30 -0700834 ret = sdes_negotiator_.SetProvisionalAnswer(cryptos, src);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800835 break;
Steve Anton3828c062017-12-06 10:34:51 -0800836 case SdpType::kAnswer:
Zhi Huangcf990f52017-09-22 12:12:30 -0700837 ret = sdes_negotiator_.SetAnswer(cryptos, src);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800838 break;
839 default:
840 break;
841 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700842
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800843 // If setting an SDES answer succeeded, apply the negotiated parameters
844 // to the SRTP transport.
Steve Anton3828c062017-12-06 10:34:51 -0800845 if ((type == SdpType::kPrAnswer || type == SdpType::kAnswer) && ret) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800846 if (sdes_negotiator_.send_cipher_suite() &&
847 sdes_negotiator_.recv_cipher_suite()) {
848 RTC_DCHECK(cached_send_extension_ids_);
849 RTC_DCHECK(cached_recv_extension_ids_);
850 ret = sdes_transport_->SetRtpParams(
851 *(sdes_negotiator_.send_cipher_suite()),
852 sdes_negotiator_.send_key().data(),
853 static_cast<int>(sdes_negotiator_.send_key().size()),
854 *(cached_send_extension_ids_),
855 *(sdes_negotiator_.recv_cipher_suite()),
856 sdes_negotiator_.recv_key().data(),
857 static_cast<int>(sdes_negotiator_.recv_key().size()),
858 *(cached_recv_extension_ids_));
859 } else {
860 RTC_LOG(LS_INFO) << "No crypto keys are provided for SDES.";
Steve Anton3828c062017-12-06 10:34:51 -0800861 if (type == SdpType::kAnswer && sdes_transport_) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800862 // Explicitly reset the |sdes_transport_| if no crypto param is
863 // provided in the answer. No need to call |ResetParams()| for
864 // |sdes_negotiator_| because it resets the params inside |SetAnswer|.
865 sdes_transport_->ResetParams();
866 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700867 }
868 }
869 }
870
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000871 if (!ret) {
Zhi Huangc99b6c72017-11-10 16:44:46 -0800872 SafeSetError("Failed to setup SRTP.", error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000873 return false;
874 }
875 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000876}
877
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200878bool BaseChannel::SetRtcpMux_n(bool enable,
Steve Anton3828c062017-12-06 10:34:51 -0800879 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000880 ContentSource src,
881 std::string* error_desc) {
deadbeef8e814d72017-01-13 11:34:39 -0800882 // Provide a more specific error message for the RTCP mux "require" policy
883 // case.
zstein56162b92017-04-24 16:54:35 -0700884 if (rtcp_mux_required_ && !enable) {
deadbeef8e814d72017-01-13 11:34:39 -0800885 SafeSetError(
886 "rtcpMuxPolicy is 'require', but media description does not "
887 "contain 'a=rtcp-mux'.",
888 error_desc);
889 return false;
890 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000891 bool ret = false;
Steve Anton3828c062017-12-06 10:34:51 -0800892 switch (type) {
893 case SdpType::kOffer:
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894 ret = rtcp_mux_filter_.SetOffer(enable, src);
895 break;
Steve Anton3828c062017-12-06 10:34:51 -0800896 case SdpType::kPrAnswer:
zhihuangb2cdd932017-01-19 16:54:25 -0800897 // This may activate RTCP muxing, but we don't yet destroy the transport
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700898 // because the final answer may deactivate it.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000899 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
900 break;
Steve Anton3828c062017-12-06 10:34:51 -0800901 case SdpType::kAnswer:
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000902 ret = rtcp_mux_filter_.SetAnswer(enable, src);
903 if (ret && rtcp_mux_filter_.IsActive()) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800904 ActivateRtcpMux();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000905 }
906 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000907 default:
908 break;
909 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000910 if (!ret) {
911 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
912 return false;
913 }
zsteine8ab5432017-07-12 11:48:11 -0700914 rtp_transport_->SetRtcpMuxEnabled(rtcp_mux_filter_.IsActive());
Steve Anton3828c062017-12-06 10:34:51 -0800915 // |rtcp_mux_filter_| can be active if |action| is SdpType::kPrAnswer or
916 // SdpType::kAnswer, but we only want to tear down the RTCP transport if we
917 // received a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000918 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000919 // If the RTP transport is already writable, then so are we.
zsteine8ab5432017-07-12 11:48:11 -0700920 if (rtp_transport_->rtp_packet_transport()->writable()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200921 ChannelWritable_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000922 }
923 }
924
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000925 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926}
927
928bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700929 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -0800930 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000931}
932
Peter Boström0c4e06b2015-10-07 12:23:21 +0200933bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700934 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000935 return media_channel()->RemoveRecvStream(ssrc);
936}
937
938bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
Steve Anton3828c062017-12-06 10:34:51 -0800939 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000940 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000941 // Check for streams that have been removed.
942 bool ret = true;
943 for (StreamParamsVec::const_iterator it = local_streams_.begin();
944 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +0000945 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000946 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000947 std::ostringstream desc;
948 desc << "Failed to remove send stream with ssrc "
949 << it->first_ssrc() << ".";
950 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000951 ret = false;
952 }
953 }
954 }
955 // Check for new streams.
956 for (StreamParamsVec::const_iterator it = streams.begin();
957 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +0000958 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000959 if (media_channel()->AddSendStream(*it)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100960 RTC_LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000961 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000962 std::ostringstream desc;
963 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
964 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000965 ret = false;
966 }
967 }
968 }
969 local_streams_ = streams;
970 return ret;
971}
972
973bool BaseChannel::UpdateRemoteStreams_w(
974 const std::vector<StreamParams>& streams,
Steve Anton3828c062017-12-06 10:34:51 -0800975 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000976 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000977 // Check for streams that have been removed.
978 bool ret = true;
979 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
980 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +0000981 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000982 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000983 std::ostringstream desc;
984 desc << "Failed to remove remote stream with ssrc "
985 << it->first_ssrc() << ".";
986 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000987 ret = false;
988 }
989 }
990 }
991 // Check for new streams.
992 for (StreamParamsVec::const_iterator it = streams.begin();
993 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +0000994 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000995 if (AddRecvStream_w(*it)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100996 RTC_LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000997 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000998 std::ostringstream desc;
999 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1000 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001001 ret = false;
1002 }
1003 }
1004 }
1005 remote_streams_ = streams;
1006 return ret;
1007}
1008
jbauch5869f502017-06-29 12:31:36 -07001009RtpHeaderExtensions BaseChannel::GetFilteredRtpHeaderExtensions(
1010 const RtpHeaderExtensions& extensions) {
1011 if (!rtp_dtls_transport_ ||
1012 !rtp_dtls_transport_->crypto_options()
1013 .enable_encrypted_rtp_header_extensions) {
1014 RtpHeaderExtensions filtered;
1015 auto pred = [](const webrtc::RtpExtension& extension) {
1016 return !extension.encrypt;
1017 };
1018 std::copy_if(extensions.begin(), extensions.end(),
1019 std::back_inserter(filtered), pred);
1020 return filtered;
1021 }
1022
1023 return webrtc::RtpExtension::FilterDuplicateNonEncrypted(extensions);
1024}
1025
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001026void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w(
isheriff6f8d6862016-05-26 11:24:55 -07001027 const std::vector<webrtc::RtpExtension>& extensions) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001028// Absolute Send Time extension id is used only with external auth,
1029// so do not bother searching for it and making asyncronious call to set
1030// something that is not used.
1031#if defined(ENABLE_EXTERNAL_AUTH)
isheriff6f8d6862016-05-26 11:24:55 -07001032 const webrtc::RtpExtension* send_time_extension =
jbauch5869f502017-06-29 12:31:36 -07001033 webrtc::RtpExtension::FindHeaderExtensionByUri(
1034 extensions, webrtc::RtpExtension::kAbsSendTimeUri);
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001035 int rtp_abs_sendtime_extn_id =
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001036 send_time_extension ? send_time_extension->id : -1;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001037 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001038 RTC_FROM_HERE, network_thread_,
1039 Bind(&BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n, this,
1040 rtp_abs_sendtime_extn_id));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001041#endif
1042}
1043
1044void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n(
1045 int rtp_abs_sendtime_extn_id) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001046 if (sdes_transport_) {
1047 sdes_transport_->CacheRtpAbsSendTimeHeaderExtension(
Zhi Huangcf990f52017-09-22 12:12:30 -07001048 rtp_abs_sendtime_extn_id);
Zhi Huang2a4d70c2017-11-29 15:41:59 -08001049 } else if (dtls_srtp_transport_) {
1050 dtls_srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
1051 rtp_abs_sendtime_extn_id);
Zhi Huangcf990f52017-09-22 12:12:30 -07001052 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001053 RTC_LOG(LS_WARNING)
1054 << "Trying to cache the Absolute Send Time extension id "
1055 "but the SRTP is not active.";
Zhi Huangcf990f52017-09-22 12:12:30 -07001056 }
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001057}
1058
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001059void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001060 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001061 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001062 case MSG_SEND_RTP_PACKET:
1063 case MSG_SEND_RTCP_PACKET: {
1064 RTC_DCHECK(network_thread_->IsCurrent());
1065 SendPacketMessageData* data =
1066 static_cast<SendPacketMessageData*>(pmsg->pdata);
1067 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
1068 SendPacket(rtcp, &data->packet, data->options);
1069 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001070 break;
1071 }
1072 case MSG_FIRSTPACKETRECEIVED: {
1073 SignalFirstPacketReceived(this);
1074 break;
1075 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001076 }
1077}
1078
zstein3dcf0e92017-06-01 13:22:42 -07001079void BaseChannel::AddHandledPayloadType(int payload_type) {
zsteine8ab5432017-07-12 11:48:11 -07001080 rtp_transport_->AddHandledPayloadType(payload_type);
zstein3dcf0e92017-06-01 13:22:42 -07001081}
1082
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001083void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001084 // Flush all remaining RTCP messages. This should only be called in
1085 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001086 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001087 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001088 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
1089 for (const auto& message : rtcp_messages) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001090 network_thread_->Send(RTC_FROM_HERE, this, MSG_SEND_RTCP_PACKET,
1091 message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001092 }
1093}
1094
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001095void BaseChannel::SignalSentPacket_n(const rtc::SentPacket& sent_packet) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001096 RTC_DCHECK(network_thread_->IsCurrent());
1097 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001098 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001099 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
1100}
1101
1102void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
1103 RTC_DCHECK(worker_thread_->IsCurrent());
1104 SignalSentPacket(sent_packet);
1105}
1106
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001107void BaseChannel::UpdateEncryptedHeaderExtensionIds(
Zhi Huangc99b6c72017-11-10 16:44:46 -08001108 cricket::ContentSource source,
1109 const std::vector<int>& extension_ids) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001110 if (source == ContentSource::CS_LOCAL) {
1111 cached_recv_extension_ids_ = std::move(extension_ids);
1112 if (dtls_srtp_transport_) {
1113 dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
1114 extension_ids);
1115 }
1116 } else {
1117 cached_send_extension_ids_ = std::move(extension_ids);
1118 if (dtls_srtp_transport_) {
1119 dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
1120 extension_ids);
1121 }
1122 }
Zhi Huangc99b6c72017-11-10 16:44:46 -08001123}
1124
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001125void BaseChannel::ActivateRtcpMux() {
1126 // We permanently activated RTCP muxing; signal that we no longer need
1127 // the RTCP transport.
1128 std::string debug_name =
1129 transport_name_.empty()
1130 ? rtp_transport_->rtp_packet_transport()->transport_name()
1131 : transport_name_;
1132 RTC_LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
1133 << "; no longer need RTCP transport for " << debug_name;
1134 if (rtp_transport_->rtcp_packet_transport()) {
1135 SetTransport_n(/*rtcp=*/true, nullptr, nullptr);
1136 if (dtls_srtp_transport_) {
1137 RTC_DCHECK(rtp_dtls_transport_);
1138 dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport_,
1139 /*rtcp_dtls_transport_=*/nullptr);
1140 } else {
1141 rtp_transport_->SetRtcpPacketTransport(nullptr);
1142 }
1143 SignalRtcpMuxFullyActive(transport_name_);
Zhi Huangc99b6c72017-11-10 16:44:46 -08001144 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001145 UpdateWritableState_n();
Zhi Huangc99b6c72017-11-10 16:44:46 -08001146}
1147
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001148VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
1149 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001150 rtc::Thread* signaling_thread,
Niels Möllerf120cba2018-01-30 09:33:03 +01001151 // TODO(nisse): Delete unused argument.
1152 MediaEngineInterface* /* media_engine */,
Steve Anton8699a322017-11-06 15:53:33 -08001153 std::unique_ptr<VoiceMediaChannel> media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001154 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08001155 bool rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001156 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001157 : BaseChannel(worker_thread,
1158 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001159 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001160 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -07001161 content_name,
deadbeefac22f702017-01-12 21:59:29 -08001162 rtcp_mux_required,
Niels Möllerf120cba2018-01-30 09:33:03 +01001163 srtp_required) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001164
1165VoiceChannel::~VoiceChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001166 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001167 // this can't be done in the base class, since it calls a virtual
1168 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001169 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001170}
1171
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001172void BaseChannel::UpdateMediaSendRecvState() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001173 RTC_DCHECK(network_thread_->IsCurrent());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001174 invoker_.AsyncInvoke<void>(
1175 RTC_FROM_HERE, worker_thread_,
1176 Bind(&BaseChannel::UpdateMediaSendRecvState_w, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001177}
1178
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001179void VoiceChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001180 // Render incoming data if we're the active call, and we have the local
1181 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001182 bool recv = IsReadyToReceiveMedia_w();
solenberg5b14b422015-10-01 04:10:31 -07001183 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001184
1185 // Send outgoing data if we're the active call, we have the remote content,
1186 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001187 bool send = IsReadyToSendMedia_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001188 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001189
Mirko Bonadei675513b2017-11-09 11:09:25 +01001190 RTC_LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001191}
1192
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001193bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001194 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001195 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001196 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001197 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001198 RTC_LOG(LS_INFO) << "Setting local voice description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001199
Steve Antonb1c1de12017-12-21 15:14:30 -08001200 RTC_DCHECK(content);
1201 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001202 SafeSetError("Can't find audio content in local description.", error_desc);
1203 return false;
1204 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001205
Steve Antonb1c1de12017-12-21 15:14:30 -08001206 const AudioContentDescription* audio = content->as_audio();
1207
jbauch5869f502017-06-29 12:31:36 -07001208 RtpHeaderExtensions rtp_header_extensions =
1209 GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
1210
Steve Anton3828c062017-12-06 10:34:51 -08001211 if (!SetRtpTransportParameters(content, type, CS_LOCAL, rtp_header_extensions,
1212 error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001213 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001214 }
1215
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001216 AudioRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07001217 RtpParametersFromMediaDescription(audio, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001218 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001219 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001220 error_desc);
1221 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001222 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001223 for (const AudioCodec& codec : audio->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07001224 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001225 }
1226 last_recv_params_ = recv_params;
1227
1228 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1229 // only give it to the media channel once we have a remote
1230 // description too (without a remote description, we won't be able
1231 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001232 if (!UpdateLocalStreams_w(audio->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001233 SafeSetError("Failed to set local audio description streams.", error_desc);
1234 return false;
1235 }
1236
1237 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001238 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001239 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001240}
1241
1242bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001243 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001244 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001245 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001246 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001247 RTC_LOG(LS_INFO) << "Setting remote voice description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001248
Steve Antonb1c1de12017-12-21 15:14:30 -08001249 RTC_DCHECK(content);
1250 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001251 SafeSetError("Can't find audio content in remote description.", error_desc);
1252 return false;
1253 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001254
Steve Antonb1c1de12017-12-21 15:14:30 -08001255 const AudioContentDescription* audio = content->as_audio();
1256
jbauch5869f502017-06-29 12:31:36 -07001257 RtpHeaderExtensions rtp_header_extensions =
1258 GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
1259
Steve Anton3828c062017-12-06 10:34:51 -08001260 if (!SetRtpTransportParameters(content, type, CS_REMOTE,
1261 rtp_header_extensions, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001262 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001263 }
1264
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001265 AudioSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07001266 RtpSendParametersFromMediaDescription(audio, rtp_header_extensions,
1267 &send_params);
skvladdc1c62c2016-03-16 19:07:43 -07001268
1269 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1270 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001271 SafeSetError("Failed to set remote audio description send parameters.",
1272 error_desc);
1273 return false;
1274 }
1275 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001276
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001277 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1278 // and only give it to the media channel once we have a local
1279 // description too (without a local description, we won't be able to
1280 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001281 if (!UpdateRemoteStreams_w(audio->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001282 SafeSetError("Failed to set remote audio description streams.", error_desc);
1283 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001284 }
1285
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001286 if (audio->rtp_header_extensions_set()) {
jbauch5869f502017-06-29 12:31:36 -07001287 MaybeCacheRtpAbsSendTimeHeaderExtension_w(rtp_header_extensions);
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001288 }
1289
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001290 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001291 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001292 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001293}
1294
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001295VideoChannel::VideoChannel(rtc::Thread* worker_thread,
1296 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001297 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001298 std::unique_ptr<VideoMediaChannel> media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001299 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08001300 bool rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001301 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001302 : BaseChannel(worker_thread,
1303 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001304 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001305 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -07001306 content_name,
deadbeefac22f702017-01-12 21:59:29 -08001307 rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001308 srtp_required) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001309
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001310VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001311 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001312 // this can't be done in the base class, since it calls a virtual
1313 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001314
1315 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001316}
1317
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001318void VideoChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001319 // Send outgoing data if we're the active call, we have the remote content,
1320 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001321 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001322 if (!media_channel()->SetSend(send)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001323 RTC_LOG(LS_ERROR) << "Failed to SetSend on video channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001324 // TODO(gangji): Report error back to server.
1325 }
1326
Mirko Bonadei675513b2017-11-09 11:09:25 +01001327 RTC_LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001328}
1329
stefanf79ade12017-06-02 06:44:03 -07001330void VideoChannel::FillBitrateInfo(BandwidthEstimationInfo* bwe_info) {
1331 InvokeOnWorker<void>(RTC_FROM_HERE, Bind(&VideoMediaChannel::FillBitrateInfo,
1332 media_channel(), bwe_info));
1333}
1334
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001335bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001336 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001337 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001338 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001339 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001340 RTC_LOG(LS_INFO) << "Setting local video description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001341
Steve Antonb1c1de12017-12-21 15:14:30 -08001342 RTC_DCHECK(content);
1343 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001344 SafeSetError("Can't find video content in local description.", error_desc);
1345 return false;
1346 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001347
Steve Antonb1c1de12017-12-21 15:14:30 -08001348 const VideoContentDescription* video = content->as_video();
1349
jbauch5869f502017-06-29 12:31:36 -07001350 RtpHeaderExtensions rtp_header_extensions =
1351 GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
1352
Steve Anton3828c062017-12-06 10:34:51 -08001353 if (!SetRtpTransportParameters(content, type, CS_LOCAL, rtp_header_extensions,
1354 error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001355 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001356 }
1357
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001358 VideoRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07001359 RtpParametersFromMediaDescription(video, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001360 if (!media_channel()->SetRecvParameters(recv_params)) {
1361 SafeSetError("Failed to set local video description recv parameters.",
1362 error_desc);
1363 return false;
1364 }
1365 for (const VideoCodec& codec : video->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07001366 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001367 }
1368 last_recv_params_ = recv_params;
1369
1370 // TODO(pthatcher): Move local streams into VideoSendParameters, and
1371 // only give it to the media channel once we have a remote
1372 // description too (without a remote description, we won't be able
1373 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001374 if (!UpdateLocalStreams_w(video->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001375 SafeSetError("Failed to set local video description streams.", error_desc);
1376 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001377 }
1378
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001379 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001380 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001381 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001382}
1383
1384bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001385 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001386 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001387 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001388 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001389 RTC_LOG(LS_INFO) << "Setting remote video description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001390
Steve Antonb1c1de12017-12-21 15:14:30 -08001391 RTC_DCHECK(content);
1392 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001393 SafeSetError("Can't find video content in remote description.", error_desc);
1394 return false;
1395 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001396
Steve Antonb1c1de12017-12-21 15:14:30 -08001397 const VideoContentDescription* video = content->as_video();
1398
jbauch5869f502017-06-29 12:31:36 -07001399 RtpHeaderExtensions rtp_header_extensions =
1400 GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
1401
Steve Anton3828c062017-12-06 10:34:51 -08001402 if (!SetRtpTransportParameters(content, type, CS_REMOTE,
1403 rtp_header_extensions, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001404 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001405 }
1406
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001407 VideoSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07001408 RtpSendParametersFromMediaDescription(video, rtp_header_extensions,
1409 &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001410 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08001411 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001412 }
skvladdc1c62c2016-03-16 19:07:43 -07001413
1414 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1415
1416 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001417 SafeSetError("Failed to set remote video description send parameters.",
1418 error_desc);
1419 return false;
1420 }
1421 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001422
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001423 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
1424 // and only give it to the media channel once we have a local
1425 // description too (without a local description, we won't be able to
1426 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001427 if (!UpdateRemoteStreams_w(video->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001428 SafeSetError("Failed to set remote video description streams.", error_desc);
1429 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001430 }
1431
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001432 if (video->rtp_header_extensions_set()) {
jbauch5869f502017-06-29 12:31:36 -07001433 MaybeCacheRtpAbsSendTimeHeaderExtension_w(rtp_header_extensions);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001434 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001435
1436 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001437 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001438 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001439}
1440
deadbeef953c2ce2017-01-09 14:53:41 -08001441RtpDataChannel::RtpDataChannel(rtc::Thread* worker_thread,
1442 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001443 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001444 std::unique_ptr<DataMediaChannel> media_channel,
deadbeef953c2ce2017-01-09 14:53:41 -08001445 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08001446 bool rtcp_mux_required,
deadbeef953c2ce2017-01-09 14:53:41 -08001447 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001448 : BaseChannel(worker_thread,
1449 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001450 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001451 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -07001452 content_name,
deadbeefac22f702017-01-12 21:59:29 -08001453 rtcp_mux_required,
deadbeef953c2ce2017-01-09 14:53:41 -08001454 srtp_required) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001455
deadbeef953c2ce2017-01-09 14:53:41 -08001456RtpDataChannel::~RtpDataChannel() {
1457 TRACE_EVENT0("webrtc", "RtpDataChannel::~RtpDataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001458 // this can't be done in the base class, since it calls a virtual
1459 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001460
1461 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001462}
1463
Steve Anton8699a322017-11-06 15:53:33 -08001464void RtpDataChannel::Init_w(
deadbeeff5346592017-01-24 21:51:21 -08001465 DtlsTransportInternal* rtp_dtls_transport,
1466 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -08001467 rtc::PacketTransportInternal* rtp_packet_transport,
1468 rtc::PacketTransportInternal* rtcp_packet_transport) {
Steve Anton8699a322017-11-06 15:53:33 -08001469 BaseChannel::Init_w(rtp_dtls_transport, rtcp_dtls_transport,
1470 rtp_packet_transport, rtcp_packet_transport);
1471
deadbeef953c2ce2017-01-09 14:53:41 -08001472 media_channel()->SignalDataReceived.connect(this,
1473 &RtpDataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001474 media_channel()->SignalReadyToSend.connect(
deadbeef953c2ce2017-01-09 14:53:41 -08001475 this, &RtpDataChannel::OnDataChannelReadyToSend);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001476}
1477
Zhi Huang2dfc42d2017-12-04 13:38:48 -08001478void RtpDataChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) {
1479 BaseChannel::Init_w(rtp_transport);
1480 media_channel()->SignalDataReceived.connect(this,
1481 &RtpDataChannel::OnDataReceived);
1482 media_channel()->SignalReadyToSend.connect(
1483 this, &RtpDataChannel::OnDataChannelReadyToSend);
1484}
1485
deadbeef953c2ce2017-01-09 14:53:41 -08001486bool RtpDataChannel::SendData(const SendDataParams& params,
1487 const rtc::CopyOnWriteBuffer& payload,
1488 SendDataResult* result) {
stefanf79ade12017-06-02 06:44:03 -07001489 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001490 RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params,
1491 payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001492}
1493
deadbeef953c2ce2017-01-09 14:53:41 -08001494bool RtpDataChannel::CheckDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001495 const DataContentDescription* content,
1496 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001497 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
1498 (content->protocol() == kMediaProtocolDtlsSctp));
deadbeef953c2ce2017-01-09 14:53:41 -08001499 // It's been set before, but doesn't match. That's bad.
1500 if (is_sctp) {
1501 SafeSetError("Data channel type mismatch. Expected RTP, got SCTP.",
1502 error_desc);
1503 return false;
1504 }
1505 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506}
1507
deadbeef953c2ce2017-01-09 14:53:41 -08001508bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001509 SdpType type,
deadbeef953c2ce2017-01-09 14:53:41 -08001510 std::string* error_desc) {
1511 TRACE_EVENT0("webrtc", "RtpDataChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001512 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001513 RTC_LOG(LS_INFO) << "Setting local data description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001514
Steve Antonb1c1de12017-12-21 15:14:30 -08001515 RTC_DCHECK(content);
1516 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001517 SafeSetError("Can't find data content in local description.", error_desc);
1518 return false;
1519 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001520
Steve Antonb1c1de12017-12-21 15:14:30 -08001521 const DataContentDescription* data = content->as_data();
1522
deadbeef953c2ce2017-01-09 14:53:41 -08001523 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001524 return false;
1525 }
1526
jbauch5869f502017-06-29 12:31:36 -07001527 RtpHeaderExtensions rtp_header_extensions =
1528 GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
1529
Steve Anton3828c062017-12-06 10:34:51 -08001530 if (!SetRtpTransportParameters(content, type, CS_LOCAL, rtp_header_extensions,
1531 error_desc)) {
deadbeef953c2ce2017-01-09 14:53:41 -08001532 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001533 }
1534
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001535 DataRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07001536 RtpParametersFromMediaDescription(data, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001537 if (!media_channel()->SetRecvParameters(recv_params)) {
1538 SafeSetError("Failed to set remote data description recv parameters.",
1539 error_desc);
1540 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001541 }
deadbeef953c2ce2017-01-09 14:53:41 -08001542 for (const DataCodec& codec : data->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07001543 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001544 }
1545 last_recv_params_ = recv_params;
1546
1547 // TODO(pthatcher): Move local streams into DataSendParameters, and
1548 // only give it to the media channel once we have a remote
1549 // description too (without a remote description, we won't be able
1550 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001551 if (!UpdateLocalStreams_w(data->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001552 SafeSetError("Failed to set local data description streams.", error_desc);
1553 return false;
1554 }
1555
1556 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001557 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001558 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001559}
1560
deadbeef953c2ce2017-01-09 14:53:41 -08001561bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001562 SdpType type,
deadbeef953c2ce2017-01-09 14:53:41 -08001563 std::string* error_desc) {
1564 TRACE_EVENT0("webrtc", "RtpDataChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001565 RTC_DCHECK_RUN_ON(worker_thread());
1566 RTC_LOG(LS_INFO) << "Setting remote data description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001567
Steve Antonb1c1de12017-12-21 15:14:30 -08001568 RTC_DCHECK(content);
1569 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001570 SafeSetError("Can't find data content in remote description.", error_desc);
1571 return false;
1572 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001573
Steve Antonb1c1de12017-12-21 15:14:30 -08001574 const DataContentDescription* data = content->as_data();
1575
Zhi Huang801b8682017-11-15 11:36:43 -08001576 // If the remote data doesn't have codecs, it must be empty, so ignore it.
1577 if (!data->has_codecs()) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001578 return true;
1579 }
1580
deadbeef953c2ce2017-01-09 14:53:41 -08001581 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001582 return false;
1583 }
1584
jbauch5869f502017-06-29 12:31:36 -07001585 RtpHeaderExtensions rtp_header_extensions =
1586 GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
1587
Mirko Bonadei675513b2017-11-09 11:09:25 +01001588 RTC_LOG(LS_INFO) << "Setting remote data description";
Steve Anton3828c062017-12-06 10:34:51 -08001589 if (!SetRtpTransportParameters(content, type, CS_REMOTE,
1590 rtp_header_extensions, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001591 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001592 }
1593
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001594 DataSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07001595 RtpSendParametersFromMediaDescription<DataCodec>(data, rtp_header_extensions,
1596 &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001597 if (!media_channel()->SetSendParameters(send_params)) {
1598 SafeSetError("Failed to set remote data description send parameters.",
1599 error_desc);
1600 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001601 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001602 last_send_params_ = send_params;
1603
1604 // TODO(pthatcher): Move remote streams into DataRecvParameters,
1605 // and only give it to the media channel once we have a local
1606 // description too (without a local description, we won't be able to
1607 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001608 if (!UpdateRemoteStreams_w(data->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001609 SafeSetError("Failed to set remote data description streams.",
1610 error_desc);
1611 return false;
1612 }
1613
1614 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001615 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001616 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001617}
1618
deadbeef953c2ce2017-01-09 14:53:41 -08001619void RtpDataChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001620 // Render incoming data if we're the active call, and we have the local
1621 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001622 bool recv = IsReadyToReceiveMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001623 if (!media_channel()->SetReceive(recv)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001624 RTC_LOG(LS_ERROR) << "Failed to SetReceive on data channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001625 }
1626
1627 // Send outgoing data if we're the active call, we have the remote content,
1628 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001629 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001630 if (!media_channel()->SetSend(send)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001631 RTC_LOG(LS_ERROR) << "Failed to SetSend on data channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001632 }
1633
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001634 // Trigger SignalReadyToSendData asynchronously.
1635 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001636
Mirko Bonadei675513b2017-11-09 11:09:25 +01001637 RTC_LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001638}
1639
deadbeef953c2ce2017-01-09 14:53:41 -08001640void RtpDataChannel::OnMessage(rtc::Message* pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001641 switch (pmsg->message_id) {
1642 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001643 DataChannelReadyToSendMessageData* data =
1644 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00001645 ready_to_send_data_ = data->data();
1646 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001647 delete data;
1648 break;
1649 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001650 case MSG_DATARECEIVED: {
1651 DataReceivedMessageData* data =
1652 static_cast<DataReceivedMessageData*>(pmsg->pdata);
deadbeef953c2ce2017-01-09 14:53:41 -08001653 SignalDataReceived(data->params, data->payload);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001654 delete data;
1655 break;
1656 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001657 default:
1658 BaseChannel::OnMessage(pmsg);
1659 break;
1660 }
1661}
1662
deadbeef953c2ce2017-01-09 14:53:41 -08001663void RtpDataChannel::OnDataReceived(const ReceiveDataParams& params,
1664 const char* data,
1665 size_t len) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001666 DataReceivedMessageData* msg = new DataReceivedMessageData(
1667 params, data, len);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001668 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001669}
1670
deadbeef953c2ce2017-01-09 14:53:41 -08001671void RtpDataChannel::OnDataChannelReadyToSend(bool writable) {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001672 // This is usded for congestion control to indicate that the stream is ready
1673 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
1674 // that the transport channel is ready.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001675 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001676 new DataChannelReadyToSendMessageData(writable));
1677}
1678
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001679} // namespace cricket