blob: 9d7bf86afc23eb7c5e8d8ea1a32e45f18b151eaa [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);
147}
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200148
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800149void BaseChannel::DisconnectFromRtpTransport() {
150 RTC_DCHECK(rtp_transport_);
151 rtp_transport_->SignalReadyToSend.disconnect(this);
152 rtp_transport_->SignalPacketReceived.disconnect(this);
153 rtp_transport_->SignalNetworkRouteChanged.disconnect(this);
154 rtp_transport_->SignalWritableState.disconnect(this);
155 rtp_transport_->SignalSentPacket.disconnect(this);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200156}
157
Steve Anton8699a322017-11-06 15:53:33 -0800158void BaseChannel::Init_w(DtlsTransportInternal* rtp_dtls_transport,
deadbeeff5346592017-01-24 21:51:21 -0800159 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800160 rtc::PacketTransportInternal* rtp_packet_transport,
161 rtc::PacketTransportInternal* rtcp_packet_transport) {
Steve Anton8699a322017-11-06 15:53:33 -0800162 RTC_DCHECK_RUN_ON(worker_thread_);
163 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800164 SetTransports_n(rtp_dtls_transport, rtcp_dtls_transport,
165 rtp_packet_transport, rtcp_packet_transport);
166
167 if (rtcp_mux_required_) {
168 rtcp_mux_filter_.SetActive();
169 }
Steve Anton8699a322017-11-06 15:53:33 -0800170 });
171
deadbeeff5346592017-01-24 21:51:21 -0800172 // Both RTP and RTCP channels should be set, we can call SetInterface on
173 // the media channel and it can set network options.
wu@webrtc.orgde305012013-10-31 15:40:38 +0000174 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000175}
176
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800177void BaseChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) {
178 RTC_DCHECK_RUN_ON(worker_thread_);
179 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
180 SetRtpTransport(rtp_transport);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200181
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800182 if (rtcp_mux_required_) {
183 rtcp_mux_filter_.SetActive();
184 }
185 });
186
187 // Both RTP and RTCP channels should be set, we can call SetInterface on
188 // the media channel and it can set network options.
189 media_channel_->SetInterface(this);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200190}
191
wu@webrtc.org78187522013-10-07 23:32:02 +0000192void BaseChannel::Deinit() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200193 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.org78187522013-10-07 23:32:02 +0000194 media_channel_->SetInterface(NULL);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200195 // Packets arrive on the network thread, processing packets calls virtual
196 // functions, so need to stop this process in Deinit that is called in
197 // derived classes destructor.
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800198 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
199 FlushRtcpMessages_n();
200
201 if (dtls_srtp_transport_) {
202 dtls_srtp_transport_->SetDtlsTransports(nullptr, nullptr);
203 } else {
204 rtp_transport_->SetRtpPacketTransport(nullptr);
205 rtp_transport_->SetRtcpPacketTransport(nullptr);
206 }
207 // Clear pending read packets/messages.
208 network_thread_->Clear(&invoker_);
209 network_thread_->Clear(this);
210 });
wu@webrtc.org78187522013-10-07 23:32:02 +0000211}
212
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800213void BaseChannel::SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) {
214 if (!network_thread_->IsCurrent()) {
215 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
216 SetRtpTransport(rtp_transport);
217 return;
218 });
219 }
220
221 RTC_DCHECK(rtp_transport);
222
223 if (rtp_transport_) {
224 DisconnectFromRtpTransport();
225 }
226 rtp_transport_ = rtp_transport;
227 RTC_LOG(LS_INFO) << "Setting the RtpTransport for " << content_name();
228 ConnectToRtpTransport();
229
230 UpdateWritableState_n();
231}
232
zhihuangb2cdd932017-01-19 16:54:25 -0800233void BaseChannel::SetTransports(DtlsTransportInternal* rtp_dtls_transport,
234 DtlsTransportInternal* rtcp_dtls_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800235 network_thread_->Invoke<void>(
236 RTC_FROM_HERE,
237 Bind(&BaseChannel::SetTransports_n, this, rtp_dtls_transport,
238 rtcp_dtls_transport, rtp_dtls_transport, rtcp_dtls_transport));
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000239}
240
deadbeeff5346592017-01-24 21:51:21 -0800241void BaseChannel::SetTransports(
deadbeef5bd5ca32017-02-10 11:31:50 -0800242 rtc::PacketTransportInternal* rtp_packet_transport,
243 rtc::PacketTransportInternal* rtcp_packet_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800244 network_thread_->Invoke<void>(
245 RTC_FROM_HERE, Bind(&BaseChannel::SetTransports_n, this, nullptr, nullptr,
246 rtp_packet_transport, rtcp_packet_transport));
247}
zhihuangf5b251b2017-01-12 19:37:48 -0800248
deadbeeff5346592017-01-24 21:51:21 -0800249void BaseChannel::SetTransports_n(
250 DtlsTransportInternal* rtp_dtls_transport,
251 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800252 rtc::PacketTransportInternal* rtp_packet_transport,
253 rtc::PacketTransportInternal* rtcp_packet_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800254 RTC_DCHECK(network_thread_->IsCurrent());
255 // Validate some assertions about the input.
256 RTC_DCHECK(rtp_packet_transport);
257 RTC_DCHECK_EQ(NeedsRtcpTransport(), rtcp_packet_transport != nullptr);
258 if (rtp_dtls_transport || rtcp_dtls_transport) {
259 // DTLS/non-DTLS pointers should be to the same object.
260 RTC_DCHECK(rtp_dtls_transport == rtp_packet_transport);
261 RTC_DCHECK(rtcp_dtls_transport == rtcp_packet_transport);
262 // Can't go from non-DTLS to DTLS.
zsteine8ab5432017-07-12 11:48:11 -0700263 RTC_DCHECK(!rtp_transport_->rtp_packet_transport() || rtp_dtls_transport_);
deadbeeff5346592017-01-24 21:51:21 -0800264 } else {
265 // Can't go from DTLS to non-DTLS.
266 RTC_DCHECK(!rtp_dtls_transport_);
267 }
268 // Transport names should be the same.
zhihuangb2cdd932017-01-19 16:54:25 -0800269 if (rtp_dtls_transport && rtcp_dtls_transport) {
270 RTC_DCHECK(rtp_dtls_transport->transport_name() ==
271 rtcp_dtls_transport->transport_name());
zhihuangb2cdd932017-01-19 16:54:25 -0800272 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800273
274 if (rtp_packet_transport == rtp_transport_->rtp_packet_transport()) {
275 // Nothing to do if transport isn't changing.
276 return;
277 }
278
deadbeeff5346592017-01-24 21:51:21 -0800279 std::string debug_name;
280 if (rtp_dtls_transport) {
281 transport_name_ = rtp_dtls_transport->transport_name();
282 debug_name = transport_name_;
283 } else {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800284 debug_name = rtp_packet_transport->transport_name();
deadbeeff5346592017-01-24 21:51:21 -0800285 }
deadbeefac22f702017-01-12 21:59:29 -0800286 // If this BaseChannel doesn't require RTCP mux and we haven't fully
287 // negotiated RTCP mux, we need an RTCP transport.
deadbeeff5346592017-01-24 21:51:21 -0800288 if (rtcp_packet_transport) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100289 RTC_LOG(LS_INFO) << "Setting RTCP Transport for " << content_name()
290 << " on " << debug_name << " transport "
291 << rtcp_packet_transport;
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800292 SetTransport_n(/*rtcp=*/true, rtcp_dtls_transport, rtcp_packet_transport);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000293 }
294
Mirko Bonadei675513b2017-11-09 11:09:25 +0100295 RTC_LOG(LS_INFO) << "Setting RTP Transport for " << content_name() << " on "
296 << debug_name << " transport " << rtp_packet_transport;
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800297 SetTransport_n(/*rtcp=*/false, rtp_dtls_transport, rtp_packet_transport);
298
299 // Set DtlsTransport/PacketTransport for RTP-level transport.
300 if ((rtp_dtls_transport_ || rtcp_dtls_transport_) && dtls_srtp_transport_) {
301 // When setting the transport with non-null |dtls_srtp_transport_|, we are
302 // using DTLS-SRTP. This could happen for bundling. If the
303 // |dtls_srtp_transport| is null, we cannot tell if it doing DTLS-SRTP or
304 // SDES until the description is set. So don't call |EnableDtlsSrtp_n| here.
305 dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport,
306 rtcp_dtls_transport);
307 } else {
308 rtp_transport_->SetRtpPacketTransport(rtp_packet_transport);
309 rtp_transport_->SetRtcpPacketTransport(rtcp_packet_transport);
310 }
guoweis46383312015-12-17 16:45:59 -0800311
deadbeefcbecd352015-09-23 11:50:27 -0700312 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700313 // setting new transport channels.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200314 UpdateWritableState_n();
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000315}
316
deadbeeff5346592017-01-24 21:51:21 -0800317void BaseChannel::SetTransport_n(
318 bool rtcp,
319 DtlsTransportInternal* new_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800320 rtc::PacketTransportInternal* new_packet_transport) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200321 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huang942bc2e2017-11-13 13:26:07 -0800322 if (new_dtls_transport) {
323 RTC_DCHECK(new_dtls_transport == new_packet_transport);
324 }
deadbeeff5346592017-01-24 21:51:21 -0800325 DtlsTransportInternal*& old_dtls_transport =
zhihuangb2cdd932017-01-19 16:54:25 -0800326 rtcp ? rtcp_dtls_transport_ : rtp_dtls_transport_;
zsteind48dbda2017-04-04 19:45:57 -0700327 rtc::PacketTransportInternal* old_packet_transport =
zsteine8ab5432017-07-12 11:48:11 -0700328 rtcp ? rtp_transport_->rtcp_packet_transport()
329 : rtp_transport_->rtp_packet_transport();
zhihuangb2cdd932017-01-19 16:54:25 -0800330
deadbeeff5346592017-01-24 21:51:21 -0800331 if (!old_packet_transport && !new_packet_transport) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700332 // Nothing to do.
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000333 return;
334 }
zhihuangb2cdd932017-01-19 16:54:25 -0800335
deadbeeff5346592017-01-24 21:51:21 -0800336 RTC_DCHECK(old_packet_transport != new_packet_transport);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000337
deadbeeff5346592017-01-24 21:51:21 -0800338 old_dtls_transport = new_dtls_transport;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000339
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800340 // If there's no new transport, we're done.
deadbeeff5346592017-01-24 21:51:21 -0800341 if (!new_packet_transport) {
342 return;
343 }
344
345 if (rtcp && new_dtls_transport) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700346 RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_active()))
347 << "Setting RTCP for DTLS/SRTP after the DTLS is active "
deadbeeff5346592017-01-24 21:51:21 -0800348 << "should never happen.";
349 }
zstein56162b92017-04-24 16:54:35 -0700350
deadbeeff5346592017-01-24 21:51:21 -0800351 auto& socket_options = rtcp ? rtcp_socket_options_ : socket_options_;
352 for (const auto& pair : socket_options) {
353 new_packet_transport->SetOption(pair.first, pair.second);
guoweis46383312015-12-17 16:45:59 -0800354 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000355}
356
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000357bool BaseChannel::Enable(bool enable) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700358 worker_thread_->Invoke<void>(
359 RTC_FROM_HERE,
360 Bind(enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
361 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000362 return true;
363}
364
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000365bool BaseChannel::AddRecvStream(const StreamParams& sp) {
stefanf79ade12017-06-02 06:44:03 -0700366 return InvokeOnWorker<bool>(RTC_FROM_HERE,
367 Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368}
369
Peter Boström0c4e06b2015-10-07 12:23:21 +0200370bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
stefanf79ade12017-06-02 06:44:03 -0700371 return InvokeOnWorker<bool>(
372 RTC_FROM_HERE, Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000373}
374
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000375bool BaseChannel::AddSendStream(const StreamParams& sp) {
stefanf79ade12017-06-02 06:44:03 -0700376 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700377 RTC_FROM_HERE, Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000378}
379
Peter Boström0c4e06b2015-10-07 12:23:21 +0200380bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
stefanf79ade12017-06-02 06:44:03 -0700381 return InvokeOnWorker<bool>(
382 RTC_FROM_HERE,
383 Bind(&MediaChannel::RemoveSendStream, media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000384}
385
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000386bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800387 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000388 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100389 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
stefanf79ade12017-06-02 06:44:03 -0700390 return InvokeOnWorker<bool>(
391 RTC_FROM_HERE,
Steve Anton3828c062017-12-06 10:34:51 -0800392 Bind(&BaseChannel::SetLocalContent_w, this, content, type, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000393}
394
395bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800396 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000397 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100398 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
stefanf79ade12017-06-02 06:44:03 -0700399 return InvokeOnWorker<bool>(
Steve Anton3828c062017-12-06 10:34:51 -0800400 RTC_FROM_HERE,
401 Bind(&BaseChannel::SetRemoteContent_w, this, content, type, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000402}
403
zhihuangf5b251b2017-01-12 19:37:48 -0800404bool BaseChannel::NeedsRtcpTransport() {
deadbeefac22f702017-01-12 21:59:29 -0800405 // If this BaseChannel doesn't require RTCP mux and we haven't fully
406 // negotiated RTCP mux, we need an RTCP transport.
zstein56162b92017-04-24 16:54:35 -0700407 return !rtcp_mux_required_ && !rtcp_mux_filter_.IsFullyActive();
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000408}
409
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700410bool BaseChannel::IsReadyToReceiveMedia_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000411 // Receive data if we are enabled and have local content,
Steve Anton4e70a722017-11-28 14:57:10 -0800412 return enabled() &&
413 webrtc::RtpTransceiverDirectionHasRecv(local_content_direction_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000414}
415
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700416bool BaseChannel::IsReadyToSendMedia_w() const {
417 // Need to access some state updated on the network thread.
418 return network_thread_->Invoke<bool>(
419 RTC_FROM_HERE, Bind(&BaseChannel::IsReadyToSendMedia_n, this));
420}
421
422bool BaseChannel::IsReadyToSendMedia_n() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000423 // Send outgoing data if we are enabled, have local and remote content,
424 // and we have had some form of connectivity.
Steve Anton4e70a722017-11-28 14:57:10 -0800425 return enabled() &&
426 webrtc::RtpTransceiverDirectionHasRecv(remote_content_direction_) &&
427 webrtc::RtpTransceiverDirectionHasSend(local_content_direction_) &&
Zhi Huangcf990f52017-09-22 12:12:30 -0700428 was_ever_writable() && (srtp_active() || !ShouldSetupDtlsSrtp_n());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000429}
430
jbaucheec21bd2016-03-20 06:15:43 -0700431bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700432 const rtc::PacketOptions& options) {
433 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000434}
435
jbaucheec21bd2016-03-20 06:15:43 -0700436bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700437 const rtc::PacketOptions& options) {
438 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000439}
440
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000441int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000442 int value) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200443 return network_thread_->Invoke<int>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700444 RTC_FROM_HERE, Bind(&BaseChannel::SetOption_n, this, type, opt, value));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200445}
446
447int BaseChannel::SetOption_n(SocketType type,
448 rtc::Socket::Option opt,
449 int value) {
450 RTC_DCHECK(network_thread_->IsCurrent());
deadbeef5bd5ca32017-02-10 11:31:50 -0800451 rtc::PacketTransportInternal* transport = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000452 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000453 case ST_RTP:
zsteine8ab5432017-07-12 11:48:11 -0700454 transport = rtp_transport_->rtp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700455 socket_options_.push_back(
456 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000457 break;
458 case ST_RTCP:
zsteine8ab5432017-07-12 11:48:11 -0700459 transport = rtp_transport_->rtcp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700460 rtcp_socket_options_.push_back(
461 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000462 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000463 }
deadbeeff5346592017-01-24 21:51:21 -0800464 return transport ? transport->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000465}
466
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800467void BaseChannel::OnWritableState(bool writable) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200468 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800469 if (writable) {
470 // This is used to cover the scenario when the DTLS handshake is completed
471 // and DtlsTransport becomes writable before the remote description is set.
472 if (ShouldSetupDtlsSrtp_n()) {
473 EnableDtlsSrtp_n();
Zhi Huangcf990f52017-09-22 12:12:30 -0700474 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800475 ChannelWritable_n();
476 } else {
477 ChannelNotWritable_n();
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800478 }
479}
480
Zhi Huang942bc2e2017-11-13 13:26:07 -0800481void BaseChannel::OnNetworkRouteChanged(
482 rtc::Optional<rtc::NetworkRoute> network_route) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200483 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huang942bc2e2017-11-13 13:26:07 -0800484 rtc::NetworkRoute new_route;
485 if (network_route) {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800486 new_route = *(network_route);
Zhi Huang8c316c12017-11-13 21:13:45 +0000487 }
Zhi Huang942bc2e2017-11-13 13:26:07 -0800488 // Note: When the RTCP-muxing is not enabled, RTCP transport and RTP transport
489 // use the same transport name and MediaChannel::OnNetworkRouteChanged cannot
490 // work correctly. Intentionally leave it broken to simplify the code and
491 // encourage the users to stop using non-muxing RTCP.
Steve Anton8699a322017-11-06 15:53:33 -0800492 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_, [=] {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800493 media_channel_->OnNetworkRouteChanged(transport_name_, new_route);
Steve Anton8699a322017-11-06 15:53:33 -0800494 });
Honghai Zhangcc411c02016-03-29 17:27:21 -0700495}
496
zstein56162b92017-04-24 16:54:35 -0700497void BaseChannel::OnTransportReadyToSend(bool ready) {
Steve Anton8699a322017-11-06 15:53:33 -0800498 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
499 [=] { media_channel_->OnReadyToSend(ready); });
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000500}
501
stefanc1aeaf02015-10-15 07:26:07 -0700502bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700503 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700504 const rtc::PacketOptions& options) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200505 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
506 // If the thread is not our network thread, we will post to our network
507 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000508 // synchronize access to all the pieces of the send path, including
509 // SRTP and the inner workings of the transport channels.
510 // The only downside is that we can't return a proper failure code if
511 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200512 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000513 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200514 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
515 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800516 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700517 data->options = options;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700518 network_thread_->Post(RTC_FROM_HERE, this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000519 return true;
520 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200521 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000522
523 // Now that we are on the correct thread, ensure we have a place to send this
524 // packet before doing anything. (We might get RTCP packets that we don't
525 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
526 // transport.
zsteine8ab5432017-07-12 11:48:11 -0700527 if (!rtp_transport_->IsWritable(rtcp)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528 return false;
529 }
530
531 // Protect ourselves against crazy data.
532 if (!ValidPacket(rtcp, packet)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100533 RTC_LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
534 << RtpRtcpStringLiteral(rtcp)
535 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000536 return false;
537 }
538
Zhi Huangcf990f52017-09-22 12:12:30 -0700539 if (!srtp_active()) {
540 if (srtp_required_) {
541 // The audio/video engines may attempt to send RTCP packets as soon as the
542 // streams are created, so don't treat this as an error for RTCP.
543 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6809
544 if (rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000545 return false;
546 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700547 // However, there shouldn't be any RTP packets sent before SRTP is set up
548 // (and SetSend(true) is called).
Mirko Bonadei675513b2017-11-09 11:09:25 +0100549 RTC_LOG(LS_ERROR)
550 << "Can't send outgoing RTP packet when SRTP is inactive"
551 << " and crypto is required";
Zhi Huangcf990f52017-09-22 12:12:30 -0700552 RTC_NOTREACHED();
deadbeef8f425f92016-12-01 12:26:27 -0800553 return false;
554 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800555
556 std::string packet_type = rtcp ? "RTCP" : "RTP";
557 RTC_LOG(LS_WARNING) << "Sending an " << packet_type
558 << " packet without encryption.";
559 } else {
560 // Make sure we didn't accidentally send any packets without encryption.
561 RTC_DCHECK(rtp_transport_ == sdes_transport_.get() ||
562 rtp_transport_ == dtls_srtp_transport_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000563 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000564 // Bon voyage.
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800565 return rtcp ? rtp_transport_->SendRtcpPacket(packet, options, PF_SRTP_BYPASS)
566 : rtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000567}
568
zstein3dcf0e92017-06-01 13:22:42 -0700569bool BaseChannel::HandlesPayloadType(int packet_type) const {
zsteine8ab5432017-07-12 11:48:11 -0700570 return rtp_transport_->HandlesPayloadType(packet_type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000571}
572
zstein3dcf0e92017-06-01 13:22:42 -0700573void BaseChannel::OnPacketReceived(bool rtcp,
zstein634977b2017-07-14 12:30:04 -0700574 rtc::CopyOnWriteBuffer* packet,
zstein3dcf0e92017-06-01 13:22:42 -0700575 const rtc::PacketTime& packet_time) {
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000576 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000577 has_received_packet_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700578 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000579 }
580
Zhi Huangcf990f52017-09-22 12:12:30 -0700581 if (!srtp_active() && srtp_required_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000582 // Our session description indicates that SRTP is required, but we got a
583 // packet before our SRTP filter is active. This means either that
584 // a) we got SRTP packets before we received the SDES keys, in which case
585 // we can't decrypt it anyway, or
586 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
zhihuangb2cdd932017-01-19 16:54:25 -0800587 // transports, so we haven't yet extracted keys, even if DTLS did
588 // complete on the transport that the packets are being sent on. It's
589 // really good practice to wait for both RTP and RTCP to be good to go
590 // before sending media, to prevent weird failure modes, so it's fine
591 // for us to just eat packets here. This is all sidestepped if RTCP mux
592 // is used anyway.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100593 RTC_LOG(LS_WARNING)
594 << "Can't process incoming " << RtpRtcpStringLiteral(rtcp)
595 << " packet when SRTP is inactive and crypto is required";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000596 return;
597 }
598
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200599 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700600 RTC_FROM_HERE, worker_thread_,
zstein634977b2017-07-14 12:30:04 -0700601 Bind(&BaseChannel::ProcessPacket, this, rtcp, *packet, packet_time));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200602}
603
zstein3dcf0e92017-06-01 13:22:42 -0700604void BaseChannel::ProcessPacket(bool rtcp,
605 const rtc::CopyOnWriteBuffer& packet,
606 const rtc::PacketTime& packet_time) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200607 RTC_DCHECK(worker_thread_->IsCurrent());
zstein3dcf0e92017-06-01 13:22:42 -0700608
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200609 // Need to copy variable because OnRtcpReceived/OnPacketReceived
610 // requires non-const pointer to buffer. This doesn't memcpy the actual data.
611 rtc::CopyOnWriteBuffer data(packet);
612 if (rtcp) {
613 media_channel_->OnRtcpReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000614 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200615 media_channel_->OnPacketReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000616 }
617}
618
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000619void BaseChannel::EnableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700620 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000621 if (enabled_)
622 return;
623
Mirko Bonadei675513b2017-11-09 11:09:25 +0100624 RTC_LOG(LS_INFO) << "Channel enabled";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000625 enabled_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700626 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000627}
628
629void BaseChannel::DisableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700630 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000631 if (!enabled_)
632 return;
633
Mirko Bonadei675513b2017-11-09 11:09:25 +0100634 RTC_LOG(LS_INFO) << "Channel disabled";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000635 enabled_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700636 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000637}
638
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200639void BaseChannel::UpdateWritableState_n() {
zsteind48dbda2017-04-04 19:45:57 -0700640 rtc::PacketTransportInternal* rtp_packet_transport =
zsteine8ab5432017-07-12 11:48:11 -0700641 rtp_transport_->rtp_packet_transport();
zsteind48dbda2017-04-04 19:45:57 -0700642 rtc::PacketTransportInternal* rtcp_packet_transport =
zsteine8ab5432017-07-12 11:48:11 -0700643 rtp_transport_->rtcp_packet_transport();
zsteind48dbda2017-04-04 19:45:57 -0700644 if (rtp_packet_transport && rtp_packet_transport->writable() &&
645 (!rtcp_packet_transport || rtcp_packet_transport->writable())) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200646 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700647 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200648 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700649 }
650}
651
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200652void BaseChannel::ChannelWritable_n() {
653 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800654 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000655 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800656 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000657
Mirko Bonadei675513b2017-11-09 11:09:25 +0100658 RTC_LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
659 << (was_ever_writable_ ? "" : " for the first time");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000660
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000661 was_ever_writable_ = true;
662 writable_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700663 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000664}
665
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200666bool BaseChannel::ShouldSetupDtlsSrtp_n() const {
zhihuangb2cdd932017-01-19 16:54:25 -0800667 // Since DTLS is applied to all transports, checking RTP should be enough.
668 return rtp_dtls_transport_ && rtp_dtls_transport_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669}
670
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200671void BaseChannel::ChannelNotWritable_n() {
672 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673 if (!writable_)
674 return;
675
Mirko Bonadei675513b2017-11-09 11:09:25 +0100676 RTC_LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000677 writable_ = false;
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::SetRtpTransportParameters(
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700682 const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800683 SdpType type,
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700684 ContentSource src,
jbauch5869f502017-06-29 12:31:36 -0700685 const RtpHeaderExtensions& extensions,
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700686 std::string* error_desc) {
jbauch5869f502017-06-29 12:31:36 -0700687 std::vector<int> encrypted_extension_ids;
688 for (const webrtc::RtpExtension& extension : extensions) {
689 if (extension.encrypt) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100690 RTC_LOG(LS_INFO) << "Using " << (src == CS_LOCAL ? "local" : "remote")
691 << " encrypted extension: " << extension.ToString();
jbauch5869f502017-06-29 12:31:36 -0700692 encrypted_extension_ids.push_back(extension.id);
693 }
694 }
695
deadbeef7af91dd2016-12-13 11:29:11 -0800696 // Cache srtp_required_ for belt and suspenders check on SendPacket
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200697 return network_thread_->Invoke<bool>(
Steve Anton3828c062017-12-06 10:34:51 -0800698 RTC_FROM_HERE,
699 Bind(&BaseChannel::SetRtpTransportParameters_n, this, content, type, src,
700 encrypted_extension_ids, error_desc));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200701}
702
703bool BaseChannel::SetRtpTransportParameters_n(
704 const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800705 SdpType type,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200706 ContentSource src,
jbauch5869f502017-06-29 12:31:36 -0700707 const std::vector<int>& encrypted_extension_ids,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200708 std::string* error_desc) {
709 RTC_DCHECK(network_thread_->IsCurrent());
710
Steve Anton3828c062017-12-06 10:34:51 -0800711 if (!SetSrtp_n(content->cryptos(), type, src, encrypted_extension_ids,
712 error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700713 return false;
714 }
715
Steve Anton3828c062017-12-06 10:34:51 -0800716 if (!SetRtcpMux_n(content->rtcp_mux(), type, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700717 return false;
718 }
719
720 return true;
721}
722
zhihuangb2cdd932017-01-19 16:54:25 -0800723// |dtls| will be set to true if DTLS is active for transport and crypto is
724// empty.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200725bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
726 bool* dtls,
727 std::string* error_desc) {
deadbeeff5346592017-01-24 21:51:21 -0800728 *dtls = rtp_dtls_transport_ && rtp_dtls_transport_->IsDtlsActive();
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000729 if (*dtls && !cryptos.empty()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200730 SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000731 return false;
732 }
733 return true;
734}
735
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800736void BaseChannel::EnableSdes_n() {
737 if (sdes_transport_) {
738 return;
Zhi Huangcf990f52017-09-22 12:12:30 -0700739 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800740 // DtlsSrtpTransport and SrtpTransport shouldn't be enabled at the same
741 // time.
742 RTC_DCHECK(!dtls_srtp_transport_);
743 RTC_DCHECK(unencrypted_rtp_transport_);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800744 sdes_transport_ = rtc::MakeUnique<webrtc::SrtpTransport>(
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800745 std::move(unencrypted_rtp_transport_));
Zhi Huangd7455782017-11-30 14:50:52 -0800746#if defined(ENABLE_EXTERNAL_AUTH)
747 sdes_transport_->EnableExternalAuth();
748#endif
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800749 SetRtpTransport(sdes_transport_.get());
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800750 RTC_LOG(LS_INFO) << "Wrapping RtpTransport in SrtpTransport.";
751}
752
753void BaseChannel::EnableDtlsSrtp_n() {
754 if (dtls_srtp_transport_) {
755 return;
756 }
757 // DtlsSrtpTransport and SrtpTransport shouldn't be enabled at the same
758 // time.
759 RTC_DCHECK(!sdes_transport_);
760 RTC_DCHECK(unencrypted_rtp_transport_);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800761
762 auto srtp_transport = rtc::MakeUnique<webrtc::SrtpTransport>(
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800763 std::move(unencrypted_rtp_transport_));
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800764#if defined(ENABLE_EXTERNAL_AUTH)
765 srtp_transport->EnableExternalAuth();
766#endif
767 dtls_srtp_transport_ =
768 rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport));
769
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800770 SetRtpTransport(dtls_srtp_transport_.get());
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800771 if (cached_send_extension_ids_) {
772 dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
773 *cached_send_extension_ids_);
774 }
775 if (cached_recv_extension_ids_) {
776 dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
777 *cached_recv_extension_ids_);
778 }
779 // Set the DtlsTransport and the |dtls_srtp_transport_| will handle the DTLS
780 // relate signal internally.
781 RTC_DCHECK(rtp_dtls_transport_);
782 dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport_,
783 rtcp_dtls_transport_);
784
785 RTC_LOG(LS_INFO) << "Wrapping SrtpTransport in DtlsSrtpTransport.";
Zhi Huangcf990f52017-09-22 12:12:30 -0700786}
787
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200788bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
Steve Anton3828c062017-12-06 10:34:51 -0800789 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000790 ContentSource src,
jbauch5869f502017-06-29 12:31:36 -0700791 const std::vector<int>& encrypted_extension_ids,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000792 std::string* error_desc) {
Peter Boströmca8b4042016-03-08 14:24:13 -0800793 TRACE_EVENT0("webrtc", "BaseChannel::SetSrtp_w");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000794 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000795 bool dtls = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200796 ret = CheckSrtpConfig_n(cryptos, &dtls, error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000797 if (!ret) {
798 return false;
799 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700800
801 // If SRTP was not required, but we're setting a description that uses SDES,
802 // we need to upgrade to an SrtpTransport.
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800803 if (!sdes_transport_ && !dtls && !cryptos.empty()) {
804 EnableSdes_n();
Zhi Huangcf990f52017-09-22 12:12:30 -0700805 }
Zhi Huangc99b6c72017-11-10 16:44:46 -0800806
Steve Anton3828c062017-12-06 10:34:51 -0800807 if ((type == SdpType::kAnswer || type == SdpType::kPrAnswer) && dtls) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800808 EnableDtlsSrtp_n();
809 }
Zhi Huangc99b6c72017-11-10 16:44:46 -0800810
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800811 UpdateEncryptedHeaderExtensionIds(src, encrypted_extension_ids);
812
813 if (!dtls) {
Steve Anton3828c062017-12-06 10:34:51 -0800814 switch (type) {
815 case SdpType::kOffer:
Zhi Huangcf990f52017-09-22 12:12:30 -0700816 ret = sdes_negotiator_.SetOffer(cryptos, src);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800817 break;
Steve Anton3828c062017-12-06 10:34:51 -0800818 case SdpType::kPrAnswer:
Zhi Huangcf990f52017-09-22 12:12:30 -0700819 ret = sdes_negotiator_.SetProvisionalAnswer(cryptos, src);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800820 break;
Steve Anton3828c062017-12-06 10:34:51 -0800821 case SdpType::kAnswer:
Zhi Huangcf990f52017-09-22 12:12:30 -0700822 ret = sdes_negotiator_.SetAnswer(cryptos, src);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800823 break;
824 default:
825 break;
826 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700827
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800828 // If setting an SDES answer succeeded, apply the negotiated parameters
829 // to the SRTP transport.
Steve Anton3828c062017-12-06 10:34:51 -0800830 if ((type == SdpType::kPrAnswer || type == SdpType::kAnswer) && ret) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800831 if (sdes_negotiator_.send_cipher_suite() &&
832 sdes_negotiator_.recv_cipher_suite()) {
833 RTC_DCHECK(cached_send_extension_ids_);
834 RTC_DCHECK(cached_recv_extension_ids_);
835 ret = sdes_transport_->SetRtpParams(
836 *(sdes_negotiator_.send_cipher_suite()),
837 sdes_negotiator_.send_key().data(),
838 static_cast<int>(sdes_negotiator_.send_key().size()),
839 *(cached_send_extension_ids_),
840 *(sdes_negotiator_.recv_cipher_suite()),
841 sdes_negotiator_.recv_key().data(),
842 static_cast<int>(sdes_negotiator_.recv_key().size()),
843 *(cached_recv_extension_ids_));
844 } else {
845 RTC_LOG(LS_INFO) << "No crypto keys are provided for SDES.";
Steve Anton3828c062017-12-06 10:34:51 -0800846 if (type == SdpType::kAnswer && sdes_transport_) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800847 // Explicitly reset the |sdes_transport_| if no crypto param is
848 // provided in the answer. No need to call |ResetParams()| for
849 // |sdes_negotiator_| because it resets the params inside |SetAnswer|.
850 sdes_transport_->ResetParams();
851 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700852 }
853 }
854 }
855
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000856 if (!ret) {
Zhi Huangc99b6c72017-11-10 16:44:46 -0800857 SafeSetError("Failed to setup SRTP.", error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000858 return false;
859 }
860 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861}
862
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200863bool BaseChannel::SetRtcpMux_n(bool enable,
Steve Anton3828c062017-12-06 10:34:51 -0800864 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000865 ContentSource src,
866 std::string* error_desc) {
deadbeef8e814d72017-01-13 11:34:39 -0800867 // Provide a more specific error message for the RTCP mux "require" policy
868 // case.
zstein56162b92017-04-24 16:54:35 -0700869 if (rtcp_mux_required_ && !enable) {
deadbeef8e814d72017-01-13 11:34:39 -0800870 SafeSetError(
871 "rtcpMuxPolicy is 'require', but media description does not "
872 "contain 'a=rtcp-mux'.",
873 error_desc);
874 return false;
875 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000876 bool ret = false;
Steve Anton3828c062017-12-06 10:34:51 -0800877 switch (type) {
878 case SdpType::kOffer:
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000879 ret = rtcp_mux_filter_.SetOffer(enable, src);
880 break;
Steve Anton3828c062017-12-06 10:34:51 -0800881 case SdpType::kPrAnswer:
zhihuangb2cdd932017-01-19 16:54:25 -0800882 // This may activate RTCP muxing, but we don't yet destroy the transport
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700883 // because the final answer may deactivate it.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000884 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
885 break;
Steve Anton3828c062017-12-06 10:34:51 -0800886 case SdpType::kAnswer:
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000887 ret = rtcp_mux_filter_.SetAnswer(enable, src);
888 if (ret && rtcp_mux_filter_.IsActive()) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800889 ActivateRtcpMux();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000890 }
891 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000892 default:
893 break;
894 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000895 if (!ret) {
896 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
897 return false;
898 }
zsteine8ab5432017-07-12 11:48:11 -0700899 rtp_transport_->SetRtcpMuxEnabled(rtcp_mux_filter_.IsActive());
Steve Anton3828c062017-12-06 10:34:51 -0800900 // |rtcp_mux_filter_| can be active if |action| is SdpType::kPrAnswer or
901 // SdpType::kAnswer, but we only want to tear down the RTCP transport if we
902 // received a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000903 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000904 // If the RTP transport is already writable, then so are we.
zsteine8ab5432017-07-12 11:48:11 -0700905 if (rtp_transport_->rtp_packet_transport()->writable()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200906 ChannelWritable_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000907 }
908 }
909
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000910 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000911}
912
913bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700914 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -0800915 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000916}
917
Peter Boström0c4e06b2015-10-07 12:23:21 +0200918bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700919 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000920 return media_channel()->RemoveRecvStream(ssrc);
921}
922
923bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
Steve Anton3828c062017-12-06 10:34:51 -0800924 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000925 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926 // Check for streams that have been removed.
927 bool ret = true;
928 for (StreamParamsVec::const_iterator it = local_streams_.begin();
929 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +0000930 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000931 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000932 std::ostringstream desc;
933 desc << "Failed to remove send stream with ssrc "
934 << it->first_ssrc() << ".";
935 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000936 ret = false;
937 }
938 }
939 }
940 // Check for new streams.
941 for (StreamParamsVec::const_iterator it = streams.begin();
942 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +0000943 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000944 if (media_channel()->AddSendStream(*it)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100945 RTC_LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000946 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000947 std::ostringstream desc;
948 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
949 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000950 ret = false;
951 }
952 }
953 }
954 local_streams_ = streams;
955 return ret;
956}
957
958bool BaseChannel::UpdateRemoteStreams_w(
959 const std::vector<StreamParams>& streams,
Steve Anton3828c062017-12-06 10:34:51 -0800960 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000961 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000962 // Check for streams that have been removed.
963 bool ret = true;
964 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
965 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +0000966 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000967 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000968 std::ostringstream desc;
969 desc << "Failed to remove remote stream with ssrc "
970 << it->first_ssrc() << ".";
971 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000972 ret = false;
973 }
974 }
975 }
976 // Check for new streams.
977 for (StreamParamsVec::const_iterator it = streams.begin();
978 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +0000979 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000980 if (AddRecvStream_w(*it)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100981 RTC_LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000982 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000983 std::ostringstream desc;
984 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
985 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 ret = false;
987 }
988 }
989 }
990 remote_streams_ = streams;
991 return ret;
992}
993
jbauch5869f502017-06-29 12:31:36 -0700994RtpHeaderExtensions BaseChannel::GetFilteredRtpHeaderExtensions(
995 const RtpHeaderExtensions& extensions) {
996 if (!rtp_dtls_transport_ ||
997 !rtp_dtls_transport_->crypto_options()
998 .enable_encrypted_rtp_header_extensions) {
999 RtpHeaderExtensions filtered;
1000 auto pred = [](const webrtc::RtpExtension& extension) {
1001 return !extension.encrypt;
1002 };
1003 std::copy_if(extensions.begin(), extensions.end(),
1004 std::back_inserter(filtered), pred);
1005 return filtered;
1006 }
1007
1008 return webrtc::RtpExtension::FilterDuplicateNonEncrypted(extensions);
1009}
1010
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001011void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w(
isheriff6f8d6862016-05-26 11:24:55 -07001012 const std::vector<webrtc::RtpExtension>& extensions) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001013// Absolute Send Time extension id is used only with external auth,
1014// so do not bother searching for it and making asyncronious call to set
1015// something that is not used.
1016#if defined(ENABLE_EXTERNAL_AUTH)
isheriff6f8d6862016-05-26 11:24:55 -07001017 const webrtc::RtpExtension* send_time_extension =
jbauch5869f502017-06-29 12:31:36 -07001018 webrtc::RtpExtension::FindHeaderExtensionByUri(
1019 extensions, webrtc::RtpExtension::kAbsSendTimeUri);
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001020 int rtp_abs_sendtime_extn_id =
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001021 send_time_extension ? send_time_extension->id : -1;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001022 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001023 RTC_FROM_HERE, network_thread_,
1024 Bind(&BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n, this,
1025 rtp_abs_sendtime_extn_id));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001026#endif
1027}
1028
1029void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n(
1030 int rtp_abs_sendtime_extn_id) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001031 if (sdes_transport_) {
1032 sdes_transport_->CacheRtpAbsSendTimeHeaderExtension(
Zhi Huangcf990f52017-09-22 12:12:30 -07001033 rtp_abs_sendtime_extn_id);
Zhi Huang2a4d70c2017-11-29 15:41:59 -08001034 } else if (dtls_srtp_transport_) {
1035 dtls_srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
1036 rtp_abs_sendtime_extn_id);
Zhi Huangcf990f52017-09-22 12:12:30 -07001037 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001038 RTC_LOG(LS_WARNING)
1039 << "Trying to cache the Absolute Send Time extension id "
1040 "but the SRTP is not active.";
Zhi Huangcf990f52017-09-22 12:12:30 -07001041 }
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001042}
1043
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001044void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001045 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001046 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001047 case MSG_SEND_RTP_PACKET:
1048 case MSG_SEND_RTCP_PACKET: {
1049 RTC_DCHECK(network_thread_->IsCurrent());
1050 SendPacketMessageData* data =
1051 static_cast<SendPacketMessageData*>(pmsg->pdata);
1052 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
1053 SendPacket(rtcp, &data->packet, data->options);
1054 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001055 break;
1056 }
1057 case MSG_FIRSTPACKETRECEIVED: {
1058 SignalFirstPacketReceived(this);
1059 break;
1060 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001061 }
1062}
1063
zstein3dcf0e92017-06-01 13:22:42 -07001064void BaseChannel::AddHandledPayloadType(int payload_type) {
zsteine8ab5432017-07-12 11:48:11 -07001065 rtp_transport_->AddHandledPayloadType(payload_type);
zstein3dcf0e92017-06-01 13:22:42 -07001066}
1067
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001068void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001069 // Flush all remaining RTCP messages. This should only be called in
1070 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001071 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001072 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001073 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
1074 for (const auto& message : rtcp_messages) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001075 network_thread_->Send(RTC_FROM_HERE, this, MSG_SEND_RTCP_PACKET,
1076 message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001077 }
1078}
1079
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001080void BaseChannel::SignalSentPacket_n(const rtc::SentPacket& sent_packet) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001081 RTC_DCHECK(network_thread_->IsCurrent());
1082 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001083 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001084 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
1085}
1086
1087void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
1088 RTC_DCHECK(worker_thread_->IsCurrent());
1089 SignalSentPacket(sent_packet);
1090}
1091
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001092void BaseChannel::UpdateEncryptedHeaderExtensionIds(
Zhi Huangc99b6c72017-11-10 16:44:46 -08001093 cricket::ContentSource source,
1094 const std::vector<int>& extension_ids) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001095 if (source == ContentSource::CS_LOCAL) {
1096 cached_recv_extension_ids_ = std::move(extension_ids);
1097 if (dtls_srtp_transport_) {
1098 dtls_srtp_transport_->UpdateRecvEncryptedHeaderExtensionIds(
1099 extension_ids);
1100 }
1101 } else {
1102 cached_send_extension_ids_ = std::move(extension_ids);
1103 if (dtls_srtp_transport_) {
1104 dtls_srtp_transport_->UpdateSendEncryptedHeaderExtensionIds(
1105 extension_ids);
1106 }
1107 }
Zhi Huangc99b6c72017-11-10 16:44:46 -08001108}
1109
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001110void BaseChannel::ActivateRtcpMux() {
1111 // We permanently activated RTCP muxing; signal that we no longer need
1112 // the RTCP transport.
1113 std::string debug_name =
1114 transport_name_.empty()
1115 ? rtp_transport_->rtp_packet_transport()->transport_name()
1116 : transport_name_;
1117 RTC_LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
1118 << "; no longer need RTCP transport for " << debug_name;
1119 if (rtp_transport_->rtcp_packet_transport()) {
1120 SetTransport_n(/*rtcp=*/true, nullptr, nullptr);
1121 if (dtls_srtp_transport_) {
1122 RTC_DCHECK(rtp_dtls_transport_);
1123 dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport_,
1124 /*rtcp_dtls_transport_=*/nullptr);
1125 } else {
1126 rtp_transport_->SetRtcpPacketTransport(nullptr);
1127 }
1128 SignalRtcpMuxFullyActive(transport_name_);
Zhi Huangc99b6c72017-11-10 16:44:46 -08001129 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -08001130 UpdateWritableState_n();
Zhi Huangc99b6c72017-11-10 16:44:46 -08001131}
1132
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001133VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
1134 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001135 rtc::Thread* signaling_thread,
Niels Möllerf120cba2018-01-30 09:33:03 +01001136 // TODO(nisse): Delete unused argument.
1137 MediaEngineInterface* /* media_engine */,
Steve Anton8699a322017-11-06 15:53:33 -08001138 std::unique_ptr<VoiceMediaChannel> media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001139 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08001140 bool rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001141 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001142 : BaseChannel(worker_thread,
1143 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001144 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001145 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -07001146 content_name,
deadbeefac22f702017-01-12 21:59:29 -08001147 rtcp_mux_required,
Niels Möllerf120cba2018-01-30 09:33:03 +01001148 srtp_required) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001149
1150VoiceChannel::~VoiceChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001151 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001152 // this can't be done in the base class, since it calls a virtual
1153 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001154 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001155}
1156
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001157void BaseChannel::UpdateMediaSendRecvState() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001158 RTC_DCHECK(network_thread_->IsCurrent());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001159 invoker_.AsyncInvoke<void>(
1160 RTC_FROM_HERE, worker_thread_,
1161 Bind(&BaseChannel::UpdateMediaSendRecvState_w, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001162}
1163
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001164void VoiceChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001165 // Render incoming data if we're the active call, and we have the local
1166 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001167 bool recv = IsReadyToReceiveMedia_w();
solenberg5b14b422015-10-01 04:10:31 -07001168 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001169
1170 // Send outgoing data if we're the active call, we have the remote content,
1171 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001172 bool send = IsReadyToSendMedia_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001173 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001174
Mirko Bonadei675513b2017-11-09 11:09:25 +01001175 RTC_LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001176}
1177
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001178bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001179 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001180 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001181 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001182 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001183 RTC_LOG(LS_INFO) << "Setting local voice description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001184
Steve Antonb1c1de12017-12-21 15:14:30 -08001185 RTC_DCHECK(content);
1186 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001187 SafeSetError("Can't find audio content in local description.", error_desc);
1188 return false;
1189 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001190
Steve Antonb1c1de12017-12-21 15:14:30 -08001191 const AudioContentDescription* audio = content->as_audio();
1192
jbauch5869f502017-06-29 12:31:36 -07001193 RtpHeaderExtensions rtp_header_extensions =
1194 GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
1195
Steve Anton3828c062017-12-06 10:34:51 -08001196 if (!SetRtpTransportParameters(content, type, CS_LOCAL, rtp_header_extensions,
1197 error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001198 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001199 }
1200
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001201 AudioRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07001202 RtpParametersFromMediaDescription(audio, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001203 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001204 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001205 error_desc);
1206 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001207 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001208 for (const AudioCodec& codec : audio->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07001209 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001210 }
1211 last_recv_params_ = recv_params;
1212
1213 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1214 // only give it to the media channel once we have a remote
1215 // description too (without a remote description, we won't be able
1216 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001217 if (!UpdateLocalStreams_w(audio->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001218 SafeSetError("Failed to set local audio description streams.", error_desc);
1219 return false;
1220 }
1221
1222 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001223 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001224 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001225}
1226
1227bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001228 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001229 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001230 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001231 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001232 RTC_LOG(LS_INFO) << "Setting remote voice description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001233
Steve Antonb1c1de12017-12-21 15:14:30 -08001234 RTC_DCHECK(content);
1235 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001236 SafeSetError("Can't find audio content in remote description.", error_desc);
1237 return false;
1238 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001239
Steve Antonb1c1de12017-12-21 15:14:30 -08001240 const AudioContentDescription* audio = content->as_audio();
1241
jbauch5869f502017-06-29 12:31:36 -07001242 RtpHeaderExtensions rtp_header_extensions =
1243 GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
1244
Steve Anton3828c062017-12-06 10:34:51 -08001245 if (!SetRtpTransportParameters(content, type, CS_REMOTE,
1246 rtp_header_extensions, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001247 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001248 }
1249
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001250 AudioSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07001251 RtpSendParametersFromMediaDescription(audio, rtp_header_extensions,
1252 &send_params);
skvladdc1c62c2016-03-16 19:07:43 -07001253
1254 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1255 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001256 SafeSetError("Failed to set remote audio description send parameters.",
1257 error_desc);
1258 return false;
1259 }
1260 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001261
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001262 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1263 // and only give it to the media channel once we have a local
1264 // description too (without a local description, we won't be able to
1265 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001266 if (!UpdateRemoteStreams_w(audio->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001267 SafeSetError("Failed to set remote audio description streams.", error_desc);
1268 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001269 }
1270
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001271 if (audio->rtp_header_extensions_set()) {
jbauch5869f502017-06-29 12:31:36 -07001272 MaybeCacheRtpAbsSendTimeHeaderExtension_w(rtp_header_extensions);
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001273 }
1274
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001275 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001276 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001277 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001278}
1279
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001280VideoChannel::VideoChannel(rtc::Thread* worker_thread,
1281 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001282 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001283 std::unique_ptr<VideoMediaChannel> media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001284 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08001285 bool rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001286 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001287 : BaseChannel(worker_thread,
1288 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001289 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001290 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -07001291 content_name,
deadbeefac22f702017-01-12 21:59:29 -08001292 rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001293 srtp_required) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001294
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001295VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001296 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001297 // this can't be done in the base class, since it calls a virtual
1298 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001299
1300 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001301}
1302
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001303void VideoChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001304 // Send outgoing data if we're the active call, we have the remote content,
1305 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001306 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001307 if (!media_channel()->SetSend(send)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001308 RTC_LOG(LS_ERROR) << "Failed to SetSend on video channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001309 // TODO(gangji): Report error back to server.
1310 }
1311
Mirko Bonadei675513b2017-11-09 11:09:25 +01001312 RTC_LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001313}
1314
stefanf79ade12017-06-02 06:44:03 -07001315void VideoChannel::FillBitrateInfo(BandwidthEstimationInfo* bwe_info) {
1316 InvokeOnWorker<void>(RTC_FROM_HERE, Bind(&VideoMediaChannel::FillBitrateInfo,
1317 media_channel(), bwe_info));
1318}
1319
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001320bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001321 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001322 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001323 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001324 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001325 RTC_LOG(LS_INFO) << "Setting local video description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001326
Steve Antonb1c1de12017-12-21 15:14:30 -08001327 RTC_DCHECK(content);
1328 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001329 SafeSetError("Can't find video content in local description.", error_desc);
1330 return false;
1331 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001332
Steve Antonb1c1de12017-12-21 15:14:30 -08001333 const VideoContentDescription* video = content->as_video();
1334
jbauch5869f502017-06-29 12:31:36 -07001335 RtpHeaderExtensions rtp_header_extensions =
1336 GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
1337
Steve Anton3828c062017-12-06 10:34:51 -08001338 if (!SetRtpTransportParameters(content, type, CS_LOCAL, rtp_header_extensions,
1339 error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001340 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001341 }
1342
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001343 VideoRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07001344 RtpParametersFromMediaDescription(video, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001345 if (!media_channel()->SetRecvParameters(recv_params)) {
1346 SafeSetError("Failed to set local video description recv parameters.",
1347 error_desc);
1348 return false;
1349 }
1350 for (const VideoCodec& codec : video->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07001351 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001352 }
1353 last_recv_params_ = recv_params;
1354
1355 // TODO(pthatcher): Move local streams into VideoSendParameters, and
1356 // only give it to the media channel once we have a remote
1357 // description too (without a remote description, we won't be able
1358 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001359 if (!UpdateLocalStreams_w(video->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001360 SafeSetError("Failed to set local video description streams.", error_desc);
1361 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001362 }
1363
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001364 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001365 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001366 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001367}
1368
1369bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001370 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001371 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001372 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001373 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001374 RTC_LOG(LS_INFO) << "Setting remote video description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001375
Steve Antonb1c1de12017-12-21 15:14:30 -08001376 RTC_DCHECK(content);
1377 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001378 SafeSetError("Can't find video content in remote description.", error_desc);
1379 return false;
1380 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001381
Steve Antonb1c1de12017-12-21 15:14:30 -08001382 const VideoContentDescription* video = content->as_video();
1383
jbauch5869f502017-06-29 12:31:36 -07001384 RtpHeaderExtensions rtp_header_extensions =
1385 GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
1386
Steve Anton3828c062017-12-06 10:34:51 -08001387 if (!SetRtpTransportParameters(content, type, CS_REMOTE,
1388 rtp_header_extensions, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001389 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001390 }
1391
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001392 VideoSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07001393 RtpSendParametersFromMediaDescription(video, rtp_header_extensions,
1394 &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001395 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08001396 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001397 }
skvladdc1c62c2016-03-16 19:07:43 -07001398
1399 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1400
1401 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001402 SafeSetError("Failed to set remote video description send parameters.",
1403 error_desc);
1404 return false;
1405 }
1406 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001407
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001408 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
1409 // and only give it to the media channel once we have a local
1410 // description too (without a local description, we won't be able to
1411 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001412 if (!UpdateRemoteStreams_w(video->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001413 SafeSetError("Failed to set remote video description streams.", error_desc);
1414 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001415 }
1416
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001417 if (video->rtp_header_extensions_set()) {
jbauch5869f502017-06-29 12:31:36 -07001418 MaybeCacheRtpAbsSendTimeHeaderExtension_w(rtp_header_extensions);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001419 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001420
1421 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001422 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001423 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001424}
1425
deadbeef953c2ce2017-01-09 14:53:41 -08001426RtpDataChannel::RtpDataChannel(rtc::Thread* worker_thread,
1427 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001428 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001429 std::unique_ptr<DataMediaChannel> media_channel,
deadbeef953c2ce2017-01-09 14:53:41 -08001430 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08001431 bool rtcp_mux_required,
deadbeef953c2ce2017-01-09 14:53:41 -08001432 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001433 : BaseChannel(worker_thread,
1434 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001435 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001436 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -07001437 content_name,
deadbeefac22f702017-01-12 21:59:29 -08001438 rtcp_mux_required,
deadbeef953c2ce2017-01-09 14:53:41 -08001439 srtp_required) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001440
deadbeef953c2ce2017-01-09 14:53:41 -08001441RtpDataChannel::~RtpDataChannel() {
1442 TRACE_EVENT0("webrtc", "RtpDataChannel::~RtpDataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001443 // this can't be done in the base class, since it calls a virtual
1444 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001445
1446 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001447}
1448
Steve Anton8699a322017-11-06 15:53:33 -08001449void RtpDataChannel::Init_w(
deadbeeff5346592017-01-24 21:51:21 -08001450 DtlsTransportInternal* rtp_dtls_transport,
1451 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -08001452 rtc::PacketTransportInternal* rtp_packet_transport,
1453 rtc::PacketTransportInternal* rtcp_packet_transport) {
Steve Anton8699a322017-11-06 15:53:33 -08001454 BaseChannel::Init_w(rtp_dtls_transport, rtcp_dtls_transport,
1455 rtp_packet_transport, rtcp_packet_transport);
1456
deadbeef953c2ce2017-01-09 14:53:41 -08001457 media_channel()->SignalDataReceived.connect(this,
1458 &RtpDataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001459 media_channel()->SignalReadyToSend.connect(
deadbeef953c2ce2017-01-09 14:53:41 -08001460 this, &RtpDataChannel::OnDataChannelReadyToSend);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001461}
1462
Zhi Huang2dfc42d2017-12-04 13:38:48 -08001463void RtpDataChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) {
1464 BaseChannel::Init_w(rtp_transport);
1465 media_channel()->SignalDataReceived.connect(this,
1466 &RtpDataChannel::OnDataReceived);
1467 media_channel()->SignalReadyToSend.connect(
1468 this, &RtpDataChannel::OnDataChannelReadyToSend);
1469}
1470
deadbeef953c2ce2017-01-09 14:53:41 -08001471bool RtpDataChannel::SendData(const SendDataParams& params,
1472 const rtc::CopyOnWriteBuffer& payload,
1473 SendDataResult* result) {
stefanf79ade12017-06-02 06:44:03 -07001474 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001475 RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params,
1476 payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001477}
1478
deadbeef953c2ce2017-01-09 14:53:41 -08001479bool RtpDataChannel::CheckDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001480 const DataContentDescription* content,
1481 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001482 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
1483 (content->protocol() == kMediaProtocolDtlsSctp));
deadbeef953c2ce2017-01-09 14:53:41 -08001484 // It's been set before, but doesn't match. That's bad.
1485 if (is_sctp) {
1486 SafeSetError("Data channel type mismatch. Expected RTP, got SCTP.",
1487 error_desc);
1488 return false;
1489 }
1490 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001491}
1492
deadbeef953c2ce2017-01-09 14:53:41 -08001493bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001494 SdpType type,
deadbeef953c2ce2017-01-09 14:53:41 -08001495 std::string* error_desc) {
1496 TRACE_EVENT0("webrtc", "RtpDataChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001497 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001498 RTC_LOG(LS_INFO) << "Setting local data description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001499
Steve Antonb1c1de12017-12-21 15:14:30 -08001500 RTC_DCHECK(content);
1501 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001502 SafeSetError("Can't find data content in local description.", error_desc);
1503 return false;
1504 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001505
Steve Antonb1c1de12017-12-21 15:14:30 -08001506 const DataContentDescription* data = content->as_data();
1507
deadbeef953c2ce2017-01-09 14:53:41 -08001508 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001509 return false;
1510 }
1511
jbauch5869f502017-06-29 12:31:36 -07001512 RtpHeaderExtensions rtp_header_extensions =
1513 GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
1514
Steve Anton3828c062017-12-06 10:34:51 -08001515 if (!SetRtpTransportParameters(content, type, CS_LOCAL, rtp_header_extensions,
1516 error_desc)) {
deadbeef953c2ce2017-01-09 14:53:41 -08001517 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001518 }
1519
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001520 DataRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07001521 RtpParametersFromMediaDescription(data, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001522 if (!media_channel()->SetRecvParameters(recv_params)) {
1523 SafeSetError("Failed to set remote data description recv parameters.",
1524 error_desc);
1525 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001526 }
deadbeef953c2ce2017-01-09 14:53:41 -08001527 for (const DataCodec& codec : data->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07001528 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001529 }
1530 last_recv_params_ = recv_params;
1531
1532 // TODO(pthatcher): Move local streams into DataSendParameters, and
1533 // only give it to the media channel once we have a remote
1534 // description too (without a remote description, we won't be able
1535 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001536 if (!UpdateLocalStreams_w(data->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001537 SafeSetError("Failed to set local data description streams.", error_desc);
1538 return false;
1539 }
1540
1541 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001542 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001543 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001544}
1545
deadbeef953c2ce2017-01-09 14:53:41 -08001546bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001547 SdpType type,
deadbeef953c2ce2017-01-09 14:53:41 -08001548 std::string* error_desc) {
1549 TRACE_EVENT0("webrtc", "RtpDataChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001550 RTC_DCHECK_RUN_ON(worker_thread());
1551 RTC_LOG(LS_INFO) << "Setting remote data description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001552
Steve Antonb1c1de12017-12-21 15:14:30 -08001553 RTC_DCHECK(content);
1554 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001555 SafeSetError("Can't find data content in remote description.", error_desc);
1556 return false;
1557 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001558
Steve Antonb1c1de12017-12-21 15:14:30 -08001559 const DataContentDescription* data = content->as_data();
1560
Zhi Huang801b8682017-11-15 11:36:43 -08001561 // If the remote data doesn't have codecs, it must be empty, so ignore it.
1562 if (!data->has_codecs()) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001563 return true;
1564 }
1565
deadbeef953c2ce2017-01-09 14:53:41 -08001566 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001567 return false;
1568 }
1569
jbauch5869f502017-06-29 12:31:36 -07001570 RtpHeaderExtensions rtp_header_extensions =
1571 GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
1572
Mirko Bonadei675513b2017-11-09 11:09:25 +01001573 RTC_LOG(LS_INFO) << "Setting remote data description";
Steve Anton3828c062017-12-06 10:34:51 -08001574 if (!SetRtpTransportParameters(content, type, CS_REMOTE,
1575 rtp_header_extensions, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001576 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001577 }
1578
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001579 DataSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07001580 RtpSendParametersFromMediaDescription<DataCodec>(data, rtp_header_extensions,
1581 &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001582 if (!media_channel()->SetSendParameters(send_params)) {
1583 SafeSetError("Failed to set remote data description send parameters.",
1584 error_desc);
1585 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001586 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001587 last_send_params_ = send_params;
1588
1589 // TODO(pthatcher): Move remote streams into DataRecvParameters,
1590 // and only give it to the media channel once we have a local
1591 // description too (without a local description, we won't be able to
1592 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001593 if (!UpdateRemoteStreams_w(data->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001594 SafeSetError("Failed to set remote data description streams.",
1595 error_desc);
1596 return false;
1597 }
1598
1599 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001600 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001601 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001602}
1603
deadbeef953c2ce2017-01-09 14:53:41 -08001604void RtpDataChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001605 // Render incoming data if we're the active call, and we have the local
1606 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001607 bool recv = IsReadyToReceiveMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001608 if (!media_channel()->SetReceive(recv)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001609 RTC_LOG(LS_ERROR) << "Failed to SetReceive on data channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001610 }
1611
1612 // Send outgoing data if we're the active call, we have the remote content,
1613 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001614 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001615 if (!media_channel()->SetSend(send)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001616 RTC_LOG(LS_ERROR) << "Failed to SetSend on data channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001617 }
1618
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001619 // Trigger SignalReadyToSendData asynchronously.
1620 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001621
Mirko Bonadei675513b2017-11-09 11:09:25 +01001622 RTC_LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001623}
1624
deadbeef953c2ce2017-01-09 14:53:41 -08001625void RtpDataChannel::OnMessage(rtc::Message* pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001626 switch (pmsg->message_id) {
1627 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001628 DataChannelReadyToSendMessageData* data =
1629 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00001630 ready_to_send_data_ = data->data();
1631 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001632 delete data;
1633 break;
1634 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001635 case MSG_DATARECEIVED: {
1636 DataReceivedMessageData* data =
1637 static_cast<DataReceivedMessageData*>(pmsg->pdata);
deadbeef953c2ce2017-01-09 14:53:41 -08001638 SignalDataReceived(data->params, data->payload);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001639 delete data;
1640 break;
1641 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001642 default:
1643 BaseChannel::OnMessage(pmsg);
1644 break;
1645 }
1646}
1647
deadbeef953c2ce2017-01-09 14:53:41 -08001648void RtpDataChannel::OnDataReceived(const ReceiveDataParams& params,
1649 const char* data,
1650 size_t len) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001651 DataReceivedMessageData* msg = new DataReceivedMessageData(
1652 params, data, len);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001653 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001654}
1655
deadbeef953c2ce2017-01-09 14:53:41 -08001656void RtpDataChannel::OnDataChannelReadyToSend(bool writable) {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001657 // This is usded for congestion control to indicate that the stream is ready
1658 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
1659 // that the transport channel is ready.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001660 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001661 new DataChannelReadyToSendMessageData(writable));
1662}
1663
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001664} // namespace cricket