blob: 8bb37d143397216efc3eb8e80eec8d97fff48c8e [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"
zhihuang38ede132017-06-15 12:52:32 -070029// Adding 'nogncheck' to disable the gn include headers check to support modular
30// WebRTC build targets.
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020031#include "media/engine/webrtcvoiceengine.h" // nogncheck
32#include "p2p/base/packettransportinternal.h"
33#include "pc/channelmanager.h"
34#include "pc/rtptransport.h"
35#include "pc/srtptransport.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000036
37namespace cricket {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000038using rtc::Bind;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000039
deadbeef2d110be2016-01-13 12:00:26 -080040namespace {
kwiberg31022942016-03-11 14:18:21 -080041// See comment below for why we need to use a pointer to a unique_ptr.
deadbeef2d110be2016-01-13 12:00:26 -080042bool SetRawAudioSink_w(VoiceMediaChannel* channel,
43 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -080044 std::unique_ptr<webrtc::AudioSinkInterface>* sink) {
45 channel->SetRawAudioSink(ssrc, std::move(*sink));
deadbeef2d110be2016-01-13 12:00:26 -080046 return true;
47}
Danil Chapovalov33b01f22016-05-11 19:55:27 +020048
49struct SendPacketMessageData : public rtc::MessageData {
50 rtc::CopyOnWriteBuffer packet;
51 rtc::PacketOptions options;
52};
53
deadbeef2d110be2016-01-13 12:00:26 -080054} // namespace
55
henrike@webrtc.org28e20752013-07-10 00:45:36 +000056enum {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000057 MSG_EARLYMEDIATIMEOUT = 1,
Danil Chapovalov33b01f22016-05-11 19:55:27 +020058 MSG_SEND_RTP_PACKET,
59 MSG_SEND_RTCP_PACKET,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000060 MSG_CHANNEL_ERROR,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000061 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000063 MSG_FIRSTPACKETRECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064};
65
66// Value specified in RFC 5764.
67static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
68
69static const int kAgcMinus10db = -10;
70
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000071static void SafeSetError(const std::string& message, std::string* error_desc) {
72 if (error_desc) {
73 *error_desc = message;
74 }
75}
76
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000077struct VoiceChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020078 VoiceChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079 VoiceMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020080 : ssrc(in_ssrc), error(in_error) {}
81 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000082 VoiceMediaChannel::Error error;
83};
84
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000085struct VideoChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020086 VideoChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087 VideoMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020088 : ssrc(in_ssrc), error(in_error) {}
89 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000090 VideoMediaChannel::Error error;
91};
92
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000093struct DataChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020094 DataChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095 DataMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020096 : ssrc(in_ssrc), error(in_error) {}
97 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000098 DataMediaChannel::Error error;
99};
100
jbaucheec21bd2016-03-20 06:15:43 -0700101static bool ValidPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102 // Check the packet size. We could check the header too if needed.
zstein3dcf0e92017-06-01 13:22:42 -0700103 return packet && IsValidRtpRtcpPacketSize(rtcp, packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000104}
105
106static bool IsReceiveContentDirection(MediaContentDirection direction) {
107 return direction == MD_SENDRECV || direction == MD_RECVONLY;
108}
109
110static bool IsSendContentDirection(MediaContentDirection direction) {
111 return direction == MD_SENDRECV || direction == MD_SENDONLY;
112}
113
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700114template <class Codec>
115void RtpParametersFromMediaDescription(
116 const MediaContentDescriptionImpl<Codec>* desc,
jbauch5869f502017-06-29 12:31:36 -0700117 const RtpHeaderExtensions& extensions,
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700118 RtpParameters<Codec>* params) {
119 // TODO(pthatcher): Remove this once we're sure no one will give us
Zhi Huang801b8682017-11-15 11:36:43 -0800120 // a description without codecs. Currently the ORTC implementation is relying
121 // on this.
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700122 if (desc->has_codecs()) {
123 params->codecs = desc->codecs();
124 }
125 // TODO(pthatcher): See if we really need
126 // rtp_header_extensions_set() and remove it if we don't.
127 if (desc->rtp_header_extensions_set()) {
jbauch5869f502017-06-29 12:31:36 -0700128 params->extensions = extensions;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700129 }
deadbeef13871492015-12-09 12:37:51 -0800130 params->rtcp.reduced_size = desc->rtcp_reduced_size();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700131}
132
nisse05103312016-03-16 02:22:50 -0700133template <class Codec>
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700134void RtpSendParametersFromMediaDescription(
135 const MediaContentDescriptionImpl<Codec>* desc,
jbauch5869f502017-06-29 12:31:36 -0700136 const RtpHeaderExtensions& extensions,
nisse05103312016-03-16 02:22:50 -0700137 RtpSendParameters<Codec>* send_params) {
jbauch5869f502017-06-29 12:31:36 -0700138 RtpParametersFromMediaDescription(desc, extensions, send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700139 send_params->max_bandwidth_bps = desc->bandwidth();
140}
141
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200142BaseChannel::BaseChannel(rtc::Thread* worker_thread,
143 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800144 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -0800145 std::unique_ptr<MediaChannel> media_channel,
deadbeefcbecd352015-09-23 11:50:27 -0700146 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -0800147 bool rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -0800148 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200149 : worker_thread_(worker_thread),
150 network_thread_(network_thread),
zhihuangf5b251b2017-01-12 19:37:48 -0800151 signaling_thread_(signaling_thread),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152 content_name_(content_name),
zstein56162b92017-04-24 16:54:35 -0700153 rtcp_mux_required_(rtcp_mux_required),
deadbeef7af91dd2016-12-13 11:29:11 -0800154 srtp_required_(srtp_required),
Zhi Huang1d88d742017-11-15 15:58:49 -0800155 media_channel_(std::move(media_channel)) {
Steve Anton8699a322017-11-06 15:53:33 -0800156 RTC_DCHECK_RUN_ON(worker_thread_);
Zhi Huangcf990f52017-09-22 12:12:30 -0700157 if (srtp_required) {
158 auto transport =
159 rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_mux_required, content_name);
160 srtp_transport_ = transport.get();
161 rtp_transport_ = std::move(transport);
jbauchdfcab722017-03-06 00:14:10 -0800162#if defined(ENABLE_EXTERNAL_AUTH)
Zhi Huangcf990f52017-09-22 12:12:30 -0700163 srtp_transport_->EnableExternalAuth();
jbauchdfcab722017-03-06 00:14:10 -0800164#endif
Zhi Huangcf990f52017-09-22 12:12:30 -0700165 } else {
166 rtp_transport_ = rtc::MakeUnique<webrtc::RtpTransport>(rtcp_mux_required);
167 srtp_transport_ = nullptr;
168 }
zsteine8ab5432017-07-12 11:48:11 -0700169 rtp_transport_->SignalReadyToSend.connect(
zstein56162b92017-04-24 16:54:35 -0700170 this, &BaseChannel::OnTransportReadyToSend);
zstein3dcf0e92017-06-01 13:22:42 -0700171 // TODO(zstein): RtpTransport::SignalPacketReceived will probably be replaced
172 // with a callback interface later so that the demuxer can select which
173 // channel to signal.
zsteine8ab5432017-07-12 11:48:11 -0700174 rtp_transport_->SignalPacketReceived.connect(this,
zstein398c3fd2017-07-19 13:38:02 -0700175 &BaseChannel::OnPacketReceived);
Zhi Huang942bc2e2017-11-13 13:26:07 -0800176 rtp_transport_->SignalNetworkRouteChanged.connect(
177 this, &BaseChannel::OnNetworkRouteChanged);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100178 RTC_LOG(LS_INFO) << "Created channel for " << content_name;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000179}
180
181BaseChannel::~BaseChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800182 TRACE_EVENT0("webrtc", "BaseChannel::~BaseChannel");
Steve Anton8699a322017-11-06 15:53:33 -0800183 RTC_DCHECK_RUN_ON(worker_thread_);
wu@webrtc.org78187522013-10-07 23:32:02 +0000184 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000185 StopConnectionMonitor();
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200186 // Eats any outstanding messages or packets.
187 worker_thread_->Clear(&invoker_);
188 worker_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000189 // We must destroy the media channel before the transport channel, otherwise
190 // the media channel may try to send on the dead transport channel. NULLing
191 // is not an effective strategy since the sends will come on another thread.
Steve Anton8699a322017-11-06 15:53:33 -0800192 media_channel_.reset();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100193 RTC_LOG(LS_INFO) << "Destroyed channel: " << content_name_;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200194}
195
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200196void BaseChannel::DisconnectTransportChannels_n() {
197 // Send any outstanding RTCP packets.
198 FlushRtcpMessages_n();
199
200 // Stop signals from transport channels, but keep them alive because
201 // media_channel may use them from a different thread.
zhihuangb2cdd932017-01-19 16:54:25 -0800202 if (rtp_dtls_transport_) {
deadbeeff5346592017-01-24 21:51:21 -0800203 DisconnectFromDtlsTransport(rtp_dtls_transport_);
zsteine8ab5432017-07-12 11:48:11 -0700204 } else if (rtp_transport_->rtp_packet_transport()) {
205 DisconnectFromPacketTransport(rtp_transport_->rtp_packet_transport());
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200206 }
zhihuangb2cdd932017-01-19 16:54:25 -0800207 if (rtcp_dtls_transport_) {
deadbeeff5346592017-01-24 21:51:21 -0800208 DisconnectFromDtlsTransport(rtcp_dtls_transport_);
zsteine8ab5432017-07-12 11:48:11 -0700209 } else if (rtp_transport_->rtcp_packet_transport()) {
210 DisconnectFromPacketTransport(rtp_transport_->rtcp_packet_transport());
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200211 }
212
zsteine8ab5432017-07-12 11:48:11 -0700213 rtp_transport_->SetRtpPacketTransport(nullptr);
214 rtp_transport_->SetRtcpPacketTransport(nullptr);
zstein3dcf0e92017-06-01 13:22:42 -0700215
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200216 // Clear pending read packets/messages.
217 network_thread_->Clear(&invoker_);
218 network_thread_->Clear(this);
219}
220
Steve Anton8699a322017-11-06 15:53:33 -0800221void BaseChannel::Init_w(DtlsTransportInternal* rtp_dtls_transport,
deadbeeff5346592017-01-24 21:51:21 -0800222 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800223 rtc::PacketTransportInternal* rtp_packet_transport,
224 rtc::PacketTransportInternal* rtcp_packet_transport) {
Steve Anton8699a322017-11-06 15:53:33 -0800225 RTC_DCHECK_RUN_ON(worker_thread_);
226 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
227 return InitNetwork_n(rtp_dtls_transport, rtcp_dtls_transport,
228 rtp_packet_transport, rtcp_packet_transport);
229 });
230
deadbeeff5346592017-01-24 21:51:21 -0800231 // Both RTP and RTCP channels should be set, we can call SetInterface on
232 // the media channel and it can set network options.
wu@webrtc.orgde305012013-10-31 15:40:38 +0000233 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000234}
235
Steve Anton8699a322017-11-06 15:53:33 -0800236void BaseChannel::InitNetwork_n(
deadbeeff5346592017-01-24 21:51:21 -0800237 DtlsTransportInternal* rtp_dtls_transport,
238 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800239 rtc::PacketTransportInternal* rtp_packet_transport,
240 rtc::PacketTransportInternal* rtcp_packet_transport) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200241 RTC_DCHECK(network_thread_->IsCurrent());
deadbeeff5346592017-01-24 21:51:21 -0800242 SetTransports_n(rtp_dtls_transport, rtcp_dtls_transport, rtp_packet_transport,
243 rtcp_packet_transport);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200244
zstein56162b92017-04-24 16:54:35 -0700245 if (rtcp_mux_required_) {
deadbeefac22f702017-01-12 21:59:29 -0800246 rtcp_mux_filter_.SetActive();
247 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200248}
249
wu@webrtc.org78187522013-10-07 23:32:02 +0000250void BaseChannel::Deinit() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200251 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.org78187522013-10-07 23:32:02 +0000252 media_channel_->SetInterface(NULL);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200253 // Packets arrive on the network thread, processing packets calls virtual
254 // functions, so need to stop this process in Deinit that is called in
255 // derived classes destructor.
256 network_thread_->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700257 RTC_FROM_HERE, Bind(&BaseChannel::DisconnectTransportChannels_n, this));
wu@webrtc.org78187522013-10-07 23:32:02 +0000258}
259
zhihuangb2cdd932017-01-19 16:54:25 -0800260void BaseChannel::SetTransports(DtlsTransportInternal* rtp_dtls_transport,
261 DtlsTransportInternal* rtcp_dtls_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800262 network_thread_->Invoke<void>(
263 RTC_FROM_HERE,
264 Bind(&BaseChannel::SetTransports_n, this, rtp_dtls_transport,
265 rtcp_dtls_transport, rtp_dtls_transport, rtcp_dtls_transport));
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000266}
267
deadbeeff5346592017-01-24 21:51:21 -0800268void BaseChannel::SetTransports(
deadbeef5bd5ca32017-02-10 11:31:50 -0800269 rtc::PacketTransportInternal* rtp_packet_transport,
270 rtc::PacketTransportInternal* rtcp_packet_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800271 network_thread_->Invoke<void>(
272 RTC_FROM_HERE, Bind(&BaseChannel::SetTransports_n, this, nullptr, nullptr,
273 rtp_packet_transport, rtcp_packet_transport));
274}
zhihuangf5b251b2017-01-12 19:37:48 -0800275
deadbeeff5346592017-01-24 21:51:21 -0800276void BaseChannel::SetTransports_n(
277 DtlsTransportInternal* rtp_dtls_transport,
278 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800279 rtc::PacketTransportInternal* rtp_packet_transport,
280 rtc::PacketTransportInternal* rtcp_packet_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800281 RTC_DCHECK(network_thread_->IsCurrent());
282 // Validate some assertions about the input.
283 RTC_DCHECK(rtp_packet_transport);
284 RTC_DCHECK_EQ(NeedsRtcpTransport(), rtcp_packet_transport != nullptr);
285 if (rtp_dtls_transport || rtcp_dtls_transport) {
286 // DTLS/non-DTLS pointers should be to the same object.
287 RTC_DCHECK(rtp_dtls_transport == rtp_packet_transport);
288 RTC_DCHECK(rtcp_dtls_transport == rtcp_packet_transport);
289 // Can't go from non-DTLS to DTLS.
zsteine8ab5432017-07-12 11:48:11 -0700290 RTC_DCHECK(!rtp_transport_->rtp_packet_transport() || rtp_dtls_transport_);
deadbeeff5346592017-01-24 21:51:21 -0800291 } else {
292 // Can't go from DTLS to non-DTLS.
293 RTC_DCHECK(!rtp_dtls_transport_);
294 }
295 // Transport names should be the same.
zhihuangb2cdd932017-01-19 16:54:25 -0800296 if (rtp_dtls_transport && rtcp_dtls_transport) {
297 RTC_DCHECK(rtp_dtls_transport->transport_name() ==
298 rtcp_dtls_transport->transport_name());
zhihuangb2cdd932017-01-19 16:54:25 -0800299 }
deadbeeff5346592017-01-24 21:51:21 -0800300 std::string debug_name;
301 if (rtp_dtls_transport) {
302 transport_name_ = rtp_dtls_transport->transport_name();
303 debug_name = transport_name_;
304 } else {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800305 debug_name = rtp_packet_transport->transport_name();
deadbeeff5346592017-01-24 21:51:21 -0800306 }
zsteine8ab5432017-07-12 11:48:11 -0700307 if (rtp_packet_transport == rtp_transport_->rtp_packet_transport()) {
deadbeeff5346592017-01-24 21:51:21 -0800308 // Nothing to do if transport isn't changing.
deadbeefbad5dad2017-01-17 18:32:35 -0800309 return;
deadbeefcbecd352015-09-23 11:50:27 -0700310 }
311
Zhi Huangcf990f52017-09-22 12:12:30 -0700312 // When using DTLS-SRTP, we must reset the SrtpTransport every time the
313 // DtlsTransport changes and wait until the DTLS handshake is complete to set
314 // the newly negotiated parameters.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200315 if (ShouldSetupDtlsSrtp_n()) {
guoweis46383312015-12-17 16:45:59 -0800316 // Set |writable_| to false such that UpdateWritableState_w can set up
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700317 // DTLS-SRTP when |writable_| becomes true again.
guoweis46383312015-12-17 16:45:59 -0800318 writable_ = false;
Zhi Huangcf990f52017-09-22 12:12:30 -0700319 dtls_active_ = false;
320 if (srtp_transport_) {
321 srtp_transport_->ResetParams();
322 }
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800323 }
324
deadbeefac22f702017-01-12 21:59:29 -0800325 // If this BaseChannel doesn't require RTCP mux and we haven't fully
326 // negotiated RTCP mux, we need an RTCP transport.
deadbeeff5346592017-01-24 21:51:21 -0800327 if (rtcp_packet_transport) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100328 RTC_LOG(LS_INFO) << "Setting RTCP Transport for " << content_name()
329 << " on " << debug_name << " transport "
330 << rtcp_packet_transport;
deadbeeff5346592017-01-24 21:51:21 -0800331 SetTransport_n(true, rtcp_dtls_transport, rtcp_packet_transport);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000332 }
333
Mirko Bonadei675513b2017-11-09 11:09:25 +0100334 RTC_LOG(LS_INFO) << "Setting RTP Transport for " << content_name() << " on "
335 << debug_name << " transport " << rtp_packet_transport;
deadbeeff5346592017-01-24 21:51:21 -0800336 SetTransport_n(false, rtp_dtls_transport, rtp_packet_transport);
guoweis46383312015-12-17 16:45:59 -0800337
deadbeefcbecd352015-09-23 11:50:27 -0700338 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700339 // setting new transport channels.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200340 UpdateWritableState_n();
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000341}
342
deadbeeff5346592017-01-24 21:51:21 -0800343void BaseChannel::SetTransport_n(
344 bool rtcp,
345 DtlsTransportInternal* new_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800346 rtc::PacketTransportInternal* new_packet_transport) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200347 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huang942bc2e2017-11-13 13:26:07 -0800348 if (new_dtls_transport) {
349 RTC_DCHECK(new_dtls_transport == new_packet_transport);
350 }
deadbeeff5346592017-01-24 21:51:21 -0800351 DtlsTransportInternal*& old_dtls_transport =
zhihuangb2cdd932017-01-19 16:54:25 -0800352 rtcp ? rtcp_dtls_transport_ : rtp_dtls_transport_;
zsteind48dbda2017-04-04 19:45:57 -0700353 rtc::PacketTransportInternal* old_packet_transport =
zsteine8ab5432017-07-12 11:48:11 -0700354 rtcp ? rtp_transport_->rtcp_packet_transport()
355 : rtp_transport_->rtp_packet_transport();
zhihuangb2cdd932017-01-19 16:54:25 -0800356
deadbeeff5346592017-01-24 21:51:21 -0800357 if (!old_packet_transport && !new_packet_transport) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700358 // Nothing to do.
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000359 return;
360 }
zhihuangb2cdd932017-01-19 16:54:25 -0800361
deadbeeff5346592017-01-24 21:51:21 -0800362 RTC_DCHECK(old_packet_transport != new_packet_transport);
363 if (old_dtls_transport) {
364 DisconnectFromDtlsTransport(old_dtls_transport);
365 } else if (old_packet_transport) {
366 DisconnectFromPacketTransport(old_packet_transport);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000367 }
368
zsteind48dbda2017-04-04 19:45:57 -0700369 if (rtcp) {
zsteine8ab5432017-07-12 11:48:11 -0700370 rtp_transport_->SetRtcpPacketTransport(new_packet_transport);
zsteind48dbda2017-04-04 19:45:57 -0700371 } else {
zsteine8ab5432017-07-12 11:48:11 -0700372 rtp_transport_->SetRtpPacketTransport(new_packet_transport);
zsteind48dbda2017-04-04 19:45:57 -0700373 }
deadbeeff5346592017-01-24 21:51:21 -0800374 old_dtls_transport = new_dtls_transport;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000375
deadbeeff5346592017-01-24 21:51:21 -0800376 // If there's no new transport, we're done after disconnecting from old one.
377 if (!new_packet_transport) {
378 return;
379 }
380
381 if (rtcp && new_dtls_transport) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700382 RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_active()))
383 << "Setting RTCP for DTLS/SRTP after the DTLS is active "
deadbeeff5346592017-01-24 21:51:21 -0800384 << "should never happen.";
385 }
zstein56162b92017-04-24 16:54:35 -0700386
deadbeeff5346592017-01-24 21:51:21 -0800387 if (new_dtls_transport) {
388 ConnectToDtlsTransport(new_dtls_transport);
389 } else {
390 ConnectToPacketTransport(new_packet_transport);
391 }
392 auto& socket_options = rtcp ? rtcp_socket_options_ : socket_options_;
393 for (const auto& pair : socket_options) {
394 new_packet_transport->SetOption(pair.first, pair.second);
guoweis46383312015-12-17 16:45:59 -0800395 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000396}
397
deadbeeff5346592017-01-24 21:51:21 -0800398void BaseChannel::ConnectToDtlsTransport(DtlsTransportInternal* transport) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200399 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000400
zstein56162b92017-04-24 16:54:35 -0700401 // TODO(zstein): de-dup with ConnectToPacketTransport
zhihuangb2cdd932017-01-19 16:54:25 -0800402 transport->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
zhihuangb2cdd932017-01-19 16:54:25 -0800403 transport->SignalDtlsState.connect(this, &BaseChannel::OnDtlsState);
404 transport->SignalSentPacket.connect(this, &BaseChannel::SignalSentPacket_n);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000405}
406
deadbeeff5346592017-01-24 21:51:21 -0800407void BaseChannel::DisconnectFromDtlsTransport(
408 DtlsTransportInternal* transport) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200409 RTC_DCHECK(network_thread_->IsCurrent());
zhihuangb2cdd932017-01-19 16:54:25 -0800410 transport->SignalWritableState.disconnect(this);
zhihuangb2cdd932017-01-19 16:54:25 -0800411 transport->SignalDtlsState.disconnect(this);
412 transport->SignalSentPacket.disconnect(this);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000413}
414
deadbeeff5346592017-01-24 21:51:21 -0800415void BaseChannel::ConnectToPacketTransport(
deadbeef5bd5ca32017-02-10 11:31:50 -0800416 rtc::PacketTransportInternal* transport) {
deadbeeff5346592017-01-24 21:51:21 -0800417 RTC_DCHECK_RUN_ON(network_thread_);
418 transport->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
deadbeeff5346592017-01-24 21:51:21 -0800419 transport->SignalSentPacket.connect(this, &BaseChannel::SignalSentPacket_n);
420}
421
422void BaseChannel::DisconnectFromPacketTransport(
deadbeef5bd5ca32017-02-10 11:31:50 -0800423 rtc::PacketTransportInternal* transport) {
deadbeeff5346592017-01-24 21:51:21 -0800424 RTC_DCHECK_RUN_ON(network_thread_);
425 transport->SignalWritableState.disconnect(this);
deadbeeff5346592017-01-24 21:51:21 -0800426 transport->SignalSentPacket.disconnect(this);
427}
428
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000429bool BaseChannel::Enable(bool enable) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700430 worker_thread_->Invoke<void>(
431 RTC_FROM_HERE,
432 Bind(enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
433 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000434 return true;
435}
436
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000437bool BaseChannel::AddRecvStream(const StreamParams& sp) {
stefanf79ade12017-06-02 06:44:03 -0700438 return InvokeOnWorker<bool>(RTC_FROM_HERE,
439 Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440}
441
Peter Boström0c4e06b2015-10-07 12:23:21 +0200442bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
stefanf79ade12017-06-02 06:44:03 -0700443 return InvokeOnWorker<bool>(
444 RTC_FROM_HERE, Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000445}
446
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000447bool BaseChannel::AddSendStream(const StreamParams& sp) {
stefanf79ade12017-06-02 06:44:03 -0700448 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700449 RTC_FROM_HERE, Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000450}
451
Peter Boström0c4e06b2015-10-07 12:23:21 +0200452bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
stefanf79ade12017-06-02 06:44:03 -0700453 return InvokeOnWorker<bool>(
454 RTC_FROM_HERE,
455 Bind(&MediaChannel::RemoveSendStream, media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000456}
457
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000458bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000459 ContentAction action,
460 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100461 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
stefanf79ade12017-06-02 06:44:03 -0700462 return InvokeOnWorker<bool>(
463 RTC_FROM_HERE,
464 Bind(&BaseChannel::SetLocalContent_w, this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000465}
466
467bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000468 ContentAction action,
469 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100470 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
stefanf79ade12017-06-02 06:44:03 -0700471 return InvokeOnWorker<bool>(
472 RTC_FROM_HERE, Bind(&BaseChannel::SetRemoteContent_w, this, content,
473 action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000474}
475
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000476void BaseChannel::StartConnectionMonitor(int cms) {
zhihuangb2cdd932017-01-19 16:54:25 -0800477 // We pass in the BaseChannel instead of the rtp_dtls_transport_
478 // because if the rtp_dtls_transport_ changes, the ConnectionMonitor
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000479 // would be pointing to the wrong TransportChannel.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200480 // We pass in the network thread because on that thread connection monitor
481 // will call BaseChannel::GetConnectionStats which must be called on the
482 // network thread.
483 connection_monitor_.reset(
484 new ConnectionMonitor(this, network_thread(), rtc::Thread::Current()));
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000485 connection_monitor_->SignalUpdate.connect(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000486 this, &BaseChannel::OnConnectionMonitorUpdate);
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000487 connection_monitor_->Start(cms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488}
489
490void BaseChannel::StopConnectionMonitor() {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000491 if (connection_monitor_) {
492 connection_monitor_->Stop();
493 connection_monitor_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000494 }
495}
496
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000497bool BaseChannel::GetConnectionStats(ConnectionInfos* infos) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200498 RTC_DCHECK(network_thread_->IsCurrent());
deadbeeff5346592017-01-24 21:51:21 -0800499 if (!rtp_dtls_transport_) {
500 return false;
501 }
zhihuangb2cdd932017-01-19 16:54:25 -0800502 return rtp_dtls_transport_->ice_transport()->GetStats(infos);
zhihuangf5b251b2017-01-12 19:37:48 -0800503}
504
505bool BaseChannel::NeedsRtcpTransport() {
deadbeefac22f702017-01-12 21:59:29 -0800506 // If this BaseChannel doesn't require RTCP mux and we haven't fully
507 // negotiated RTCP mux, we need an RTCP transport.
zstein56162b92017-04-24 16:54:35 -0700508 return !rtcp_mux_required_ && !rtcp_mux_filter_.IsFullyActive();
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000509}
510
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700511bool BaseChannel::IsReadyToReceiveMedia_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000512 // Receive data if we are enabled and have local content,
513 return enabled() && IsReceiveContentDirection(local_content_direction_);
514}
515
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700516bool BaseChannel::IsReadyToSendMedia_w() const {
517 // Need to access some state updated on the network thread.
518 return network_thread_->Invoke<bool>(
519 RTC_FROM_HERE, Bind(&BaseChannel::IsReadyToSendMedia_n, this));
520}
521
522bool BaseChannel::IsReadyToSendMedia_n() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000523 // Send outgoing data if we are enabled, have local and remote content,
524 // and we have had some form of connectivity.
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800525 return enabled() && IsReceiveContentDirection(remote_content_direction_) &&
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000526 IsSendContentDirection(local_content_direction_) &&
Zhi Huangcf990f52017-09-22 12:12:30 -0700527 was_ever_writable() && (srtp_active() || !ShouldSetupDtlsSrtp_n());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528}
529
jbaucheec21bd2016-03-20 06:15:43 -0700530bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700531 const rtc::PacketOptions& options) {
532 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000533}
534
jbaucheec21bd2016-03-20 06:15:43 -0700535bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700536 const rtc::PacketOptions& options) {
537 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000538}
539
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000540int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000541 int value) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200542 return network_thread_->Invoke<int>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700543 RTC_FROM_HERE, Bind(&BaseChannel::SetOption_n, this, type, opt, value));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200544}
545
546int BaseChannel::SetOption_n(SocketType type,
547 rtc::Socket::Option opt,
548 int value) {
549 RTC_DCHECK(network_thread_->IsCurrent());
deadbeef5bd5ca32017-02-10 11:31:50 -0800550 rtc::PacketTransportInternal* transport = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000551 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000552 case ST_RTP:
zsteine8ab5432017-07-12 11:48:11 -0700553 transport = rtp_transport_->rtp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700554 socket_options_.push_back(
555 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000556 break;
557 case ST_RTCP:
zsteine8ab5432017-07-12 11:48:11 -0700558 transport = rtp_transport_->rtcp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700559 rtcp_socket_options_.push_back(
560 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000561 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000562 }
deadbeeff5346592017-01-24 21:51:21 -0800563 return transport ? transport->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000564}
565
deadbeef5bd5ca32017-02-10 11:31:50 -0800566void BaseChannel::OnWritableState(rtc::PacketTransportInternal* transport) {
zsteine8ab5432017-07-12 11:48:11 -0700567 RTC_DCHECK(transport == rtp_transport_->rtp_packet_transport() ||
568 transport == rtp_transport_->rtcp_packet_transport());
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200569 RTC_DCHECK(network_thread_->IsCurrent());
570 UpdateWritableState_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000571}
572
zhihuangb2cdd932017-01-19 16:54:25 -0800573void BaseChannel::OnDtlsState(DtlsTransportInternal* transport,
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800574 DtlsTransportState state) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200575 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800576 return;
577 }
578
Zhi Huangcf990f52017-09-22 12:12:30 -0700579 // Reset the SrtpTransport if it's not the CONNECTED state. For the CONNECTED
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800580 // state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to
zhihuangb2cdd932017-01-19 16:54:25 -0800581 // cover other scenarios like the whole transport is writable (not just this
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800582 // TransportChannel) or when TransportChannel is attached after DTLS is
583 // negotiated.
584 if (state != DTLS_TRANSPORT_CONNECTED) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700585 dtls_active_ = false;
586 if (srtp_transport_) {
587 srtp_transport_->ResetParams();
588 }
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800589 }
590}
591
Zhi Huang942bc2e2017-11-13 13:26:07 -0800592void BaseChannel::OnNetworkRouteChanged(
593 rtc::Optional<rtc::NetworkRoute> network_route) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200594 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huang942bc2e2017-11-13 13:26:07 -0800595 rtc::NetworkRoute new_route;
596 if (network_route) {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800597 new_route = *(network_route);
Zhi Huang8c316c12017-11-13 21:13:45 +0000598 }
Zhi Huang942bc2e2017-11-13 13:26:07 -0800599 // Note: When the RTCP-muxing is not enabled, RTCP transport and RTP transport
600 // use the same transport name and MediaChannel::OnNetworkRouteChanged cannot
601 // work correctly. Intentionally leave it broken to simplify the code and
602 // encourage the users to stop using non-muxing RTCP.
Steve Anton8699a322017-11-06 15:53:33 -0800603 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_, [=] {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800604 media_channel_->OnNetworkRouteChanged(transport_name_, new_route);
Steve Anton8699a322017-11-06 15:53:33 -0800605 });
Honghai Zhangcc411c02016-03-29 17:27:21 -0700606}
607
zstein56162b92017-04-24 16:54:35 -0700608void BaseChannel::OnTransportReadyToSend(bool ready) {
Steve Anton8699a322017-11-06 15:53:33 -0800609 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
610 [=] { media_channel_->OnReadyToSend(ready); });
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000611}
612
stefanc1aeaf02015-10-15 07:26:07 -0700613bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700614 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700615 const rtc::PacketOptions& options) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200616 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
617 // If the thread is not our network thread, we will post to our network
618 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000619 // synchronize access to all the pieces of the send path, including
620 // SRTP and the inner workings of the transport channels.
621 // The only downside is that we can't return a proper failure code if
622 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200623 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000624 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200625 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
626 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800627 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700628 data->options = options;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700629 network_thread_->Post(RTC_FROM_HERE, this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000630 return true;
631 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200632 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000633
634 // Now that we are on the correct thread, ensure we have a place to send this
635 // packet before doing anything. (We might get RTCP packets that we don't
636 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
637 // transport.
zsteine8ab5432017-07-12 11:48:11 -0700638 if (!rtp_transport_->IsWritable(rtcp)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000639 return false;
640 }
641
642 // Protect ourselves against crazy data.
643 if (!ValidPacket(rtcp, packet)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100644 RTC_LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
645 << RtpRtcpStringLiteral(rtcp)
646 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000647 return false;
648 }
649
Zhi Huangcf990f52017-09-22 12:12:30 -0700650 if (!srtp_active()) {
651 if (srtp_required_) {
652 // The audio/video engines may attempt to send RTCP packets as soon as the
653 // streams are created, so don't treat this as an error for RTCP.
654 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6809
655 if (rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000656 return false;
657 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700658 // However, there shouldn't be any RTP packets sent before SRTP is set up
659 // (and SetSend(true) is called).
Mirko Bonadei675513b2017-11-09 11:09:25 +0100660 RTC_LOG(LS_ERROR)
661 << "Can't send outgoing RTP packet when SRTP is inactive"
662 << " and crypto is required";
Zhi Huangcf990f52017-09-22 12:12:30 -0700663 RTC_NOTREACHED();
deadbeef8f425f92016-12-01 12:26:27 -0800664 return false;
665 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700666 // Bon voyage.
Zhi Huang04eaa152017-10-04 14:08:30 -0700667 return rtcp
668 ? rtp_transport_->SendRtcpPacket(packet, options, PF_SRTP_BYPASS)
669 : rtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000670 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700671 RTC_DCHECK(srtp_transport_);
672 RTC_DCHECK(srtp_transport_->IsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673 // Bon voyage.
Zhi Huangcf990f52017-09-22 12:12:30 -0700674 return rtcp ? srtp_transport_->SendRtcpPacket(packet, options, PF_SRTP_BYPASS)
675 : srtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000676}
677
zstein3dcf0e92017-06-01 13:22:42 -0700678bool BaseChannel::HandlesPayloadType(int packet_type) const {
zsteine8ab5432017-07-12 11:48:11 -0700679 return rtp_transport_->HandlesPayloadType(packet_type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680}
681
zstein3dcf0e92017-06-01 13:22:42 -0700682void BaseChannel::OnPacketReceived(bool rtcp,
zstein634977b2017-07-14 12:30:04 -0700683 rtc::CopyOnWriteBuffer* packet,
zstein3dcf0e92017-06-01 13:22:42 -0700684 const rtc::PacketTime& packet_time) {
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000685 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686 has_received_packet_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700687 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688 }
689
Zhi Huangcf990f52017-09-22 12:12:30 -0700690 if (!srtp_active() && srtp_required_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000691 // Our session description indicates that SRTP is required, but we got a
692 // packet before our SRTP filter is active. This means either that
693 // a) we got SRTP packets before we received the SDES keys, in which case
694 // we can't decrypt it anyway, or
695 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
zhihuangb2cdd932017-01-19 16:54:25 -0800696 // transports, so we haven't yet extracted keys, even if DTLS did
697 // complete on the transport that the packets are being sent on. It's
698 // really good practice to wait for both RTP and RTCP to be good to go
699 // before sending media, to prevent weird failure modes, so it's fine
700 // for us to just eat packets here. This is all sidestepped if RTCP mux
701 // is used anyway.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100702 RTC_LOG(LS_WARNING)
703 << "Can't process incoming " << RtpRtcpStringLiteral(rtcp)
704 << " packet when SRTP is inactive and crypto is required";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000705 return;
706 }
707
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200708 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700709 RTC_FROM_HERE, worker_thread_,
zstein634977b2017-07-14 12:30:04 -0700710 Bind(&BaseChannel::ProcessPacket, this, rtcp, *packet, packet_time));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200711}
712
zstein3dcf0e92017-06-01 13:22:42 -0700713void BaseChannel::ProcessPacket(bool rtcp,
714 const rtc::CopyOnWriteBuffer& packet,
715 const rtc::PacketTime& packet_time) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200716 RTC_DCHECK(worker_thread_->IsCurrent());
zstein3dcf0e92017-06-01 13:22:42 -0700717
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200718 // Need to copy variable because OnRtcpReceived/OnPacketReceived
719 // requires non-const pointer to buffer. This doesn't memcpy the actual data.
720 rtc::CopyOnWriteBuffer data(packet);
721 if (rtcp) {
722 media_channel_->OnRtcpReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000723 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200724 media_channel_->OnPacketReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000725 }
726}
727
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000728void BaseChannel::EnableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700729 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000730 if (enabled_)
731 return;
732
Mirko Bonadei675513b2017-11-09 11:09:25 +0100733 RTC_LOG(LS_INFO) << "Channel enabled";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000734 enabled_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700735 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000736}
737
738void BaseChannel::DisableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700739 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000740 if (!enabled_)
741 return;
742
Mirko Bonadei675513b2017-11-09 11:09:25 +0100743 RTC_LOG(LS_INFO) << "Channel disabled";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000744 enabled_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700745 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000746}
747
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200748void BaseChannel::UpdateWritableState_n() {
zsteind48dbda2017-04-04 19:45:57 -0700749 rtc::PacketTransportInternal* rtp_packet_transport =
zsteine8ab5432017-07-12 11:48:11 -0700750 rtp_transport_->rtp_packet_transport();
zsteind48dbda2017-04-04 19:45:57 -0700751 rtc::PacketTransportInternal* rtcp_packet_transport =
zsteine8ab5432017-07-12 11:48:11 -0700752 rtp_transport_->rtcp_packet_transport();
zsteind48dbda2017-04-04 19:45:57 -0700753 if (rtp_packet_transport && rtp_packet_transport->writable() &&
754 (!rtcp_packet_transport || rtcp_packet_transport->writable())) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200755 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700756 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200757 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700758 }
759}
760
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200761void BaseChannel::ChannelWritable_n() {
762 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800763 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000764 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800765 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000766
Mirko Bonadei675513b2017-11-09 11:09:25 +0100767 RTC_LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
768 << (was_ever_writable_ ? "" : " for the first time");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000769
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000770 was_ever_writable_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200771 MaybeSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000772 writable_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700773 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000774}
775
deadbeef953c2ce2017-01-09 14:53:41 -0800776void BaseChannel::SignalDtlsSrtpSetupFailure_n(bool rtcp) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200777 RTC_DCHECK(network_thread_->IsCurrent());
778 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700779 RTC_FROM_HERE, signaling_thread(),
deadbeef953c2ce2017-01-09 14:53:41 -0800780 Bind(&BaseChannel::SignalDtlsSrtpSetupFailure_s, this, rtcp));
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000781}
782
deadbeef953c2ce2017-01-09 14:53:41 -0800783void BaseChannel::SignalDtlsSrtpSetupFailure_s(bool rtcp) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700784 RTC_DCHECK(signaling_thread() == rtc::Thread::Current());
deadbeef953c2ce2017-01-09 14:53:41 -0800785 SignalDtlsSrtpSetupFailure(this, rtcp);
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000786}
787
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200788bool BaseChannel::ShouldSetupDtlsSrtp_n() const {
zhihuangb2cdd932017-01-19 16:54:25 -0800789 // Since DTLS is applied to all transports, checking RTP should be enough.
790 return rtp_dtls_transport_ && rtp_dtls_transport_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000791}
792
793// This function returns true if either DTLS-SRTP is not in use
794// *or* DTLS-SRTP is successfully set up.
zhihuangb2cdd932017-01-19 16:54:25 -0800795bool BaseChannel::SetupDtlsSrtp_n(bool rtcp) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200796 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000797 bool ret = false;
798
zhihuangb2cdd932017-01-19 16:54:25 -0800799 DtlsTransportInternal* transport =
800 rtcp ? rtcp_dtls_transport_ : rtp_dtls_transport_;
deadbeeff5346592017-01-24 21:51:21 -0800801 RTC_DCHECK(transport);
zhihuangb2cdd932017-01-19 16:54:25 -0800802 RTC_DCHECK(transport->IsDtlsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000803
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800804 int selected_crypto_suite;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000805
zhihuangb2cdd932017-01-19 16:54:25 -0800806 if (!transport->GetSrtpCryptoSuite(&selected_crypto_suite)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100807 RTC_LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000808 return false;
809 }
810
Mirko Bonadei675513b2017-11-09 11:09:25 +0100811 RTC_LOG(LS_INFO) << "Installing keys from DTLS-SRTP on " << content_name()
812 << " " << RtpRtcpStringLiteral(rtcp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000813
jbauchcb560652016-08-04 05:20:32 -0700814 int key_len;
815 int salt_len;
816 if (!rtc::GetSrtpKeyAndSaltLengths(selected_crypto_suite, &key_len,
817 &salt_len)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100818 RTC_LOG(LS_ERROR) << "Unknown DTLS-SRTP crypto suite"
819 << selected_crypto_suite;
jbauchcb560652016-08-04 05:20:32 -0700820 return false;
821 }
822
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000823 // OK, we're now doing DTLS (RFC 5764)
jbauchcb560652016-08-04 05:20:32 -0700824 std::vector<unsigned char> dtls_buffer(key_len * 2 + salt_len * 2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000825
826 // RFC 5705 exporter using the RFC 5764 parameters
zhihuangb2cdd932017-01-19 16:54:25 -0800827 if (!transport->ExportKeyingMaterial(kDtlsSrtpExporterLabel, NULL, 0, false,
828 &dtls_buffer[0], dtls_buffer.size())) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100829 RTC_LOG(LS_WARNING) << "DTLS-SRTP key export failed";
nisseeb4ca4e2017-01-12 02:24:27 -0800830 RTC_NOTREACHED(); // This should never happen
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000831 return false;
832 }
833
834 // Sync up the keys with the DTLS-SRTP interface
jbauchcb560652016-08-04 05:20:32 -0700835 std::vector<unsigned char> client_write_key(key_len + salt_len);
836 std::vector<unsigned char> server_write_key(key_len + salt_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000837 size_t offset = 0;
jbauchcb560652016-08-04 05:20:32 -0700838 memcpy(&client_write_key[0], &dtls_buffer[offset], key_len);
839 offset += key_len;
840 memcpy(&server_write_key[0], &dtls_buffer[offset], key_len);
841 offset += key_len;
842 memcpy(&client_write_key[key_len], &dtls_buffer[offset], salt_len);
843 offset += salt_len;
844 memcpy(&server_write_key[key_len], &dtls_buffer[offset], salt_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000845
846 std::vector<unsigned char> *send_key, *recv_key;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000847 rtc::SSLRole role;
zhihuangb2cdd932017-01-19 16:54:25 -0800848 if (!transport->GetSslRole(&role)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100849 RTC_LOG(LS_WARNING) << "GetSslRole failed";
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000850 return false;
851 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000852
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000853 if (role == rtc::SSL_SERVER) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000854 send_key = &server_write_key;
855 recv_key = &client_write_key;
856 } else {
857 send_key = &client_write_key;
858 recv_key = &server_write_key;
859 }
860
Zhi Huangc99b6c72017-11-10 16:44:46 -0800861 // Use an empty encrypted header extension ID vector if not set. This could
862 // happen when the DTLS handshake is completed before processing the
863 // Offer/Answer which contains the encrypted header extension IDs.
864 std::vector<int> send_extension_ids;
865 std::vector<int> recv_extension_ids;
866 if (catched_send_extension_ids_) {
867 send_extension_ids = *catched_send_extension_ids_;
868 }
869 if (catched_recv_extension_ids_) {
870 recv_extension_ids = *catched_recv_extension_ids_;
871 }
872
Zhi Huangcf990f52017-09-22 12:12:30 -0700873 if (rtcp) {
874 if (!dtls_active()) {
875 RTC_DCHECK(srtp_transport_);
876 ret = srtp_transport_->SetRtcpParams(
877 selected_crypto_suite, &(*send_key)[0],
Zhi Huangc99b6c72017-11-10 16:44:46 -0800878 static_cast<int>(send_key->size()), send_extension_ids,
879 selected_crypto_suite, &(*recv_key)[0],
880 static_cast<int>(recv_key->size()), recv_extension_ids);
jbauch5869f502017-06-29 12:31:36 -0700881 } else {
Zhi Huangcf990f52017-09-22 12:12:30 -0700882 // RTCP doesn't need to call SetRtpParam because it is only used
883 // to make the updated encrypted RTP header extension IDs take effect.
884 ret = true;
jbauch5869f502017-06-29 12:31:36 -0700885 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000886 } else {
Zhi Huangcf990f52017-09-22 12:12:30 -0700887 RTC_DCHECK(srtp_transport_);
Zhi Huangc99b6c72017-11-10 16:44:46 -0800888 ret = srtp_transport_->SetRtpParams(
889 selected_crypto_suite, &(*send_key)[0],
890 static_cast<int>(send_key->size()), send_extension_ids,
891 selected_crypto_suite, &(*recv_key)[0],
892 static_cast<int>(recv_key->size()), recv_extension_ids);
Zhi Huangcf990f52017-09-22 12:12:30 -0700893 dtls_active_ = ret;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894 }
895
michaelt79e05882016-11-08 02:50:09 -0800896 if (!ret) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100897 RTC_LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
michaelt79e05882016-11-08 02:50:09 -0800898 }
Zhi Huang942bc2e2017-11-13 13:26:07 -0800899
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000900 return ret;
901}
902
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200903void BaseChannel::MaybeSetupDtlsSrtp_n() {
Zhi Huangcf990f52017-09-22 12:12:30 -0700904 if (dtls_active()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800905 return;
906 }
907
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200908 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800909 return;
910 }
911
Zhi Huangcf990f52017-09-22 12:12:30 -0700912 if (!srtp_transport_) {
913 EnableSrtpTransport_n();
914 }
915
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200916 if (!SetupDtlsSrtp_n(false)) {
deadbeef953c2ce2017-01-09 14:53:41 -0800917 SignalDtlsSrtpSetupFailure_n(false);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800918 return;
919 }
920
zhihuangb2cdd932017-01-19 16:54:25 -0800921 if (rtcp_dtls_transport_) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200922 if (!SetupDtlsSrtp_n(true)) {
deadbeef953c2ce2017-01-09 14:53:41 -0800923 SignalDtlsSrtpSetupFailure_n(true);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800924 return;
925 }
926 }
927}
928
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200929void BaseChannel::ChannelNotWritable_n() {
930 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000931 if (!writable_)
932 return;
933
Mirko Bonadei675513b2017-11-09 11:09:25 +0100934 RTC_LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000935 writable_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700936 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000937}
938
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200939bool BaseChannel::SetRtpTransportParameters(
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700940 const MediaContentDescription* content,
941 ContentAction action,
942 ContentSource src,
jbauch5869f502017-06-29 12:31:36 -0700943 const RtpHeaderExtensions& extensions,
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700944 std::string* error_desc) {
jbauch5869f502017-06-29 12:31:36 -0700945 std::vector<int> encrypted_extension_ids;
946 for (const webrtc::RtpExtension& extension : extensions) {
947 if (extension.encrypt) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100948 RTC_LOG(LS_INFO) << "Using " << (src == CS_LOCAL ? "local" : "remote")
949 << " encrypted extension: " << extension.ToString();
jbauch5869f502017-06-29 12:31:36 -0700950 encrypted_extension_ids.push_back(extension.id);
951 }
952 }
953
deadbeef7af91dd2016-12-13 11:29:11 -0800954 // Cache srtp_required_ for belt and suspenders check on SendPacket
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200955 return network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700956 RTC_FROM_HERE, Bind(&BaseChannel::SetRtpTransportParameters_n, this,
jbauch5869f502017-06-29 12:31:36 -0700957 content, action, src, encrypted_extension_ids,
958 error_desc));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200959}
960
961bool BaseChannel::SetRtpTransportParameters_n(
962 const MediaContentDescription* content,
963 ContentAction action,
964 ContentSource src,
jbauch5869f502017-06-29 12:31:36 -0700965 const std::vector<int>& encrypted_extension_ids,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200966 std::string* error_desc) {
967 RTC_DCHECK(network_thread_->IsCurrent());
968
jbauch5869f502017-06-29 12:31:36 -0700969 if (!SetSrtp_n(content->cryptos(), action, src, encrypted_extension_ids,
970 error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700971 return false;
972 }
973
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200974 if (!SetRtcpMux_n(content->rtcp_mux(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700975 return false;
976 }
977
978 return true;
979}
980
zhihuangb2cdd932017-01-19 16:54:25 -0800981// |dtls| will be set to true if DTLS is active for transport and crypto is
982// empty.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200983bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
984 bool* dtls,
985 std::string* error_desc) {
deadbeeff5346592017-01-24 21:51:21 -0800986 *dtls = rtp_dtls_transport_ && rtp_dtls_transport_->IsDtlsActive();
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000987 if (*dtls && !cryptos.empty()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200988 SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000989 return false;
990 }
991 return true;
992}
993
Zhi Huangcf990f52017-09-22 12:12:30 -0700994void BaseChannel::EnableSrtpTransport_n() {
995 if (srtp_transport_ == nullptr) {
996 rtp_transport_->SignalReadyToSend.disconnect(this);
997 rtp_transport_->SignalPacketReceived.disconnect(this);
Zhi Huang942bc2e2017-11-13 13:26:07 -0800998 rtp_transport_->SignalNetworkRouteChanged.disconnect(this);
Zhi Huangcf990f52017-09-22 12:12:30 -0700999
1000 auto transport = rtc::MakeUnique<webrtc::SrtpTransport>(
1001 std::move(rtp_transport_), content_name_);
1002 srtp_transport_ = transport.get();
1003 rtp_transport_ = std::move(transport);
1004
1005 rtp_transport_->SignalReadyToSend.connect(
1006 this, &BaseChannel::OnTransportReadyToSend);
1007 rtp_transport_->SignalPacketReceived.connect(
1008 this, &BaseChannel::OnPacketReceived);
Zhi Huang942bc2e2017-11-13 13:26:07 -08001009 rtp_transport_->SignalNetworkRouteChanged.connect(
1010 this, &BaseChannel::OnNetworkRouteChanged);
Mirko Bonadei675513b2017-11-09 11:09:25 +01001011 RTC_LOG(LS_INFO) << "Wrapping RtpTransport in SrtpTransport.";
Zhi Huangcf990f52017-09-22 12:12:30 -07001012 }
1013}
1014
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001015bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001016 ContentAction action,
1017 ContentSource src,
jbauch5869f502017-06-29 12:31:36 -07001018 const std::vector<int>& encrypted_extension_ids,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001019 std::string* error_desc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001020 TRACE_EVENT0("webrtc", "BaseChannel::SetSrtp_w");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001021 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001022 bool dtls = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001023 ret = CheckSrtpConfig_n(cryptos, &dtls, error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001024 if (!ret) {
1025 return false;
1026 }
Zhi Huangcf990f52017-09-22 12:12:30 -07001027
1028 // If SRTP was not required, but we're setting a description that uses SDES,
1029 // we need to upgrade to an SrtpTransport.
1030 if (!srtp_transport_ && !dtls && !cryptos.empty()) {
1031 EnableSrtpTransport_n();
1032 }
Zhi Huangc99b6c72017-11-10 16:44:46 -08001033
1034 bool encrypted_header_extensions_id_changed =
1035 EncryptedHeaderExtensionIdsChanged(src, encrypted_extension_ids);
1036 CacheEncryptedHeaderExtensionIds(src, encrypted_extension_ids);
1037
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001038 switch (action) {
1039 case CA_OFFER:
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001040 // If DTLS is already active on the channel, we could be renegotiating
1041 // here. We don't update the srtp filter.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001042 if (!dtls) {
Zhi Huangcf990f52017-09-22 12:12:30 -07001043 ret = sdes_negotiator_.SetOffer(cryptos, src);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001044 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001045 break;
1046 case CA_PRANSWER:
1047 // If we're doing DTLS-SRTP, we don't want to update the filter
1048 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001049 if (!dtls) {
Zhi Huangcf990f52017-09-22 12:12:30 -07001050 ret = sdes_negotiator_.SetProvisionalAnswer(cryptos, src);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001051 }
1052 break;
1053 case CA_ANSWER:
1054 // If we're doing DTLS-SRTP, we don't want to update the filter
1055 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001056 if (!dtls) {
Zhi Huangcf990f52017-09-22 12:12:30 -07001057 ret = sdes_negotiator_.SetAnswer(cryptos, src);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001058 }
1059 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001060 default:
1061 break;
1062 }
Zhi Huangcf990f52017-09-22 12:12:30 -07001063
1064 // If setting an SDES answer succeeded, apply the negotiated parameters
1065 // to the SRTP transport.
1066 if ((action == CA_PRANSWER || action == CA_ANSWER) && !dtls && ret) {
1067 if (sdes_negotiator_.send_cipher_suite() &&
1068 sdes_negotiator_.recv_cipher_suite()) {
Zhi Huangc99b6c72017-11-10 16:44:46 -08001069 RTC_DCHECK(catched_send_extension_ids_);
1070 RTC_DCHECK(catched_recv_extension_ids_);
Zhi Huangcf990f52017-09-22 12:12:30 -07001071 ret = srtp_transport_->SetRtpParams(
1072 *(sdes_negotiator_.send_cipher_suite()),
1073 sdes_negotiator_.send_key().data(),
1074 static_cast<int>(sdes_negotiator_.send_key().size()),
Zhi Huangc99b6c72017-11-10 16:44:46 -08001075 *(catched_send_extension_ids_),
Zhi Huangcf990f52017-09-22 12:12:30 -07001076 *(sdes_negotiator_.recv_cipher_suite()),
1077 sdes_negotiator_.recv_key().data(),
Zhi Huangc99b6c72017-11-10 16:44:46 -08001078 static_cast<int>(sdes_negotiator_.recv_key().size()),
1079 *(catched_recv_extension_ids_));
Zhi Huangcf990f52017-09-22 12:12:30 -07001080 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001081 RTC_LOG(LS_INFO) << "No crypto keys are provided for SDES.";
Zhi Huangcf990f52017-09-22 12:12:30 -07001082 if (action == CA_ANSWER && srtp_transport_) {
1083 // Explicitly reset the |srtp_transport_| if no crypto param is
1084 // provided in the answer. No need to call |ResetParams()| for
1085 // |sdes_negotiator_| because it resets the params inside |SetAnswer|.
1086 srtp_transport_->ResetParams();
1087 }
1088 }
1089 }
1090
Zhi Huangc99b6c72017-11-10 16:44:46 -08001091 // Only update SRTP transport if using DTLS. SDES is handled internally
jbauch5869f502017-06-29 12:31:36 -07001092 // by the SRTP filter.
Zhi Huangcf990f52017-09-22 12:12:30 -07001093 if (ret && dtls_active() && rtp_dtls_transport_ &&
Zhi Huangc99b6c72017-11-10 16:44:46 -08001094 rtp_dtls_transport_->dtls_state() == DTLS_TRANSPORT_CONNECTED &&
1095 encrypted_header_extensions_id_changed) {
1096 ret = SetupDtlsSrtp_n(/*rtcp=*/false);
jbauch5869f502017-06-29 12:31:36 -07001097 }
Zhi Huangc99b6c72017-11-10 16:44:46 -08001098
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001099 if (!ret) {
Zhi Huangc99b6c72017-11-10 16:44:46 -08001100 SafeSetError("Failed to setup SRTP.", error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001101 return false;
1102 }
1103 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001104}
1105
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001106bool BaseChannel::SetRtcpMux_n(bool enable,
1107 ContentAction action,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001108 ContentSource src,
1109 std::string* error_desc) {
deadbeef8e814d72017-01-13 11:34:39 -08001110 // Provide a more specific error message for the RTCP mux "require" policy
1111 // case.
zstein56162b92017-04-24 16:54:35 -07001112 if (rtcp_mux_required_ && !enable) {
deadbeef8e814d72017-01-13 11:34:39 -08001113 SafeSetError(
1114 "rtcpMuxPolicy is 'require', but media description does not "
1115 "contain 'a=rtcp-mux'.",
1116 error_desc);
1117 return false;
1118 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001119 bool ret = false;
1120 switch (action) {
1121 case CA_OFFER:
1122 ret = rtcp_mux_filter_.SetOffer(enable, src);
1123 break;
1124 case CA_PRANSWER:
zhihuangb2cdd932017-01-19 16:54:25 -08001125 // This may activate RTCP muxing, but we don't yet destroy the transport
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001126 // because the final answer may deactivate it.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001127 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
1128 break;
1129 case CA_ANSWER:
1130 ret = rtcp_mux_filter_.SetAnswer(enable, src);
1131 if (ret && rtcp_mux_filter_.IsActive()) {
deadbeefe814a0d2017-02-25 18:15:09 -08001132 // We permanently activated RTCP muxing; signal that we no longer need
1133 // the RTCP transport.
zsteind48dbda2017-04-04 19:45:57 -07001134 std::string debug_name =
1135 transport_name_.empty()
Zhi Huang942bc2e2017-11-13 13:26:07 -08001136 ? rtp_transport_->rtp_packet_transport()->transport_name()
zsteind48dbda2017-04-04 19:45:57 -07001137 : transport_name_;
Mirko Bonadei675513b2017-11-09 11:09:25 +01001138 RTC_LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
1139 << "; no longer need RTCP transport for "
1140 << debug_name;
zsteine8ab5432017-07-12 11:48:11 -07001141 if (rtp_transport_->rtcp_packet_transport()) {
deadbeeff5346592017-01-24 21:51:21 -08001142 SetTransport_n(true, nullptr, nullptr);
1143 SignalRtcpMuxFullyActive(transport_name_);
zhihuangf5b251b2017-01-12 19:37:48 -08001144 }
deadbeef062ce9f2016-08-26 21:42:15 -07001145 UpdateWritableState_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001146 }
1147 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001148 default:
1149 break;
1150 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001151 if (!ret) {
1152 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
1153 return false;
1154 }
zsteine8ab5432017-07-12 11:48:11 -07001155 rtp_transport_->SetRtcpMuxEnabled(rtcp_mux_filter_.IsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001156 // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
zhihuangb2cdd932017-01-19 16:54:25 -08001157 // CA_ANSWER, but we only want to tear down the RTCP transport if we received
1158 // a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001159 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001160 // If the RTP transport is already writable, then so are we.
zsteine8ab5432017-07-12 11:48:11 -07001161 if (rtp_transport_->rtp_packet_transport()->writable()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001162 ChannelWritable_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001163 }
1164 }
1165
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001166 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001167}
1168
1169bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001170 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -08001171 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001172}
1173
Peter Boström0c4e06b2015-10-07 12:23:21 +02001174bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001175 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001176 return media_channel()->RemoveRecvStream(ssrc);
1177}
1178
1179bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001180 ContentAction action,
1181 std::string* error_desc) {
Zhi Huang801b8682017-11-15 11:36:43 -08001182 if (!(action == CA_OFFER || action == CA_ANSWER || action == CA_PRANSWER))
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001183 return false;
1184
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001185 // Check for streams that have been removed.
1186 bool ret = true;
1187 for (StreamParamsVec::const_iterator it = local_streams_.begin();
1188 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001189 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001190 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001191 std::ostringstream desc;
1192 desc << "Failed to remove send stream with ssrc "
1193 << it->first_ssrc() << ".";
1194 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001195 ret = false;
1196 }
1197 }
1198 }
1199 // Check for new streams.
1200 for (StreamParamsVec::const_iterator it = streams.begin();
1201 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001202 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001203 if (media_channel()->AddSendStream(*it)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001204 RTC_LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001205 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001206 std::ostringstream desc;
1207 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1208 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001209 ret = false;
1210 }
1211 }
1212 }
1213 local_streams_ = streams;
1214 return ret;
1215}
1216
1217bool BaseChannel::UpdateRemoteStreams_w(
1218 const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001219 ContentAction action,
1220 std::string* error_desc) {
Zhi Huang801b8682017-11-15 11:36:43 -08001221 if (!(action == CA_OFFER || action == CA_ANSWER || action == CA_PRANSWER))
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001222 return false;
1223
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001224 // Check for streams that have been removed.
1225 bool ret = true;
1226 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
1227 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001228 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001229 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001230 std::ostringstream desc;
1231 desc << "Failed to remove remote stream with ssrc "
1232 << it->first_ssrc() << ".";
1233 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001234 ret = false;
1235 }
1236 }
1237 }
1238 // Check for new streams.
1239 for (StreamParamsVec::const_iterator it = streams.begin();
1240 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001241 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001242 if (AddRecvStream_w(*it)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001243 RTC_LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001244 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001245 std::ostringstream desc;
1246 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1247 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001248 ret = false;
1249 }
1250 }
1251 }
1252 remote_streams_ = streams;
1253 return ret;
1254}
1255
jbauch5869f502017-06-29 12:31:36 -07001256RtpHeaderExtensions BaseChannel::GetFilteredRtpHeaderExtensions(
1257 const RtpHeaderExtensions& extensions) {
1258 if (!rtp_dtls_transport_ ||
1259 !rtp_dtls_transport_->crypto_options()
1260 .enable_encrypted_rtp_header_extensions) {
1261 RtpHeaderExtensions filtered;
1262 auto pred = [](const webrtc::RtpExtension& extension) {
1263 return !extension.encrypt;
1264 };
1265 std::copy_if(extensions.begin(), extensions.end(),
1266 std::back_inserter(filtered), pred);
1267 return filtered;
1268 }
1269
1270 return webrtc::RtpExtension::FilterDuplicateNonEncrypted(extensions);
1271}
1272
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001273void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w(
isheriff6f8d6862016-05-26 11:24:55 -07001274 const std::vector<webrtc::RtpExtension>& extensions) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001275// Absolute Send Time extension id is used only with external auth,
1276// so do not bother searching for it and making asyncronious call to set
1277// something that is not used.
1278#if defined(ENABLE_EXTERNAL_AUTH)
isheriff6f8d6862016-05-26 11:24:55 -07001279 const webrtc::RtpExtension* send_time_extension =
jbauch5869f502017-06-29 12:31:36 -07001280 webrtc::RtpExtension::FindHeaderExtensionByUri(
1281 extensions, webrtc::RtpExtension::kAbsSendTimeUri);
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001282 int rtp_abs_sendtime_extn_id =
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001283 send_time_extension ? send_time_extension->id : -1;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001284 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001285 RTC_FROM_HERE, network_thread_,
1286 Bind(&BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n, this,
1287 rtp_abs_sendtime_extn_id));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001288#endif
1289}
1290
1291void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n(
1292 int rtp_abs_sendtime_extn_id) {
Zhi Huangcf990f52017-09-22 12:12:30 -07001293 if (srtp_transport_) {
1294 srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
1295 rtp_abs_sendtime_extn_id);
1296 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001297 RTC_LOG(LS_WARNING)
1298 << "Trying to cache the Absolute Send Time extension id "
1299 "but the SRTP is not active.";
Zhi Huangcf990f52017-09-22 12:12:30 -07001300 }
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001301}
1302
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001303void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001304 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001305 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001306 case MSG_SEND_RTP_PACKET:
1307 case MSG_SEND_RTCP_PACKET: {
1308 RTC_DCHECK(network_thread_->IsCurrent());
1309 SendPacketMessageData* data =
1310 static_cast<SendPacketMessageData*>(pmsg->pdata);
1311 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
1312 SendPacket(rtcp, &data->packet, data->options);
1313 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001314 break;
1315 }
1316 case MSG_FIRSTPACKETRECEIVED: {
1317 SignalFirstPacketReceived(this);
1318 break;
1319 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001320 }
1321}
1322
zstein3dcf0e92017-06-01 13:22:42 -07001323void BaseChannel::AddHandledPayloadType(int payload_type) {
zsteine8ab5432017-07-12 11:48:11 -07001324 rtp_transport_->AddHandledPayloadType(payload_type);
zstein3dcf0e92017-06-01 13:22:42 -07001325}
1326
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001327void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001328 // Flush all remaining RTCP messages. This should only be called in
1329 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001330 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001331 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001332 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
1333 for (const auto& message : rtcp_messages) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001334 network_thread_->Send(RTC_FROM_HERE, this, MSG_SEND_RTCP_PACKET,
1335 message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001336 }
1337}
1338
johand89ab142016-10-25 10:50:32 -07001339void BaseChannel::SignalSentPacket_n(
deadbeef5bd5ca32017-02-10 11:31:50 -08001340 rtc::PacketTransportInternal* /* transport */,
johand89ab142016-10-25 10:50:32 -07001341 const rtc::SentPacket& sent_packet) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001342 RTC_DCHECK(network_thread_->IsCurrent());
1343 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001344 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001345 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
1346}
1347
1348void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
1349 RTC_DCHECK(worker_thread_->IsCurrent());
1350 SignalSentPacket(sent_packet);
1351}
1352
Zhi Huangc99b6c72017-11-10 16:44:46 -08001353void BaseChannel::CacheEncryptedHeaderExtensionIds(
1354 cricket::ContentSource source,
1355 const std::vector<int>& extension_ids) {
1356 source == ContentSource::CS_LOCAL
1357 ? catched_recv_extension_ids_.emplace(extension_ids)
1358 : catched_send_extension_ids_.emplace(extension_ids);
1359}
1360
1361bool BaseChannel::EncryptedHeaderExtensionIdsChanged(
1362 cricket::ContentSource source,
1363 const std::vector<int>& new_extension_ids) {
1364 if (source == ContentSource::CS_LOCAL) {
1365 return !catched_recv_extension_ids_ ||
1366 (*catched_recv_extension_ids_) != new_extension_ids;
1367 } else {
1368 return !catched_send_extension_ids_ ||
1369 (*catched_send_extension_ids_) != new_extension_ids;
1370 }
1371}
1372
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001373VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
1374 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001375 rtc::Thread* signaling_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001376 MediaEngineInterface* media_engine,
Steve Anton8699a322017-11-06 15:53:33 -08001377 std::unique_ptr<VoiceMediaChannel> media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001378 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08001379 bool rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001380 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001381 : BaseChannel(worker_thread,
1382 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001383 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001384 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -07001385 content_name,
deadbeefac22f702017-01-12 21:59:29 -08001386 rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001387 srtp_required),
Steve Anton8699a322017-11-06 15:53:33 -08001388 media_engine_(media_engine) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001389
1390VoiceChannel::~VoiceChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001391 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001392 StopAudioMonitor();
1393 StopMediaMonitor();
1394 // this can't be done in the base class, since it calls a virtual
1395 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001396 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001397}
1398
Peter Boström0c4e06b2015-10-07 12:23:21 +02001399bool VoiceChannel::SetAudioSend(uint32_t ssrc,
solenbergdfc8f4f2015-10-01 02:31:10 -07001400 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001401 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001402 AudioSource* source) {
stefanf79ade12017-06-02 06:44:03 -07001403 return InvokeOnWorker<bool>(
1404 RTC_FROM_HERE, Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
1405 ssrc, enable, options, source));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001406}
1407
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001408// TODO(juberti): Handle early media the right way. We should get an explicit
1409// ringing message telling us to start playing local ringback, which we cancel
1410// if any early media actually arrives. For now, we do the opposite, which is
1411// to wait 1 second for early media, and start playing local ringback if none
1412// arrives.
1413void VoiceChannel::SetEarlyMedia(bool enable) {
1414 if (enable) {
1415 // Start the early media timeout
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001416 worker_thread()->PostDelayed(RTC_FROM_HERE, kEarlyMediaTimeout, this,
1417 MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001418 } else {
1419 // Stop the timeout if currently going.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001420 worker_thread()->Clear(this, MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001421 }
1422}
1423
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001424bool VoiceChannel::CanInsertDtmf() {
stefanf79ade12017-06-02 06:44:03 -07001425 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001426 RTC_FROM_HERE, Bind(&VoiceMediaChannel::CanInsertDtmf, media_channel()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001427}
1428
Peter Boström0c4e06b2015-10-07 12:23:21 +02001429bool VoiceChannel::InsertDtmf(uint32_t ssrc,
1430 int event_code,
solenberg1d63dd02015-12-02 12:35:09 -08001431 int duration) {
stefanf79ade12017-06-02 06:44:03 -07001432 return InvokeOnWorker<bool>(
1433 RTC_FROM_HERE,
1434 Bind(&VoiceChannel::InsertDtmf_w, this, ssrc, event_code, duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001435}
1436
solenberg4bac9c52015-10-09 02:32:53 -07001437bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) {
stefanf79ade12017-06-02 06:44:03 -07001438 return InvokeOnWorker<bool>(
1439 RTC_FROM_HERE,
1440 Bind(&VoiceMediaChannel::SetOutputVolume, media_channel(), ssrc, volume));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001441}
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001442
Tommif888bb52015-12-12 01:37:01 +01001443void VoiceChannel::SetRawAudioSink(
1444 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -08001445 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
1446 // We need to work around Bind's lack of support for unique_ptr and ownership
deadbeef2d110be2016-01-13 12:00:26 -08001447 // passing. So we invoke to our own little routine that gets a pointer to
1448 // our local variable. This is OK since we're synchronously invoking.
stefanf79ade12017-06-02 06:44:03 -07001449 InvokeOnWorker<bool>(RTC_FROM_HERE,
1450 Bind(&SetRawAudioSink_w, media_channel(), ssrc, &sink));
Tommif888bb52015-12-12 01:37:01 +01001451}
1452
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001453webrtc::RtpParameters VoiceChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001454 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001455 RTC_FROM_HERE, Bind(&VoiceChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001456}
1457
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001458webrtc::RtpParameters VoiceChannel::GetRtpSendParameters_w(
1459 uint32_t ssrc) const {
1460 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001461}
1462
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001463bool VoiceChannel::SetRtpSendParameters(
1464 uint32_t ssrc,
1465 const webrtc::RtpParameters& parameters) {
stefanf79ade12017-06-02 06:44:03 -07001466 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001467 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001468 Bind(&VoiceChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001469}
1470
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001471bool VoiceChannel::SetRtpSendParameters_w(uint32_t ssrc,
1472 webrtc::RtpParameters parameters) {
1473 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1474}
1475
1476webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters(
1477 uint32_t ssrc) const {
1478 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001479 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001480 Bind(&VoiceChannel::GetRtpReceiveParameters_w, this, ssrc));
1481}
1482
1483webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters_w(
1484 uint32_t ssrc) const {
1485 return media_channel()->GetRtpReceiveParameters(ssrc);
1486}
1487
1488bool VoiceChannel::SetRtpReceiveParameters(
1489 uint32_t ssrc,
1490 const webrtc::RtpParameters& parameters) {
stefanf79ade12017-06-02 06:44:03 -07001491 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001492 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001493 Bind(&VoiceChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1494}
1495
1496bool VoiceChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1497 webrtc::RtpParameters parameters) {
1498 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001499}
1500
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001501bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
stefanf79ade12017-06-02 06:44:03 -07001502 return InvokeOnWorker<bool>(RTC_FROM_HERE, Bind(&VoiceMediaChannel::GetStats,
1503 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001504}
1505
hbos8d609f62017-04-10 07:39:05 -07001506std::vector<webrtc::RtpSource> VoiceChannel::GetSources(uint32_t ssrc) const {
1507 return worker_thread()->Invoke<std::vector<webrtc::RtpSource>>(
zhihuang38ede132017-06-15 12:52:32 -07001508 RTC_FROM_HERE, Bind(&VoiceChannel::GetSources_w, this, ssrc));
1509}
1510
1511std::vector<webrtc::RtpSource> VoiceChannel::GetSources_w(uint32_t ssrc) const {
1512 RTC_DCHECK(worker_thread()->IsCurrent());
1513 return media_channel()->GetSources(ssrc);
hbos8d609f62017-04-10 07:39:05 -07001514}
1515
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001516void VoiceChannel::StartMediaMonitor(int cms) {
1517 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001518 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001519 media_monitor_->SignalUpdate.connect(
1520 this, &VoiceChannel::OnMediaMonitorUpdate);
1521 media_monitor_->Start(cms);
1522}
1523
1524void VoiceChannel::StopMediaMonitor() {
1525 if (media_monitor_) {
1526 media_monitor_->Stop();
1527 media_monitor_->SignalUpdate.disconnect(this);
1528 media_monitor_.reset();
1529 }
1530}
1531
1532void VoiceChannel::StartAudioMonitor(int cms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001533 audio_monitor_.reset(new AudioMonitor(this, rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001534 audio_monitor_
1535 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1536 audio_monitor_->Start(cms);
1537}
1538
1539void VoiceChannel::StopAudioMonitor() {
1540 if (audio_monitor_) {
1541 audio_monitor_->Stop();
1542 audio_monitor_.reset();
1543 }
1544}
1545
1546bool VoiceChannel::IsAudioMonitorRunning() const {
1547 return (audio_monitor_.get() != NULL);
1548}
1549
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001550int VoiceChannel::GetInputLevel_w() {
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001551 return media_engine_->GetInputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001552}
1553
1554int VoiceChannel::GetOutputLevel_w() {
1555 return media_channel()->GetOutputLevel();
1556}
1557
1558void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1559 media_channel()->GetActiveStreams(actives);
1560}
1561
zstein3dcf0e92017-06-01 13:22:42 -07001562void VoiceChannel::OnPacketReceived(bool rtcp,
zstein634977b2017-07-14 12:30:04 -07001563 rtc::CopyOnWriteBuffer* packet,
zstein3dcf0e92017-06-01 13:22:42 -07001564 const rtc::PacketTime& packet_time) {
1565 BaseChannel::OnPacketReceived(rtcp, packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001566 // Set a flag when we've received an RTP packet. If we're waiting for early
1567 // media, this will disable the timeout.
zstein3dcf0e92017-06-01 13:22:42 -07001568 if (!received_media_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001569 received_media_ = true;
1570 }
1571}
1572
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001573void BaseChannel::UpdateMediaSendRecvState() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001574 RTC_DCHECK(network_thread_->IsCurrent());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001575 invoker_.AsyncInvoke<void>(
1576 RTC_FROM_HERE, worker_thread_,
1577 Bind(&BaseChannel::UpdateMediaSendRecvState_w, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001578}
1579
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001580void VoiceChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001581 // Render incoming data if we're the active call, and we have the local
1582 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001583 bool recv = IsReadyToReceiveMedia_w();
solenberg5b14b422015-10-01 04:10:31 -07001584 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001585
1586 // Send outgoing data if we're the active call, we have the remote content,
1587 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001588 bool send = IsReadyToSendMedia_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001589 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001590
Mirko Bonadei675513b2017-11-09 11:09:25 +01001591 RTC_LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001592}
1593
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001594bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001595 ContentAction action,
1596 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001597 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001598 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001599 RTC_LOG(LS_INFO) << "Setting local voice description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001600
1601 const AudioContentDescription* audio =
1602 static_cast<const AudioContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001603 RTC_DCHECK(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001604 if (!audio) {
1605 SafeSetError("Can't find audio content in local description.", error_desc);
1606 return false;
1607 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001608
jbauch5869f502017-06-29 12:31:36 -07001609 RtpHeaderExtensions rtp_header_extensions =
1610 GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
1611
1612 if (!SetRtpTransportParameters(content, action, CS_LOCAL,
1613 rtp_header_extensions, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001614 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001615 }
1616
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001617 AudioRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07001618 RtpParametersFromMediaDescription(audio, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001619 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001620 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001621 error_desc);
1622 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001623 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001624 for (const AudioCodec& codec : audio->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07001625 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001626 }
1627 last_recv_params_ = recv_params;
1628
1629 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1630 // only give it to the media channel once we have a remote
1631 // description too (without a remote description, we won't be able
1632 // to send them anyway).
1633 if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) {
1634 SafeSetError("Failed to set local audio description streams.", error_desc);
1635 return false;
1636 }
1637
1638 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001639 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001640 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001641}
1642
1643bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001644 ContentAction action,
1645 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001646 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001647 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001648 RTC_LOG(LS_INFO) << "Setting remote voice description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001649
1650 const AudioContentDescription* audio =
1651 static_cast<const AudioContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001652 RTC_DCHECK(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001653 if (!audio) {
1654 SafeSetError("Can't find audio content in remote description.", error_desc);
1655 return false;
1656 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001657
jbauch5869f502017-06-29 12:31:36 -07001658 RtpHeaderExtensions rtp_header_extensions =
1659 GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
1660
1661 if (!SetRtpTransportParameters(content, action, CS_REMOTE,
1662 rtp_header_extensions, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001663 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001664 }
1665
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001666 AudioSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07001667 RtpSendParametersFromMediaDescription(audio, rtp_header_extensions,
1668 &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001669 if (audio->agc_minus_10db()) {
Oskar Sundbom36f8f3e2017-11-16 10:54:27 +01001670 send_params.options.adjust_agc_delta = kAgcMinus10db;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001671 }
skvladdc1c62c2016-03-16 19:07:43 -07001672
1673 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1674 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001675 SafeSetError("Failed to set remote audio description send parameters.",
1676 error_desc);
1677 return false;
1678 }
1679 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001680
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001681 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1682 // and only give it to the media channel once we have a local
1683 // description too (without a local description, we won't be able to
1684 // recv them anyway).
1685 if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) {
1686 SafeSetError("Failed to set remote audio description streams.", error_desc);
1687 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001688 }
1689
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001690 if (audio->rtp_header_extensions_set()) {
jbauch5869f502017-06-29 12:31:36 -07001691 MaybeCacheRtpAbsSendTimeHeaderExtension_w(rtp_header_extensions);
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001692 }
1693
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001694 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001695 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001696 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001697}
1698
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001699void VoiceChannel::HandleEarlyMediaTimeout() {
1700 // This occurs on the main thread, not the worker thread.
1701 if (!received_media_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001702 RTC_LOG(LS_INFO) << "No early media received before timeout";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001703 SignalEarlyMediaTimeout(this);
1704 }
1705}
1706
Peter Boström0c4e06b2015-10-07 12:23:21 +02001707bool VoiceChannel::InsertDtmf_w(uint32_t ssrc,
1708 int event,
solenberg1d63dd02015-12-02 12:35:09 -08001709 int duration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001710 if (!enabled()) {
1711 return false;
1712 }
solenberg1d63dd02015-12-02 12:35:09 -08001713 return media_channel()->InsertDtmf(ssrc, event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001714}
1715
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001716void VoiceChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001717 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001718 case MSG_EARLYMEDIATIMEOUT:
1719 HandleEarlyMediaTimeout();
1720 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001721 case MSG_CHANNEL_ERROR: {
1722 VoiceChannelErrorMessageData* data =
1723 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001724 delete data;
1725 break;
1726 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001727 default:
1728 BaseChannel::OnMessage(pmsg);
1729 break;
1730 }
1731}
1732
1733void VoiceChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001734 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001735 SignalConnectionMonitor(this, infos);
1736}
1737
1738void VoiceChannel::OnMediaMonitorUpdate(
1739 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001740 RTC_DCHECK(media_channel == this->media_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001741 SignalMediaMonitor(this, info);
1742}
1743
1744void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1745 const AudioInfo& info) {
1746 SignalAudioMonitor(this, info);
1747}
1748
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001749VideoChannel::VideoChannel(rtc::Thread* worker_thread,
1750 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001751 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001752 std::unique_ptr<VideoMediaChannel> media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001753 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08001754 bool rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001755 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001756 : BaseChannel(worker_thread,
1757 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001758 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001759 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -07001760 content_name,
deadbeefac22f702017-01-12 21:59:29 -08001761 rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001762 srtp_required) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001763
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001764VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001765 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001766 StopMediaMonitor();
1767 // this can't be done in the base class, since it calls a virtual
1768 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001769
1770 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001771}
1772
nisse08582ff2016-02-04 01:24:52 -08001773bool VideoChannel::SetSink(uint32_t ssrc,
nisseacd935b2016-11-11 03:55:13 -08001774 rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) {
nisse08582ff2016-02-04 01:24:52 -08001775 worker_thread()->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001776 RTC_FROM_HERE,
nisse08582ff2016-02-04 01:24:52 -08001777 Bind(&VideoMediaChannel::SetSink, media_channel(), ssrc, sink));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001778 return true;
1779}
1780
deadbeef5a4a75a2016-06-02 16:23:38 -07001781bool VideoChannel::SetVideoSend(
nisse2ded9b12016-04-08 02:23:55 -07001782 uint32_t ssrc,
deadbeef5a4a75a2016-06-02 16:23:38 -07001783 bool mute,
1784 const VideoOptions* options,
nisseacd935b2016-11-11 03:55:13 -08001785 rtc::VideoSourceInterface<webrtc::VideoFrame>* source) {
stefanf79ade12017-06-02 06:44:03 -07001786 return InvokeOnWorker<bool>(
1787 RTC_FROM_HERE, Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
1788 ssrc, mute, options, source));
solenberg1dd98f32015-09-10 01:57:14 -07001789}
1790
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001791webrtc::RtpParameters VideoChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001792 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001793 RTC_FROM_HERE, Bind(&VideoChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001794}
1795
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001796webrtc::RtpParameters VideoChannel::GetRtpSendParameters_w(
1797 uint32_t ssrc) const {
1798 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001799}
1800
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001801bool VideoChannel::SetRtpSendParameters(
1802 uint32_t ssrc,
1803 const webrtc::RtpParameters& parameters) {
stefanf79ade12017-06-02 06:44:03 -07001804 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001805 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001806 Bind(&VideoChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001807}
1808
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001809bool VideoChannel::SetRtpSendParameters_w(uint32_t ssrc,
1810 webrtc::RtpParameters parameters) {
1811 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1812}
1813
1814webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters(
1815 uint32_t ssrc) const {
1816 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001817 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001818 Bind(&VideoChannel::GetRtpReceiveParameters_w, this, ssrc));
1819}
1820
1821webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters_w(
1822 uint32_t ssrc) const {
1823 return media_channel()->GetRtpReceiveParameters(ssrc);
1824}
1825
1826bool VideoChannel::SetRtpReceiveParameters(
1827 uint32_t ssrc,
1828 const webrtc::RtpParameters& parameters) {
stefanf79ade12017-06-02 06:44:03 -07001829 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001830 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001831 Bind(&VideoChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1832}
1833
1834bool VideoChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1835 webrtc::RtpParameters parameters) {
1836 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001837}
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001838
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001839void VideoChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001840 // Send outgoing data if we're the active call, we have the remote content,
1841 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001842 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001843 if (!media_channel()->SetSend(send)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001844 RTC_LOG(LS_ERROR) << "Failed to SetSend on video channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001845 // TODO(gangji): Report error back to server.
1846 }
1847
Mirko Bonadei675513b2017-11-09 11:09:25 +01001848 RTC_LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001849}
1850
stefanf79ade12017-06-02 06:44:03 -07001851void VideoChannel::FillBitrateInfo(BandwidthEstimationInfo* bwe_info) {
1852 InvokeOnWorker<void>(RTC_FROM_HERE, Bind(&VideoMediaChannel::FillBitrateInfo,
1853 media_channel(), bwe_info));
1854}
1855
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00001856bool VideoChannel::GetStats(VideoMediaInfo* stats) {
stefanf79ade12017-06-02 06:44:03 -07001857 return InvokeOnWorker<bool>(RTC_FROM_HERE, Bind(&VideoMediaChannel::GetStats,
1858 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001859}
1860
1861void VideoChannel::StartMediaMonitor(int cms) {
1862 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001863 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001864 media_monitor_->SignalUpdate.connect(
1865 this, &VideoChannel::OnMediaMonitorUpdate);
1866 media_monitor_->Start(cms);
1867}
1868
1869void VideoChannel::StopMediaMonitor() {
1870 if (media_monitor_) {
1871 media_monitor_->Stop();
1872 media_monitor_.reset();
1873 }
1874}
1875
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001876bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001877 ContentAction action,
1878 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001879 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001880 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001881 RTC_LOG(LS_INFO) << "Setting local video description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001882
1883 const VideoContentDescription* video =
1884 static_cast<const VideoContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001885 RTC_DCHECK(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001886 if (!video) {
1887 SafeSetError("Can't find video content in local description.", error_desc);
1888 return false;
1889 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001890
jbauch5869f502017-06-29 12:31:36 -07001891 RtpHeaderExtensions rtp_header_extensions =
1892 GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
1893
1894 if (!SetRtpTransportParameters(content, action, CS_LOCAL,
1895 rtp_header_extensions, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001896 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001897 }
1898
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001899 VideoRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07001900 RtpParametersFromMediaDescription(video, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001901 if (!media_channel()->SetRecvParameters(recv_params)) {
1902 SafeSetError("Failed to set local video description recv parameters.",
1903 error_desc);
1904 return false;
1905 }
1906 for (const VideoCodec& codec : video->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07001907 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001908 }
1909 last_recv_params_ = recv_params;
1910
1911 // TODO(pthatcher): Move local streams into VideoSendParameters, and
1912 // only give it to the media channel once we have a remote
1913 // description too (without a remote description, we won't be able
1914 // to send them anyway).
1915 if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) {
1916 SafeSetError("Failed to set local video description streams.", error_desc);
1917 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001918 }
1919
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001920 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001921 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001922 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001923}
1924
1925bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001926 ContentAction action,
1927 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001928 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001929 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001930 RTC_LOG(LS_INFO) << "Setting remote video description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001931
1932 const VideoContentDescription* video =
1933 static_cast<const VideoContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001934 RTC_DCHECK(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001935 if (!video) {
1936 SafeSetError("Can't find video content in remote description.", error_desc);
1937 return false;
1938 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001939
jbauch5869f502017-06-29 12:31:36 -07001940 RtpHeaderExtensions rtp_header_extensions =
1941 GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
1942
1943 if (!SetRtpTransportParameters(content, action, CS_REMOTE,
1944 rtp_header_extensions, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001945 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001946 }
1947
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001948 VideoSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07001949 RtpSendParametersFromMediaDescription(video, rtp_header_extensions,
1950 &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001951 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08001952 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001953 }
skvladdc1c62c2016-03-16 19:07:43 -07001954
1955 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1956
1957 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001958 SafeSetError("Failed to set remote video description send parameters.",
1959 error_desc);
1960 return false;
1961 }
1962 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001963
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001964 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
1965 // and only give it to the media channel once we have a local
1966 // description too (without a local description, we won't be able to
1967 // recv them anyway).
1968 if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) {
1969 SafeSetError("Failed to set remote video description streams.", error_desc);
1970 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001971 }
1972
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001973 if (video->rtp_header_extensions_set()) {
jbauch5869f502017-06-29 12:31:36 -07001974 MaybeCacheRtpAbsSendTimeHeaderExtension_w(rtp_header_extensions);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001975 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001976
1977 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001978 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001979 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001980}
1981
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001982void VideoChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001983 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001984 case MSG_CHANNEL_ERROR: {
1985 const VideoChannelErrorMessageData* data =
1986 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001987 delete data;
1988 break;
1989 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001990 default:
1991 BaseChannel::OnMessage(pmsg);
1992 break;
1993 }
1994}
1995
1996void VideoChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001997 ConnectionMonitor* monitor, const std::vector<ConnectionInfo> &infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001998 SignalConnectionMonitor(this, infos);
1999}
2000
2001// TODO(pthatcher): Look into removing duplicate code between
2002// audio, video, and data, perhaps by using templates.
2003void VideoChannel::OnMediaMonitorUpdate(
2004 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002005 RTC_DCHECK(media_channel == this->media_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002006 SignalMediaMonitor(this, info);
2007}
2008
deadbeef953c2ce2017-01-09 14:53:41 -08002009RtpDataChannel::RtpDataChannel(rtc::Thread* worker_thread,
2010 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08002011 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08002012 std::unique_ptr<DataMediaChannel> media_channel,
deadbeef953c2ce2017-01-09 14:53:41 -08002013 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08002014 bool rtcp_mux_required,
deadbeef953c2ce2017-01-09 14:53:41 -08002015 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002016 : BaseChannel(worker_thread,
2017 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08002018 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08002019 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -07002020 content_name,
deadbeefac22f702017-01-12 21:59:29 -08002021 rtcp_mux_required,
deadbeef953c2ce2017-01-09 14:53:41 -08002022 srtp_required) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002023
deadbeef953c2ce2017-01-09 14:53:41 -08002024RtpDataChannel::~RtpDataChannel() {
2025 TRACE_EVENT0("webrtc", "RtpDataChannel::~RtpDataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002026 StopMediaMonitor();
2027 // this can't be done in the base class, since it calls a virtual
2028 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00002029
2030 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002031}
2032
Steve Anton8699a322017-11-06 15:53:33 -08002033void RtpDataChannel::Init_w(
deadbeeff5346592017-01-24 21:51:21 -08002034 DtlsTransportInternal* rtp_dtls_transport,
2035 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -08002036 rtc::PacketTransportInternal* rtp_packet_transport,
2037 rtc::PacketTransportInternal* rtcp_packet_transport) {
Steve Anton8699a322017-11-06 15:53:33 -08002038 BaseChannel::Init_w(rtp_dtls_transport, rtcp_dtls_transport,
2039 rtp_packet_transport, rtcp_packet_transport);
2040
deadbeef953c2ce2017-01-09 14:53:41 -08002041 media_channel()->SignalDataReceived.connect(this,
2042 &RtpDataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002043 media_channel()->SignalReadyToSend.connect(
deadbeef953c2ce2017-01-09 14:53:41 -08002044 this, &RtpDataChannel::OnDataChannelReadyToSend);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002045}
2046
deadbeef953c2ce2017-01-09 14:53:41 -08002047bool RtpDataChannel::SendData(const SendDataParams& params,
2048 const rtc::CopyOnWriteBuffer& payload,
2049 SendDataResult* result) {
stefanf79ade12017-06-02 06:44:03 -07002050 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002051 RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params,
2052 payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002053}
2054
deadbeef953c2ce2017-01-09 14:53:41 -08002055bool RtpDataChannel::CheckDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002056 const DataContentDescription* content,
2057 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002058 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
2059 (content->protocol() == kMediaProtocolDtlsSctp));
deadbeef953c2ce2017-01-09 14:53:41 -08002060 // It's been set before, but doesn't match. That's bad.
2061 if (is_sctp) {
2062 SafeSetError("Data channel type mismatch. Expected RTP, got SCTP.",
2063 error_desc);
2064 return false;
2065 }
2066 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002067}
2068
deadbeef953c2ce2017-01-09 14:53:41 -08002069bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content,
2070 ContentAction action,
2071 std::string* error_desc) {
2072 TRACE_EVENT0("webrtc", "RtpDataChannel::SetLocalContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002073 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
Mirko Bonadei675513b2017-11-09 11:09:25 +01002074 RTC_LOG(LS_INFO) << "Setting local data description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002075
2076 const DataContentDescription* data =
2077 static_cast<const DataContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002078 RTC_DCHECK(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002079 if (!data) {
2080 SafeSetError("Can't find data content in local description.", error_desc);
2081 return false;
2082 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002083
deadbeef953c2ce2017-01-09 14:53:41 -08002084 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002085 return false;
2086 }
2087
jbauch5869f502017-06-29 12:31:36 -07002088 RtpHeaderExtensions rtp_header_extensions =
2089 GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
2090
2091 if (!SetRtpTransportParameters(content, action, CS_LOCAL,
2092 rtp_header_extensions, error_desc)) {
deadbeef953c2ce2017-01-09 14:53:41 -08002093 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002094 }
2095
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002096 DataRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07002097 RtpParametersFromMediaDescription(data, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002098 if (!media_channel()->SetRecvParameters(recv_params)) {
2099 SafeSetError("Failed to set remote data description recv parameters.",
2100 error_desc);
2101 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002102 }
deadbeef953c2ce2017-01-09 14:53:41 -08002103 for (const DataCodec& codec : data->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07002104 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002105 }
2106 last_recv_params_ = recv_params;
2107
2108 // TODO(pthatcher): Move local streams into DataSendParameters, and
2109 // only give it to the media channel once we have a remote
2110 // description too (without a remote description, we won't be able
2111 // to send them anyway).
2112 if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) {
2113 SafeSetError("Failed to set local data description streams.", error_desc);
2114 return false;
2115 }
2116
2117 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002118 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002119 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002120}
2121
deadbeef953c2ce2017-01-09 14:53:41 -08002122bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content,
2123 ContentAction action,
2124 std::string* error_desc) {
2125 TRACE_EVENT0("webrtc", "RtpDataChannel::SetRemoteContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002126 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002127
2128 const DataContentDescription* data =
2129 static_cast<const DataContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002130 RTC_DCHECK(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002131 if (!data) {
2132 SafeSetError("Can't find data content in remote description.", error_desc);
2133 return false;
2134 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002135
Zhi Huang801b8682017-11-15 11:36:43 -08002136 // If the remote data doesn't have codecs, it must be empty, so ignore it.
2137 if (!data->has_codecs()) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002138 return true;
2139 }
2140
deadbeef953c2ce2017-01-09 14:53:41 -08002141 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002142 return false;
2143 }
2144
jbauch5869f502017-06-29 12:31:36 -07002145 RtpHeaderExtensions rtp_header_extensions =
2146 GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
2147
Mirko Bonadei675513b2017-11-09 11:09:25 +01002148 RTC_LOG(LS_INFO) << "Setting remote data description";
jbauch5869f502017-06-29 12:31:36 -07002149 if (!SetRtpTransportParameters(content, action, CS_REMOTE,
2150 rtp_header_extensions, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002151 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002152 }
2153
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002154 DataSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07002155 RtpSendParametersFromMediaDescription<DataCodec>(data, rtp_header_extensions,
2156 &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002157 if (!media_channel()->SetSendParameters(send_params)) {
2158 SafeSetError("Failed to set remote data description send parameters.",
2159 error_desc);
2160 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002161 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002162 last_send_params_ = send_params;
2163
2164 // TODO(pthatcher): Move remote streams into DataRecvParameters,
2165 // and only give it to the media channel once we have a local
2166 // description too (without a local description, we won't be able to
2167 // recv them anyway).
2168 if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) {
2169 SafeSetError("Failed to set remote data description streams.",
2170 error_desc);
2171 return false;
2172 }
2173
2174 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002175 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002176 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002177}
2178
deadbeef953c2ce2017-01-09 14:53:41 -08002179void RtpDataChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002180 // Render incoming data if we're the active call, and we have the local
2181 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002182 bool recv = IsReadyToReceiveMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002183 if (!media_channel()->SetReceive(recv)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01002184 RTC_LOG(LS_ERROR) << "Failed to SetReceive on data channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002185 }
2186
2187 // Send outgoing data if we're the active call, we have the remote content,
2188 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002189 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002190 if (!media_channel()->SetSend(send)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01002191 RTC_LOG(LS_ERROR) << "Failed to SetSend on data channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002192 }
2193
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002194 // Trigger SignalReadyToSendData asynchronously.
2195 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002196
Mirko Bonadei675513b2017-11-09 11:09:25 +01002197 RTC_LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002198}
2199
deadbeef953c2ce2017-01-09 14:53:41 -08002200void RtpDataChannel::OnMessage(rtc::Message* pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002201 switch (pmsg->message_id) {
2202 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002203 DataChannelReadyToSendMessageData* data =
2204 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002205 ready_to_send_data_ = data->data();
2206 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002207 delete data;
2208 break;
2209 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002210 case MSG_DATARECEIVED: {
2211 DataReceivedMessageData* data =
2212 static_cast<DataReceivedMessageData*>(pmsg->pdata);
deadbeef953c2ce2017-01-09 14:53:41 -08002213 SignalDataReceived(data->params, data->payload);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002214 delete data;
2215 break;
2216 }
2217 case MSG_CHANNEL_ERROR: {
2218 const DataChannelErrorMessageData* data =
2219 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002220 delete data;
2221 break;
2222 }
2223 default:
2224 BaseChannel::OnMessage(pmsg);
2225 break;
2226 }
2227}
2228
deadbeef953c2ce2017-01-09 14:53:41 -08002229void RtpDataChannel::OnConnectionMonitorUpdate(
2230 ConnectionMonitor* monitor,
2231 const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002232 SignalConnectionMonitor(this, infos);
2233}
2234
deadbeef953c2ce2017-01-09 14:53:41 -08002235void RtpDataChannel::StartMediaMonitor(int cms) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002236 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002237 rtc::Thread::Current()));
deadbeef953c2ce2017-01-09 14:53:41 -08002238 media_monitor_->SignalUpdate.connect(this,
2239 &RtpDataChannel::OnMediaMonitorUpdate);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002240 media_monitor_->Start(cms);
2241}
2242
deadbeef953c2ce2017-01-09 14:53:41 -08002243void RtpDataChannel::StopMediaMonitor() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002244 if (media_monitor_) {
2245 media_monitor_->Stop();
2246 media_monitor_->SignalUpdate.disconnect(this);
2247 media_monitor_.reset();
2248 }
2249}
2250
deadbeef953c2ce2017-01-09 14:53:41 -08002251void RtpDataChannel::OnMediaMonitorUpdate(DataMediaChannel* media_channel,
2252 const DataMediaInfo& info) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002253 RTC_DCHECK(media_channel == this->media_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002254 SignalMediaMonitor(this, info);
2255}
2256
deadbeef953c2ce2017-01-09 14:53:41 -08002257void RtpDataChannel::OnDataReceived(const ReceiveDataParams& params,
2258 const char* data,
2259 size_t len) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002260 DataReceivedMessageData* msg = new DataReceivedMessageData(
2261 params, data, len);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002262 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002263}
2264
deadbeef953c2ce2017-01-09 14:53:41 -08002265void RtpDataChannel::OnDataChannelError(uint32_t ssrc,
2266 DataMediaChannel::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002267 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2268 ssrc, err);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002269 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_CHANNEL_ERROR, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002270}
2271
deadbeef953c2ce2017-01-09 14:53:41 -08002272void RtpDataChannel::OnDataChannelReadyToSend(bool writable) {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002273 // This is usded for congestion control to indicate that the stream is ready
2274 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2275 // that the transport channel is ready.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002276 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002277 new DataChannelReadyToSendMessageData(writable));
2278}
2279
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002280} // namespace cricket