blob: f5428a43effac7a93fce554e11946c220946337c [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
kwiberg0eb15ed2015-12-17 03:04:15 -080011#include <utility>
12
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010013#include "webrtc/pc/channel.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014
kjellandera69d9732016-08-31 07:33:05 -070015#include "webrtc/api/call/audio_sink.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000016#include "webrtc/base/bind.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000017#include "webrtc/base/byteorder.h"
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -070018#include "webrtc/base/checks.h"
jbaucheec21bd2016-03-20 06:15:43 -070019#include "webrtc/base/copyonwritebuffer.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000020#include "webrtc/base/dscp.h"
21#include "webrtc/base/logging.h"
Honghai Zhangcc411c02016-03-29 17:27:21 -070022#include "webrtc/base/networkroute.h"
Peter Boström6f28cf02015-12-07 23:17:15 +010023#include "webrtc/base/trace_event.h"
kjellanderf4752772016-03-02 05:42:30 -080024#include "webrtc/media/base/mediaconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080025#include "webrtc/media/base/rtputils.h"
hbos8d609f62017-04-10 07:39:05 -070026#include "webrtc/media/engine/webrtcvoiceengine.h"
deadbeef5bd5ca32017-02-10 11:31:50 -080027#include "webrtc/p2p/base/packettransportinternal.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010028#include "webrtc/pc/channelmanager.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000029
30namespace cricket {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000031using rtc::Bind;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000032
deadbeef2d110be2016-01-13 12:00:26 -080033namespace {
kwiberg31022942016-03-11 14:18:21 -080034// See comment below for why we need to use a pointer to a unique_ptr.
deadbeef2d110be2016-01-13 12:00:26 -080035bool SetRawAudioSink_w(VoiceMediaChannel* channel,
36 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -080037 std::unique_ptr<webrtc::AudioSinkInterface>* sink) {
38 channel->SetRawAudioSink(ssrc, std::move(*sink));
deadbeef2d110be2016-01-13 12:00:26 -080039 return true;
40}
Danil Chapovalov33b01f22016-05-11 19:55:27 +020041
42struct SendPacketMessageData : public rtc::MessageData {
43 rtc::CopyOnWriteBuffer packet;
44 rtc::PacketOptions options;
45};
46
isheriff6f8d6862016-05-26 11:24:55 -070047#if defined(ENABLE_EXTERNAL_AUTH)
48// Returns the named header extension if found among all extensions,
49// nullptr otherwise.
50const webrtc::RtpExtension* FindHeaderExtension(
51 const std::vector<webrtc::RtpExtension>& extensions,
52 const std::string& uri) {
53 for (const auto& extension : extensions) {
54 if (extension.uri == uri)
55 return &extension;
56 }
57 return nullptr;
58}
59#endif
60
deadbeef2d110be2016-01-13 12:00:26 -080061} // namespace
62
henrike@webrtc.org28e20752013-07-10 00:45:36 +000063enum {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000064 MSG_EARLYMEDIATIMEOUT = 1,
Danil Chapovalov33b01f22016-05-11 19:55:27 +020065 MSG_SEND_RTP_PACKET,
66 MSG_SEND_RTCP_PACKET,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067 MSG_CHANNEL_ERROR,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000069 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000070 MSG_FIRSTPACKETRECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000071};
72
73// Value specified in RFC 5764.
74static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
75
76static const int kAgcMinus10db = -10;
77
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000078static void SafeSetError(const std::string& message, std::string* error_desc) {
79 if (error_desc) {
80 *error_desc = message;
81 }
82}
83
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000084struct VoiceChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020085 VoiceChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086 VoiceMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020087 : ssrc(in_ssrc), error(in_error) {}
88 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089 VoiceMediaChannel::Error error;
90};
91
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000092struct VideoChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020093 VideoChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094 VideoMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020095 : ssrc(in_ssrc), error(in_error) {}
96 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097 VideoMediaChannel::Error error;
98};
99
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000100struct DataChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200101 DataChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102 DataMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +0200103 : ssrc(in_ssrc), error(in_error) {}
104 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000105 DataMediaChannel::Error error;
106};
107
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108static const char* PacketType(bool rtcp) {
109 return (!rtcp) ? "RTP" : "RTCP";
110}
111
jbaucheec21bd2016-03-20 06:15:43 -0700112static bool ValidPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113 // Check the packet size. We could check the header too if needed.
114 return (packet &&
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000115 packet->size() >= (!rtcp ? kMinRtpPacketLen : kMinRtcpPacketLen) &&
116 packet->size() <= kMaxRtpPacketLen);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000117}
118
119static bool IsReceiveContentDirection(MediaContentDirection direction) {
120 return direction == MD_SENDRECV || direction == MD_RECVONLY;
121}
122
123static bool IsSendContentDirection(MediaContentDirection direction) {
124 return direction == MD_SENDRECV || direction == MD_SENDONLY;
125}
126
127static const MediaContentDescription* GetContentDescription(
128 const ContentInfo* cinfo) {
129 if (cinfo == NULL)
130 return NULL;
131 return static_cast<const MediaContentDescription*>(cinfo->description);
132}
133
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700134template <class Codec>
135void RtpParametersFromMediaDescription(
136 const MediaContentDescriptionImpl<Codec>* desc,
137 RtpParameters<Codec>* params) {
138 // TODO(pthatcher): Remove this once we're sure no one will give us
139 // a description without codecs (currently a CA_UPDATE with just
140 // streams can).
141 if (desc->has_codecs()) {
142 params->codecs = desc->codecs();
143 }
144 // TODO(pthatcher): See if we really need
145 // rtp_header_extensions_set() and remove it if we don't.
146 if (desc->rtp_header_extensions_set()) {
147 params->extensions = desc->rtp_header_extensions();
148 }
deadbeef13871492015-12-09 12:37:51 -0800149 params->rtcp.reduced_size = desc->rtcp_reduced_size();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700150}
151
nisse05103312016-03-16 02:22:50 -0700152template <class Codec>
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700153void RtpSendParametersFromMediaDescription(
154 const MediaContentDescriptionImpl<Codec>* desc,
nisse05103312016-03-16 02:22:50 -0700155 RtpSendParameters<Codec>* send_params) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700156 RtpParametersFromMediaDescription(desc, send_params);
157 send_params->max_bandwidth_bps = desc->bandwidth();
158}
159
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200160BaseChannel::BaseChannel(rtc::Thread* worker_thread,
161 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800162 rtc::Thread* signaling_thread,
deadbeefcbecd352015-09-23 11:50:27 -0700163 MediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -0700164 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -0800165 bool rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -0800166 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200167 : worker_thread_(worker_thread),
168 network_thread_(network_thread),
zhihuangf5b251b2017-01-12 19:37:48 -0800169 signaling_thread_(signaling_thread),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000170 content_name_(content_name),
zstein56162b92017-04-24 16:54:35 -0700171 rtcp_mux_required_(rtcp_mux_required),
zsteind48dbda2017-04-04 19:45:57 -0700172 rtp_transport_(rtcp_mux_required),
deadbeef7af91dd2016-12-13 11:29:11 -0800173 srtp_required_(srtp_required),
michaelt79e05882016-11-08 02:50:09 -0800174 media_channel_(media_channel),
175 selected_candidate_pair_(nullptr) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700176 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
jbauchdfcab722017-03-06 00:14:10 -0800177#if defined(ENABLE_EXTERNAL_AUTH)
178 srtp_filter_.EnableExternalAuth();
179#endif
zstein56162b92017-04-24 16:54:35 -0700180 rtp_transport_.SignalReadyToSend.connect(
181 this, &BaseChannel::OnTransportReadyToSend);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000182 LOG(LS_INFO) << "Created channel for " << content_name;
183}
184
185BaseChannel::~BaseChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800186 TRACE_EVENT0("webrtc", "BaseChannel::~BaseChannel");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700187 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
wu@webrtc.org78187522013-10-07 23:32:02 +0000188 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000189 StopConnectionMonitor();
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200190 // Eats any outstanding messages or packets.
191 worker_thread_->Clear(&invoker_);
192 worker_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000193 // We must destroy the media channel before the transport channel, otherwise
194 // the media channel may try to send on the dead transport channel. NULLing
195 // is not an effective strategy since the sends will come on another thread.
196 delete media_channel_;
zhihuangf5b251b2017-01-12 19:37:48 -0800197 LOG(LS_INFO) << "Destroyed channel: " << content_name_;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200198}
199
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200200void BaseChannel::DisconnectTransportChannels_n() {
201 // Send any outstanding RTCP packets.
202 FlushRtcpMessages_n();
203
204 // Stop signals from transport channels, but keep them alive because
205 // media_channel may use them from a different thread.
zhihuangb2cdd932017-01-19 16:54:25 -0800206 if (rtp_dtls_transport_) {
deadbeeff5346592017-01-24 21:51:21 -0800207 DisconnectFromDtlsTransport(rtp_dtls_transport_);
zsteind48dbda2017-04-04 19:45:57 -0700208 } else if (rtp_transport_.rtp_packet_transport()) {
209 DisconnectFromPacketTransport(rtp_transport_.rtp_packet_transport());
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200210 }
zhihuangb2cdd932017-01-19 16:54:25 -0800211 if (rtcp_dtls_transport_) {
deadbeeff5346592017-01-24 21:51:21 -0800212 DisconnectFromDtlsTransport(rtcp_dtls_transport_);
zsteind48dbda2017-04-04 19:45:57 -0700213 } else if (rtp_transport_.rtcp_packet_transport()) {
214 DisconnectFromPacketTransport(rtp_transport_.rtcp_packet_transport());
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200215 }
216
217 // Clear pending read packets/messages.
218 network_thread_->Clear(&invoker_);
219 network_thread_->Clear(this);
220}
221
zhihuangb2cdd932017-01-19 16:54:25 -0800222bool BaseChannel::Init_w(DtlsTransportInternal* rtp_dtls_transport,
deadbeeff5346592017-01-24 21:51:21 -0800223 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800224 rtc::PacketTransportInternal* rtp_packet_transport,
225 rtc::PacketTransportInternal* rtcp_packet_transport) {
skvlad6c87a672016-05-17 17:49:52 -0700226 if (!network_thread_->Invoke<bool>(
zhihuangb2cdd932017-01-19 16:54:25 -0800227 RTC_FROM_HERE, Bind(&BaseChannel::InitNetwork_n, this,
deadbeeff5346592017-01-24 21:51:21 -0800228 rtp_dtls_transport, rtcp_dtls_transport,
229 rtp_packet_transport, rtcp_packet_transport))) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000230 return false;
231 }
deadbeeff5346592017-01-24 21:51:21 -0800232 // Both RTP and RTCP channels should be set, we can call SetInterface on
233 // the media channel and it can set network options.
234 RTC_DCHECK_RUN_ON(worker_thread_);
wu@webrtc.orgde305012013-10-31 15:40:38 +0000235 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000236 return true;
237}
238
deadbeeff5346592017-01-24 21:51:21 -0800239bool BaseChannel::InitNetwork_n(
240 DtlsTransportInternal* rtp_dtls_transport,
241 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800242 rtc::PacketTransportInternal* rtp_packet_transport,
243 rtc::PacketTransportInternal* rtcp_packet_transport) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200244 RTC_DCHECK(network_thread_->IsCurrent());
deadbeeff5346592017-01-24 21:51:21 -0800245 SetTransports_n(rtp_dtls_transport, rtcp_dtls_transport, rtp_packet_transport,
246 rtcp_packet_transport);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200247
zstein56162b92017-04-24 16:54:35 -0700248 if (rtcp_mux_required_) {
deadbeefac22f702017-01-12 21:59:29 -0800249 rtcp_mux_filter_.SetActive();
250 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200251 return true;
252}
253
wu@webrtc.org78187522013-10-07 23:32:02 +0000254void BaseChannel::Deinit() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200255 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.org78187522013-10-07 23:32:02 +0000256 media_channel_->SetInterface(NULL);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200257 // Packets arrive on the network thread, processing packets calls virtual
258 // functions, so need to stop this process in Deinit that is called in
259 // derived classes destructor.
260 network_thread_->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700261 RTC_FROM_HERE, Bind(&BaseChannel::DisconnectTransportChannels_n, this));
wu@webrtc.org78187522013-10-07 23:32:02 +0000262}
263
zhihuangb2cdd932017-01-19 16:54:25 -0800264void BaseChannel::SetTransports(DtlsTransportInternal* rtp_dtls_transport,
265 DtlsTransportInternal* rtcp_dtls_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800266 network_thread_->Invoke<void>(
267 RTC_FROM_HERE,
268 Bind(&BaseChannel::SetTransports_n, this, rtp_dtls_transport,
269 rtcp_dtls_transport, rtp_dtls_transport, rtcp_dtls_transport));
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000270}
271
deadbeeff5346592017-01-24 21:51:21 -0800272void BaseChannel::SetTransports(
deadbeef5bd5ca32017-02-10 11:31:50 -0800273 rtc::PacketTransportInternal* rtp_packet_transport,
274 rtc::PacketTransportInternal* rtcp_packet_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800275 network_thread_->Invoke<void>(
276 RTC_FROM_HERE, Bind(&BaseChannel::SetTransports_n, this, nullptr, nullptr,
277 rtp_packet_transport, rtcp_packet_transport));
278}
zhihuangf5b251b2017-01-12 19:37:48 -0800279
deadbeeff5346592017-01-24 21:51:21 -0800280void BaseChannel::SetTransports_n(
281 DtlsTransportInternal* rtp_dtls_transport,
282 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -0800283 rtc::PacketTransportInternal* rtp_packet_transport,
284 rtc::PacketTransportInternal* rtcp_packet_transport) {
deadbeeff5346592017-01-24 21:51:21 -0800285 RTC_DCHECK(network_thread_->IsCurrent());
286 // Validate some assertions about the input.
287 RTC_DCHECK(rtp_packet_transport);
288 RTC_DCHECK_EQ(NeedsRtcpTransport(), rtcp_packet_transport != nullptr);
289 if (rtp_dtls_transport || rtcp_dtls_transport) {
290 // DTLS/non-DTLS pointers should be to the same object.
291 RTC_DCHECK(rtp_dtls_transport == rtp_packet_transport);
292 RTC_DCHECK(rtcp_dtls_transport == rtcp_packet_transport);
293 // Can't go from non-DTLS to DTLS.
zsteind48dbda2017-04-04 19:45:57 -0700294 RTC_DCHECK(!rtp_transport_.rtp_packet_transport() || rtp_dtls_transport_);
deadbeeff5346592017-01-24 21:51:21 -0800295 } else {
296 // Can't go from DTLS to non-DTLS.
297 RTC_DCHECK(!rtp_dtls_transport_);
298 }
299 // Transport names should be the same.
zhihuangb2cdd932017-01-19 16:54:25 -0800300 if (rtp_dtls_transport && rtcp_dtls_transport) {
301 RTC_DCHECK(rtp_dtls_transport->transport_name() ==
302 rtcp_dtls_transport->transport_name());
zhihuangb2cdd932017-01-19 16:54:25 -0800303 }
deadbeeff5346592017-01-24 21:51:21 -0800304 std::string debug_name;
305 if (rtp_dtls_transport) {
306 transport_name_ = rtp_dtls_transport->transport_name();
307 debug_name = transport_name_;
308 } else {
309 debug_name = rtp_packet_transport->debug_name();
310 }
zsteind48dbda2017-04-04 19:45:57 -0700311 if (rtp_packet_transport == rtp_transport_.rtp_packet_transport()) {
deadbeeff5346592017-01-24 21:51:21 -0800312 // Nothing to do if transport isn't changing.
deadbeefbad5dad2017-01-17 18:32:35 -0800313 return;
deadbeefcbecd352015-09-23 11:50:27 -0700314 }
315
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800316 // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport
317 // changes and wait until the DTLS handshake is complete to set the newly
318 // negotiated parameters.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200319 if (ShouldSetupDtlsSrtp_n()) {
guoweis46383312015-12-17 16:45:59 -0800320 // Set |writable_| to false such that UpdateWritableState_w can set up
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700321 // DTLS-SRTP when |writable_| becomes true again.
guoweis46383312015-12-17 16:45:59 -0800322 writable_ = false;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800323 srtp_filter_.ResetParams();
324 }
325
deadbeefac22f702017-01-12 21:59:29 -0800326 // If this BaseChannel doesn't require RTCP mux and we haven't fully
327 // negotiated RTCP mux, we need an RTCP transport.
deadbeeff5346592017-01-24 21:51:21 -0800328 if (rtcp_packet_transport) {
zhihuangf5b251b2017-01-12 19:37:48 -0800329 LOG(LS_INFO) << "Setting RTCP Transport for " << content_name() << " on "
deadbeeff5346592017-01-24 21:51:21 -0800330 << debug_name << " transport " << rtcp_packet_transport;
331 SetTransport_n(true, rtcp_dtls_transport, rtcp_packet_transport);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000332 }
333
deadbeeff5346592017-01-24 21:51:21 -0800334 LOG(LS_INFO) << "Setting RTP Transport for " << content_name() << " on "
335 << debug_name << " transport " << rtp_packet_transport;
336 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());
deadbeeff5346592017-01-24 21:51:21 -0800348 DtlsTransportInternal*& old_dtls_transport =
zhihuangb2cdd932017-01-19 16:54:25 -0800349 rtcp ? rtcp_dtls_transport_ : rtp_dtls_transport_;
zsteind48dbda2017-04-04 19:45:57 -0700350 rtc::PacketTransportInternal* old_packet_transport =
351 rtcp ? rtp_transport_.rtcp_packet_transport()
352 : rtp_transport_.rtp_packet_transport();
zhihuangb2cdd932017-01-19 16:54:25 -0800353
deadbeeff5346592017-01-24 21:51:21 -0800354 if (!old_packet_transport && !new_packet_transport) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700355 // Nothing to do.
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000356 return;
357 }
zhihuangb2cdd932017-01-19 16:54:25 -0800358
deadbeeff5346592017-01-24 21:51:21 -0800359 RTC_DCHECK(old_packet_transport != new_packet_transport);
360 if (old_dtls_transport) {
361 DisconnectFromDtlsTransport(old_dtls_transport);
362 } else if (old_packet_transport) {
363 DisconnectFromPacketTransport(old_packet_transport);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000364 }
365
zsteind48dbda2017-04-04 19:45:57 -0700366 if (rtcp) {
zstein56162b92017-04-24 16:54:35 -0700367 rtp_transport_.SetRtcpPacketTransport(new_packet_transport);
zsteind48dbda2017-04-04 19:45:57 -0700368 } else {
zstein56162b92017-04-24 16:54:35 -0700369 rtp_transport_.SetRtpPacketTransport(new_packet_transport);
zsteind48dbda2017-04-04 19:45:57 -0700370 }
deadbeeff5346592017-01-24 21:51:21 -0800371 old_dtls_transport = new_dtls_transport;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000372
deadbeeff5346592017-01-24 21:51:21 -0800373 // If there's no new transport, we're done after disconnecting from old one.
374 if (!new_packet_transport) {
375 return;
376 }
377
378 if (rtcp && new_dtls_transport) {
379 RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_filter_.IsActive()))
380 << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
381 << "should never happen.";
382 }
zstein56162b92017-04-24 16:54:35 -0700383
deadbeeff5346592017-01-24 21:51:21 -0800384 if (new_dtls_transport) {
385 ConnectToDtlsTransport(new_dtls_transport);
386 } else {
387 ConnectToPacketTransport(new_packet_transport);
388 }
389 auto& socket_options = rtcp ? rtcp_socket_options_ : socket_options_;
390 for (const auto& pair : socket_options) {
391 new_packet_transport->SetOption(pair.first, pair.second);
guoweis46383312015-12-17 16:45:59 -0800392 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000393}
394
deadbeeff5346592017-01-24 21:51:21 -0800395void BaseChannel::ConnectToDtlsTransport(DtlsTransportInternal* transport) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200396 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000397
zstein56162b92017-04-24 16:54:35 -0700398 // TODO(zstein): de-dup with ConnectToPacketTransport
zhihuangb2cdd932017-01-19 16:54:25 -0800399 transport->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
400 transport->SignalReadPacket.connect(this, &BaseChannel::OnPacketRead);
zhihuangb2cdd932017-01-19 16:54:25 -0800401 transport->SignalDtlsState.connect(this, &BaseChannel::OnDtlsState);
402 transport->SignalSentPacket.connect(this, &BaseChannel::SignalSentPacket_n);
403 transport->ice_transport()->SignalSelectedCandidatePairChanged.connect(
Honghai Zhangcc411c02016-03-29 17:27:21 -0700404 this, &BaseChannel::OnSelectedCandidatePairChanged);
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 OnSelectedCandidatePairChanged(transport->ice_transport(), nullptr, -1,
411 false);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000412
zhihuangb2cdd932017-01-19 16:54:25 -0800413 transport->SignalWritableState.disconnect(this);
414 transport->SignalReadPacket.disconnect(this);
zhihuangb2cdd932017-01-19 16:54:25 -0800415 transport->SignalDtlsState.disconnect(this);
416 transport->SignalSentPacket.disconnect(this);
417 transport->ice_transport()->SignalSelectedCandidatePairChanged.disconnect(
418 this);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000419}
420
deadbeeff5346592017-01-24 21:51:21 -0800421void BaseChannel::ConnectToPacketTransport(
deadbeef5bd5ca32017-02-10 11:31:50 -0800422 rtc::PacketTransportInternal* transport) {
deadbeeff5346592017-01-24 21:51:21 -0800423 RTC_DCHECK_RUN_ON(network_thread_);
424 transport->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
425 transport->SignalReadPacket.connect(this, &BaseChannel::OnPacketRead);
deadbeeff5346592017-01-24 21:51:21 -0800426 transport->SignalSentPacket.connect(this, &BaseChannel::SignalSentPacket_n);
427}
428
429void BaseChannel::DisconnectFromPacketTransport(
deadbeef5bd5ca32017-02-10 11:31:50 -0800430 rtc::PacketTransportInternal* transport) {
deadbeeff5346592017-01-24 21:51:21 -0800431 RTC_DCHECK_RUN_ON(network_thread_);
432 transport->SignalWritableState.disconnect(this);
433 transport->SignalReadPacket.disconnect(this);
deadbeeff5346592017-01-24 21:51:21 -0800434 transport->SignalSentPacket.disconnect(this);
435}
436
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000437bool BaseChannel::Enable(bool enable) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700438 worker_thread_->Invoke<void>(
439 RTC_FROM_HERE,
440 Bind(enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
441 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000442 return true;
443}
444
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000445bool BaseChannel::AddRecvStream(const StreamParams& sp) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700446 return InvokeOnWorker(RTC_FROM_HERE,
447 Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000448}
449
Peter Boström0c4e06b2015-10-07 12:23:21 +0200450bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700451 return InvokeOnWorker(RTC_FROM_HERE,
452 Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000453}
454
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000455bool BaseChannel::AddSendStream(const StreamParams& sp) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000456 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700457 RTC_FROM_HERE, Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000458}
459
Peter Boström0c4e06b2015-10-07 12:23:21 +0200460bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700461 return InvokeOnWorker(RTC_FROM_HERE, Bind(&MediaChannel::RemoveSendStream,
462 media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000463}
464
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000465bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000466 ContentAction action,
467 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100468 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700469 return InvokeOnWorker(RTC_FROM_HERE, Bind(&BaseChannel::SetLocalContent_w,
470 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000471}
472
473bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000474 ContentAction action,
475 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100476 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700477 return InvokeOnWorker(RTC_FROM_HERE, Bind(&BaseChannel::SetRemoteContent_w,
478 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000479}
480
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000481void BaseChannel::StartConnectionMonitor(int cms) {
zhihuangb2cdd932017-01-19 16:54:25 -0800482 // We pass in the BaseChannel instead of the rtp_dtls_transport_
483 // because if the rtp_dtls_transport_ changes, the ConnectionMonitor
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000484 // would be pointing to the wrong TransportChannel.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200485 // We pass in the network thread because on that thread connection monitor
486 // will call BaseChannel::GetConnectionStats which must be called on the
487 // network thread.
488 connection_monitor_.reset(
489 new ConnectionMonitor(this, network_thread(), rtc::Thread::Current()));
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000490 connection_monitor_->SignalUpdate.connect(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000491 this, &BaseChannel::OnConnectionMonitorUpdate);
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000492 connection_monitor_->Start(cms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000493}
494
495void BaseChannel::StopConnectionMonitor() {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000496 if (connection_monitor_) {
497 connection_monitor_->Stop();
498 connection_monitor_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000499 }
500}
501
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000502bool BaseChannel::GetConnectionStats(ConnectionInfos* infos) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200503 RTC_DCHECK(network_thread_->IsCurrent());
deadbeeff5346592017-01-24 21:51:21 -0800504 if (!rtp_dtls_transport_) {
505 return false;
506 }
zhihuangb2cdd932017-01-19 16:54:25 -0800507 return rtp_dtls_transport_->ice_transport()->GetStats(infos);
zhihuangf5b251b2017-01-12 19:37:48 -0800508}
509
510bool BaseChannel::NeedsRtcpTransport() {
deadbeefac22f702017-01-12 21:59:29 -0800511 // If this BaseChannel doesn't require RTCP mux and we haven't fully
512 // negotiated RTCP mux, we need an RTCP transport.
zstein56162b92017-04-24 16:54:35 -0700513 return !rtcp_mux_required_ && !rtcp_mux_filter_.IsFullyActive();
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000514}
515
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700516bool BaseChannel::IsReadyToReceiveMedia_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000517 // Receive data if we are enabled and have local content,
518 return enabled() && IsReceiveContentDirection(local_content_direction_);
519}
520
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700521bool BaseChannel::IsReadyToSendMedia_w() const {
522 // Need to access some state updated on the network thread.
523 return network_thread_->Invoke<bool>(
524 RTC_FROM_HERE, Bind(&BaseChannel::IsReadyToSendMedia_n, this));
525}
526
527bool BaseChannel::IsReadyToSendMedia_n() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528 // Send outgoing data if we are enabled, have local and remote content,
529 // and we have had some form of connectivity.
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800530 return enabled() && IsReceiveContentDirection(remote_content_direction_) &&
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000531 IsSendContentDirection(local_content_direction_) &&
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700532 was_ever_writable() &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200533 (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp_n());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000534}
535
jbaucheec21bd2016-03-20 06:15:43 -0700536bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700537 const rtc::PacketOptions& options) {
538 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000539}
540
jbaucheec21bd2016-03-20 06:15:43 -0700541bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700542 const rtc::PacketOptions& options) {
543 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000544}
545
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000546int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000547 int value) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200548 return network_thread_->Invoke<int>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700549 RTC_FROM_HERE, Bind(&BaseChannel::SetOption_n, this, type, opt, value));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200550}
551
552int BaseChannel::SetOption_n(SocketType type,
553 rtc::Socket::Option opt,
554 int value) {
555 RTC_DCHECK(network_thread_->IsCurrent());
deadbeef5bd5ca32017-02-10 11:31:50 -0800556 rtc::PacketTransportInternal* transport = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000557 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000558 case ST_RTP:
zsteind48dbda2017-04-04 19:45:57 -0700559 transport = rtp_transport_.rtp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700560 socket_options_.push_back(
561 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000562 break;
563 case ST_RTCP:
zsteind48dbda2017-04-04 19:45:57 -0700564 transport = rtp_transport_.rtcp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700565 rtcp_socket_options_.push_back(
566 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000567 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000568 }
deadbeeff5346592017-01-24 21:51:21 -0800569 return transport ? transport->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000570}
571
deadbeef5bd5ca32017-02-10 11:31:50 -0800572void BaseChannel::OnWritableState(rtc::PacketTransportInternal* transport) {
zsteind48dbda2017-04-04 19:45:57 -0700573 RTC_DCHECK(transport == rtp_transport_.rtp_packet_transport() ||
574 transport == rtp_transport_.rtcp_packet_transport());
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200575 RTC_DCHECK(network_thread_->IsCurrent());
576 UpdateWritableState_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000577}
578
deadbeef5bd5ca32017-02-10 11:31:50 -0800579void BaseChannel::OnPacketRead(rtc::PacketTransportInternal* transport,
johand89ab142016-10-25 10:50:32 -0700580 const char* data,
581 size_t len,
582 const rtc::PacketTime& packet_time,
583 int flags) {
584 TRACE_EVENT0("webrtc", "BaseChannel::OnPacketRead");
585 // OnPacketRead gets called from P2PSocket; now pass data to MediaEngine
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200586 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000587
588 // When using RTCP multiplexing we might get RTCP packets on the RTP
589 // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
johand89ab142016-10-25 10:50:32 -0700590 bool rtcp = PacketIsRtcp(transport, data, len);
jbaucheec21bd2016-03-20 06:15:43 -0700591 rtc::CopyOnWriteBuffer packet(data, len);
wu@webrtc.orga9890802013-12-13 00:21:03 +0000592 HandlePacket(rtcp, &packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000593}
594
zhihuangb2cdd932017-01-19 16:54:25 -0800595void BaseChannel::OnDtlsState(DtlsTransportInternal* transport,
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800596 DtlsTransportState state) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200597 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800598 return;
599 }
600
601 // Reset the srtp filter if it's not the CONNECTED state. For the CONNECTED
602 // state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to
zhihuangb2cdd932017-01-19 16:54:25 -0800603 // cover other scenarios like the whole transport is writable (not just this
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800604 // TransportChannel) or when TransportChannel is attached after DTLS is
605 // negotiated.
606 if (state != DTLS_TRANSPORT_CONNECTED) {
607 srtp_filter_.ResetParams();
608 }
609}
610
Honghai Zhangcc411c02016-03-29 17:27:21 -0700611void BaseChannel::OnSelectedCandidatePairChanged(
zhihuangb2cdd932017-01-19 16:54:25 -0800612 IceTransportInternal* ice_transport,
Honghai Zhang52dce732016-03-31 12:37:31 -0700613 CandidatePairInterface* selected_candidate_pair,
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -0700614 int last_sent_packet_id,
615 bool ready_to_send) {
deadbeeff5346592017-01-24 21:51:21 -0800616 RTC_DCHECK((rtp_dtls_transport_ &&
617 ice_transport == rtp_dtls_transport_->ice_transport()) ||
618 (rtcp_dtls_transport_ &&
619 ice_transport == rtcp_dtls_transport_->ice_transport()));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200620 RTC_DCHECK(network_thread_->IsCurrent());
michaelt79e05882016-11-08 02:50:09 -0800621 selected_candidate_pair_ = selected_candidate_pair;
zhihuangb2cdd932017-01-19 16:54:25 -0800622 std::string transport_name = ice_transport->transport_name();
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700623 rtc::NetworkRoute network_route;
Honghai Zhangcc411c02016-03-29 17:27:21 -0700624 if (selected_candidate_pair) {
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700625 network_route = rtc::NetworkRoute(
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -0700626 ready_to_send, selected_candidate_pair->local_candidate().network_id(),
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700627 selected_candidate_pair->remote_candidate().network_id(),
628 last_sent_packet_id);
michaelt79e05882016-11-08 02:50:09 -0800629
630 UpdateTransportOverhead();
Honghai Zhangcc411c02016-03-29 17:27:21 -0700631 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200632 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700633 RTC_FROM_HERE, worker_thread_,
634 Bind(&MediaChannel::OnNetworkRouteChanged, media_channel_, transport_name,
635 network_route));
Honghai Zhangcc411c02016-03-29 17:27:21 -0700636}
637
zstein56162b92017-04-24 16:54:35 -0700638void BaseChannel::OnTransportReadyToSend(bool ready) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200639 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700640 RTC_FROM_HERE, worker_thread_,
zstein56162b92017-04-24 16:54:35 -0700641 Bind(&MediaChannel::OnReadyToSend, media_channel_, ready));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000642}
643
deadbeef5bd5ca32017-02-10 11:31:50 -0800644bool BaseChannel::PacketIsRtcp(const rtc::PacketTransportInternal* transport,
johand89ab142016-10-25 10:50:32 -0700645 const char* data,
646 size_t len) {
zsteind48dbda2017-04-04 19:45:57 -0700647 return (transport == rtp_transport_.rtcp_packet_transport() ||
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000648 rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000649}
650
stefanc1aeaf02015-10-15 07:26:07 -0700651bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700652 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700653 const rtc::PacketOptions& options) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200654 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
655 // If the thread is not our network thread, we will post to our network
656 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000657 // synchronize access to all the pieces of the send path, including
658 // SRTP and the inner workings of the transport channels.
659 // The only downside is that we can't return a proper failure code if
660 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200661 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000662 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200663 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
664 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800665 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700666 data->options = options;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700667 network_thread_->Post(RTC_FROM_HERE, this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000668 return true;
669 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200670 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000671
672 // Now that we are on the correct thread, ensure we have a place to send this
673 // packet before doing anything. (We might get RTCP packets that we don't
674 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
675 // transport.
zstein56162b92017-04-24 16:54:35 -0700676 if (!rtp_transport_.IsWritable(rtcp)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000677 return false;
678 }
679
680 // Protect ourselves against crazy data.
681 if (!ValidPacket(rtcp, packet)) {
682 LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000683 << PacketType(rtcp)
684 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000685 return false;
686 }
687
stefanc1aeaf02015-10-15 07:26:07 -0700688 rtc::PacketOptions updated_options;
689 updated_options = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000690 // Protect if needed.
691 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200692 TRACE_EVENT0("webrtc", "SRTP Encode");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000693 bool res;
Karl Wibergc56ac1e2015-05-04 14:54:55 +0200694 uint8_t* data = packet->data();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000695 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000696 if (!rtcp) {
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000697 // If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
698 // inside libsrtp for a RTP packet. A external HMAC module will be writing
699 // a fake HMAC value. This is ONLY done for a RTP packet.
700 // Socket layer will update rtp sendtime extension header if present in
701 // packet with current time before updating the HMAC.
702#if !defined(ENABLE_EXTERNAL_AUTH)
703 res = srtp_filter_.ProtectRtp(
704 data, len, static_cast<int>(packet->capacity()), &len);
705#else
jbauchd48f4882017-03-01 15:34:36 -0800706 if (!srtp_filter_.IsExternalAuthActive()) {
707 res = srtp_filter_.ProtectRtp(
708 data, len, static_cast<int>(packet->capacity()), &len);
709 } else {
710 updated_options.packet_time_params.rtp_sendtime_extension_id =
711 rtp_abs_sendtime_extn_id_;
712 res = srtp_filter_.ProtectRtp(
713 data, len, static_cast<int>(packet->capacity()), &len,
714 &updated_options.packet_time_params.srtp_packet_index);
715 // If protection succeeds, let's get auth params from srtp.
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000716 if (res) {
jbauchd48f4882017-03-01 15:34:36 -0800717 uint8_t* auth_key = NULL;
718 int key_len;
719 res = srtp_filter_.GetRtpAuthParams(
720 &auth_key, &key_len,
721 &updated_options.packet_time_params.srtp_auth_tag_len);
722 if (res) {
723 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
724 updated_options.packet_time_params.srtp_auth_key.assign(
725 auth_key, auth_key + key_len);
726 }
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000727 }
728 }
729#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000730 if (!res) {
731 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200732 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000733 GetRtpSeqNum(data, len, &seq_num);
734 GetRtpSsrc(data, len, &ssrc);
735 LOG(LS_ERROR) << "Failed to protect " << content_name_
736 << " RTP packet: size=" << len
737 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
738 return false;
739 }
740 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000741 res = srtp_filter_.ProtectRtcp(data, len,
742 static_cast<int>(packet->capacity()),
743 &len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000744 if (!res) {
745 int type = -1;
746 GetRtcpType(data, len, &type);
747 LOG(LS_ERROR) << "Failed to protect " << content_name_
748 << " RTCP packet: size=" << len << ", type=" << type;
749 return false;
750 }
751 }
752
753 // Update the length of the packet now that we've added the auth tag.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000754 packet->SetSize(len);
deadbeef7af91dd2016-12-13 11:29:11 -0800755 } else if (srtp_required_) {
deadbeef8f425f92016-12-01 12:26:27 -0800756 // The audio/video engines may attempt to send RTCP packets as soon as the
757 // streams are created, so don't treat this as an error for RTCP.
758 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6809
759 if (rtcp) {
760 return false;
761 }
762 // However, there shouldn't be any RTP packets sent before SRTP is set up
763 // (and SetSend(true) is called).
764 LOG(LS_ERROR) << "Can't send outgoing RTP packet when SRTP is inactive"
765 << " and crypto is required";
nisseeb4ca4e2017-01-12 02:24:27 -0800766 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000767 return false;
768 }
769
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000770 // Bon voyage.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200771 int flags = (secure() && secure_dtls()) ? PF_SRTP_BYPASS : PF_NORMAL;
zstein56162b92017-04-24 16:54:35 -0700772 return rtp_transport_.SendPacket(rtcp, packet, updated_options, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000773}
774
jbaucheec21bd2016-03-20 06:15:43 -0700775bool BaseChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000776 // Protect ourselves against crazy data.
777 if (!ValidPacket(rtcp, packet)) {
778 LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000779 << PacketType(rtcp)
780 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000781 return false;
782 }
pbos482b12e2015-11-16 10:19:58 -0800783 if (rtcp) {
784 // Permit all (seemingly valid) RTCP packets.
785 return true;
786 }
787 // Check whether we handle this payload.
jbaucheec21bd2016-03-20 06:15:43 -0700788 return bundle_filter_.DemuxPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000789}
790
jbaucheec21bd2016-03-20 06:15:43 -0700791void BaseChannel::HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000792 const rtc::PacketTime& packet_time) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200793 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000794 if (!WantsPacket(rtcp, packet)) {
795 return;
796 }
797
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000798 // We are only interested in the first rtp packet because that
799 // indicates the media has started flowing.
800 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000801 has_received_packet_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700802 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000803 }
804
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000805 // Unprotect the packet, if needed.
806 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200807 TRACE_EVENT0("webrtc", "SRTP Decode");
Karl Wiberg94784372015-04-20 14:03:07 +0200808 char* data = packet->data<char>();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000809 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000810 bool res;
811 if (!rtcp) {
812 res = srtp_filter_.UnprotectRtp(data, len, &len);
813 if (!res) {
814 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200815 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000816 GetRtpSeqNum(data, len, &seq_num);
817 GetRtpSsrc(data, len, &ssrc);
818 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
819 << " RTP packet: size=" << len
820 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
821 return;
822 }
823 } else {
824 res = srtp_filter_.UnprotectRtcp(data, len, &len);
825 if (!res) {
826 int type = -1;
827 GetRtcpType(data, len, &type);
828 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
829 << " RTCP packet: size=" << len << ", type=" << type;
830 return;
831 }
832 }
833
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000834 packet->SetSize(len);
deadbeef7af91dd2016-12-13 11:29:11 -0800835 } else if (srtp_required_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000836 // Our session description indicates that SRTP is required, but we got a
837 // packet before our SRTP filter is active. This means either that
838 // a) we got SRTP packets before we received the SDES keys, in which case
839 // we can't decrypt it anyway, or
840 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
zhihuangb2cdd932017-01-19 16:54:25 -0800841 // transports, so we haven't yet extracted keys, even if DTLS did
842 // complete on the transport that the packets are being sent on. It's
843 // really good practice to wait for both RTP and RTCP to be good to go
844 // before sending media, to prevent weird failure modes, so it's fine
845 // for us to just eat packets here. This is all sidestepped if RTCP mux
846 // is used anyway.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000847 LOG(LS_WARNING) << "Can't process incoming " << PacketType(rtcp)
848 << " packet when SRTP is inactive and crypto is required";
849 return;
850 }
851
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200852 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700853 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200854 Bind(&BaseChannel::OnPacketReceived, this, rtcp, *packet, packet_time));
855}
856
857void BaseChannel::OnPacketReceived(bool rtcp,
858 const rtc::CopyOnWriteBuffer& packet,
859 const rtc::PacketTime& packet_time) {
860 RTC_DCHECK(worker_thread_->IsCurrent());
861 // Need to copy variable because OnRtcpReceived/OnPacketReceived
862 // requires non-const pointer to buffer. This doesn't memcpy the actual data.
863 rtc::CopyOnWriteBuffer data(packet);
864 if (rtcp) {
865 media_channel_->OnRtcpReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000866 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200867 media_channel_->OnPacketReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000868 }
869}
870
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000871bool BaseChannel::PushdownLocalDescription(
872 const SessionDescription* local_desc, ContentAction action,
873 std::string* error_desc) {
874 const ContentInfo* content_info = GetFirstContent(local_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000875 const MediaContentDescription* content_desc =
876 GetContentDescription(content_info);
877 if (content_desc && content_info && !content_info->rejected &&
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000878 !SetLocalContent(content_desc, action, error_desc)) {
879 LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
880 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000881 }
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000882 return true;
883}
884
885bool BaseChannel::PushdownRemoteDescription(
886 const SessionDescription* remote_desc, ContentAction action,
887 std::string* error_desc) {
888 const ContentInfo* content_info = GetFirstContent(remote_desc);
889 const MediaContentDescription* content_desc =
890 GetContentDescription(content_info);
891 if (content_desc && content_info && !content_info->rejected &&
892 !SetRemoteContent(content_desc, action, error_desc)) {
893 LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
894 return false;
895 }
896 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000897}
898
899void BaseChannel::EnableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700900 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000901 if (enabled_)
902 return;
903
904 LOG(LS_INFO) << "Channel enabled";
905 enabled_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700906 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000907}
908
909void BaseChannel::DisableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700910 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000911 if (!enabled_)
912 return;
913
914 LOG(LS_INFO) << "Channel disabled";
915 enabled_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700916 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000917}
918
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200919void BaseChannel::UpdateWritableState_n() {
zsteind48dbda2017-04-04 19:45:57 -0700920 rtc::PacketTransportInternal* rtp_packet_transport =
921 rtp_transport_.rtp_packet_transport();
922 rtc::PacketTransportInternal* rtcp_packet_transport =
923 rtp_transport_.rtcp_packet_transport();
924 if (rtp_packet_transport && rtp_packet_transport->writable() &&
925 (!rtcp_packet_transport || rtcp_packet_transport->writable())) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200926 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700927 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200928 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700929 }
930}
931
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200932void BaseChannel::ChannelWritable_n() {
933 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800934 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000935 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800936 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000937
deadbeefcbecd352015-09-23 11:50:27 -0700938 LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000939 << (was_ever_writable_ ? "" : " for the first time");
940
michaelt79e05882016-11-08 02:50:09 -0800941 if (selected_candidate_pair_)
942 LOG(LS_INFO)
943 << "Using "
944 << selected_candidate_pair_->local_candidate().ToSensitiveString()
945 << "->"
946 << selected_candidate_pair_->remote_candidate().ToSensitiveString();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000947
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000948 was_ever_writable_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200949 MaybeSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000950 writable_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700951 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000952}
953
deadbeef953c2ce2017-01-09 14:53:41 -0800954void BaseChannel::SignalDtlsSrtpSetupFailure_n(bool rtcp) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200955 RTC_DCHECK(network_thread_->IsCurrent());
956 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700957 RTC_FROM_HERE, signaling_thread(),
deadbeef953c2ce2017-01-09 14:53:41 -0800958 Bind(&BaseChannel::SignalDtlsSrtpSetupFailure_s, this, rtcp));
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000959}
960
deadbeef953c2ce2017-01-09 14:53:41 -0800961void BaseChannel::SignalDtlsSrtpSetupFailure_s(bool rtcp) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700962 RTC_DCHECK(signaling_thread() == rtc::Thread::Current());
deadbeef953c2ce2017-01-09 14:53:41 -0800963 SignalDtlsSrtpSetupFailure(this, rtcp);
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000964}
965
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200966bool BaseChannel::ShouldSetupDtlsSrtp_n() const {
zhihuangb2cdd932017-01-19 16:54:25 -0800967 // Since DTLS is applied to all transports, checking RTP should be enough.
968 return rtp_dtls_transport_ && rtp_dtls_transport_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000969}
970
971// This function returns true if either DTLS-SRTP is not in use
972// *or* DTLS-SRTP is successfully set up.
zhihuangb2cdd932017-01-19 16:54:25 -0800973bool BaseChannel::SetupDtlsSrtp_n(bool rtcp) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200974 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000975 bool ret = false;
976
zhihuangb2cdd932017-01-19 16:54:25 -0800977 DtlsTransportInternal* transport =
978 rtcp ? rtcp_dtls_transport_ : rtp_dtls_transport_;
deadbeeff5346592017-01-24 21:51:21 -0800979 RTC_DCHECK(transport);
zhihuangb2cdd932017-01-19 16:54:25 -0800980 RTC_DCHECK(transport->IsDtlsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000981
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800982 int selected_crypto_suite;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000983
zhihuangb2cdd932017-01-19 16:54:25 -0800984 if (!transport->GetSrtpCryptoSuite(&selected_crypto_suite)) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800985 LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 return false;
987 }
988
zhihuangb2cdd932017-01-19 16:54:25 -0800989 LOG(LS_INFO) << "Installing keys from DTLS-SRTP on " << content_name() << " "
990 << PacketType(rtcp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000991
jbauchcb560652016-08-04 05:20:32 -0700992 int key_len;
993 int salt_len;
994 if (!rtc::GetSrtpKeyAndSaltLengths(selected_crypto_suite, &key_len,
995 &salt_len)) {
996 LOG(LS_ERROR) << "Unknown DTLS-SRTP crypto suite" << selected_crypto_suite;
997 return false;
998 }
999
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001000 // OK, we're now doing DTLS (RFC 5764)
jbauchcb560652016-08-04 05:20:32 -07001001 std::vector<unsigned char> dtls_buffer(key_len * 2 + salt_len * 2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001002
1003 // RFC 5705 exporter using the RFC 5764 parameters
zhihuangb2cdd932017-01-19 16:54:25 -08001004 if (!transport->ExportKeyingMaterial(kDtlsSrtpExporterLabel, NULL, 0, false,
1005 &dtls_buffer[0], dtls_buffer.size())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001006 LOG(LS_WARNING) << "DTLS-SRTP key export failed";
nisseeb4ca4e2017-01-12 02:24:27 -08001007 RTC_NOTREACHED(); // This should never happen
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001008 return false;
1009 }
1010
1011 // Sync up the keys with the DTLS-SRTP interface
jbauchcb560652016-08-04 05:20:32 -07001012 std::vector<unsigned char> client_write_key(key_len + salt_len);
1013 std::vector<unsigned char> server_write_key(key_len + salt_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001014 size_t offset = 0;
jbauchcb560652016-08-04 05:20:32 -07001015 memcpy(&client_write_key[0], &dtls_buffer[offset], key_len);
1016 offset += key_len;
1017 memcpy(&server_write_key[0], &dtls_buffer[offset], key_len);
1018 offset += key_len;
1019 memcpy(&client_write_key[key_len], &dtls_buffer[offset], salt_len);
1020 offset += salt_len;
1021 memcpy(&server_write_key[key_len], &dtls_buffer[offset], salt_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001022
1023 std::vector<unsigned char> *send_key, *recv_key;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001024 rtc::SSLRole role;
zhihuangb2cdd932017-01-19 16:54:25 -08001025 if (!transport->GetSslRole(&role)) {
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00001026 LOG(LS_WARNING) << "GetSslRole failed";
1027 return false;
1028 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001029
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001030 if (role == rtc::SSL_SERVER) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001031 send_key = &server_write_key;
1032 recv_key = &client_write_key;
1033 } else {
1034 send_key = &client_write_key;
1035 recv_key = &server_write_key;
1036 }
1037
zhihuangb2cdd932017-01-19 16:54:25 -08001038 if (rtcp) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001039 ret = srtp_filter_.SetRtcpParams(selected_crypto_suite, &(*send_key)[0],
1040 static_cast<int>(send_key->size()),
1041 selected_crypto_suite, &(*recv_key)[0],
1042 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001043 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001044 ret = srtp_filter_.SetRtpParams(selected_crypto_suite, &(*send_key)[0],
1045 static_cast<int>(send_key->size()),
1046 selected_crypto_suite, &(*recv_key)[0],
1047 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001048 }
1049
michaelt79e05882016-11-08 02:50:09 -08001050 if (!ret) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001051 LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
michaelt79e05882016-11-08 02:50:09 -08001052 } else {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001053 dtls_keyed_ = true;
michaelt79e05882016-11-08 02:50:09 -08001054 UpdateTransportOverhead();
1055 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001056 return ret;
1057}
1058
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001059void BaseChannel::MaybeSetupDtlsSrtp_n() {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001060 if (srtp_filter_.IsActive()) {
1061 return;
1062 }
1063
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001064 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001065 return;
1066 }
1067
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001068 if (!SetupDtlsSrtp_n(false)) {
deadbeef953c2ce2017-01-09 14:53:41 -08001069 SignalDtlsSrtpSetupFailure_n(false);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001070 return;
1071 }
1072
zhihuangb2cdd932017-01-19 16:54:25 -08001073 if (rtcp_dtls_transport_) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001074 if (!SetupDtlsSrtp_n(true)) {
deadbeef953c2ce2017-01-09 14:53:41 -08001075 SignalDtlsSrtpSetupFailure_n(true);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001076 return;
1077 }
1078 }
1079}
1080
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001081void BaseChannel::ChannelNotWritable_n() {
1082 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001083 if (!writable_)
1084 return;
1085
deadbeefcbecd352015-09-23 11:50:27 -07001086 LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001087 writable_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001088 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001089}
1090
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001091bool BaseChannel::SetRtpTransportParameters(
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001092 const MediaContentDescription* content,
1093 ContentAction action,
1094 ContentSource src,
1095 std::string* error_desc) {
1096 if (action == CA_UPDATE) {
1097 // These parameters never get changed by a CA_UDPATE.
1098 return true;
1099 }
1100
deadbeef7af91dd2016-12-13 11:29:11 -08001101 // Cache srtp_required_ for belt and suspenders check on SendPacket
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001102 return network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001103 RTC_FROM_HERE, Bind(&BaseChannel::SetRtpTransportParameters_n, this,
1104 content, action, src, error_desc));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001105}
1106
1107bool BaseChannel::SetRtpTransportParameters_n(
1108 const MediaContentDescription* content,
1109 ContentAction action,
1110 ContentSource src,
1111 std::string* error_desc) {
1112 RTC_DCHECK(network_thread_->IsCurrent());
1113
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001114 if (!SetSrtp_n(content->cryptos(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001115 return false;
1116 }
1117
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001118 if (!SetRtcpMux_n(content->rtcp_mux(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001119 return false;
1120 }
1121
1122 return true;
1123}
1124
zhihuangb2cdd932017-01-19 16:54:25 -08001125// |dtls| will be set to true if DTLS is active for transport and crypto is
1126// empty.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001127bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
1128 bool* dtls,
1129 std::string* error_desc) {
deadbeeff5346592017-01-24 21:51:21 -08001130 *dtls = rtp_dtls_transport_ && rtp_dtls_transport_->IsDtlsActive();
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001131 if (*dtls && !cryptos.empty()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001132 SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001133 return false;
1134 }
1135 return true;
1136}
1137
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001138bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001139 ContentAction action,
1140 ContentSource src,
1141 std::string* error_desc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001142 TRACE_EVENT0("webrtc", "BaseChannel::SetSrtp_w");
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001143 if (action == CA_UPDATE) {
1144 // no crypto params.
1145 return true;
1146 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001147 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001148 bool dtls = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001149 ret = CheckSrtpConfig_n(cryptos, &dtls, error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001150 if (!ret) {
1151 return false;
1152 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001153 switch (action) {
1154 case CA_OFFER:
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001155 // If DTLS is already active on the channel, we could be renegotiating
1156 // here. We don't update the srtp filter.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001157 if (!dtls) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001158 ret = srtp_filter_.SetOffer(cryptos, src);
1159 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001160 break;
1161 case CA_PRANSWER:
1162 // If we're doing DTLS-SRTP, we don't want to update the filter
1163 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001164 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001165 ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
1166 }
1167 break;
1168 case CA_ANSWER:
1169 // If we're doing DTLS-SRTP, we don't want to update the filter
1170 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001171 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001172 ret = srtp_filter_.SetAnswer(cryptos, src);
1173 }
1174 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001175 default:
1176 break;
1177 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001178 if (!ret) {
1179 SafeSetError("Failed to setup SRTP filter.", error_desc);
1180 return false;
1181 }
1182 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001183}
1184
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001185bool BaseChannel::SetRtcpMux_n(bool enable,
1186 ContentAction action,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001187 ContentSource src,
1188 std::string* error_desc) {
deadbeef8e814d72017-01-13 11:34:39 -08001189 // Provide a more specific error message for the RTCP mux "require" policy
1190 // case.
zstein56162b92017-04-24 16:54:35 -07001191 if (rtcp_mux_required_ && !enable) {
deadbeef8e814d72017-01-13 11:34:39 -08001192 SafeSetError(
1193 "rtcpMuxPolicy is 'require', but media description does not "
1194 "contain 'a=rtcp-mux'.",
1195 error_desc);
1196 return false;
1197 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001198 bool ret = false;
1199 switch (action) {
1200 case CA_OFFER:
1201 ret = rtcp_mux_filter_.SetOffer(enable, src);
1202 break;
1203 case CA_PRANSWER:
zhihuangb2cdd932017-01-19 16:54:25 -08001204 // This may activate RTCP muxing, but we don't yet destroy the transport
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001205 // because the final answer may deactivate it.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001206 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
1207 break;
1208 case CA_ANSWER:
1209 ret = rtcp_mux_filter_.SetAnswer(enable, src);
1210 if (ret && rtcp_mux_filter_.IsActive()) {
deadbeefe814a0d2017-02-25 18:15:09 -08001211 // We permanently activated RTCP muxing; signal that we no longer need
1212 // the RTCP transport.
zsteind48dbda2017-04-04 19:45:57 -07001213 std::string debug_name =
1214 transport_name_.empty()
1215 ? rtp_transport_.rtp_packet_transport()->debug_name()
1216 : transport_name_;
deadbeefe814a0d2017-02-25 18:15:09 -08001217 ;
deadbeefcbecd352015-09-23 11:50:27 -07001218 LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
deadbeefe814a0d2017-02-25 18:15:09 -08001219 << "; no longer need RTCP transport for " << debug_name;
zsteind48dbda2017-04-04 19:45:57 -07001220 if (rtp_transport_.rtcp_packet_transport()) {
deadbeeff5346592017-01-24 21:51:21 -08001221 SetTransport_n(true, nullptr, nullptr);
1222 SignalRtcpMuxFullyActive(transport_name_);
zhihuangf5b251b2017-01-12 19:37:48 -08001223 }
deadbeef062ce9f2016-08-26 21:42:15 -07001224 UpdateWritableState_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001225 }
1226 break;
1227 case CA_UPDATE:
1228 // No RTCP mux info.
1229 ret = true;
Henrik Kjellander7c027b62015-04-22 13:21:30 +02001230 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001231 default:
1232 break;
1233 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001234 if (!ret) {
1235 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
1236 return false;
1237 }
zstein56162b92017-04-24 16:54:35 -07001238 rtp_transport_.SetRtcpMuxEnabled(rtcp_mux_filter_.IsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001239 // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
zhihuangb2cdd932017-01-19 16:54:25 -08001240 // CA_ANSWER, but we only want to tear down the RTCP transport if we received
1241 // a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001242 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001243 // If the RTP transport is already writable, then so are we.
zsteind48dbda2017-04-04 19:45:57 -07001244 if (rtp_transport_.rtp_packet_transport()->writable()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001245 ChannelWritable_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001246 }
1247 }
1248
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001249 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001250}
1251
1252bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001253 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -08001254 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001255}
1256
Peter Boström0c4e06b2015-10-07 12:23:21 +02001257bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001258 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001259 return media_channel()->RemoveRecvStream(ssrc);
1260}
1261
1262bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001263 ContentAction action,
1264 std::string* error_desc) {
nisse7ce109a2017-01-31 00:57:56 -08001265 if (!(action == CA_OFFER || action == CA_ANSWER ||
1266 action == CA_PRANSWER || action == CA_UPDATE))
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001267 return false;
1268
1269 // If this is an update, streams only contain streams that have changed.
1270 if (action == CA_UPDATE) {
1271 for (StreamParamsVec::const_iterator it = streams.begin();
1272 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001273 const StreamParams* existing_stream =
1274 GetStreamByIds(local_streams_, it->groupid, it->id);
1275 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001276 if (media_channel()->AddSendStream(*it)) {
1277 local_streams_.push_back(*it);
1278 LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
1279 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001280 std::ostringstream desc;
1281 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1282 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001283 return false;
1284 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001285 } else if (existing_stream && !it->has_ssrcs()) {
1286 if (!media_channel()->RemoveSendStream(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001287 std::ostringstream desc;
1288 desc << "Failed to remove send stream with ssrc "
1289 << it->first_ssrc() << ".";
1290 SafeSetError(desc.str(), error_desc);
1291 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001292 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001293 RemoveStreamBySsrc(&local_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001294 } else {
1295 LOG(LS_WARNING) << "Ignore unsupported stream update";
1296 }
1297 }
1298 return true;
1299 }
1300 // Else streams are all the streams we want to send.
1301
1302 // Check for streams that have been removed.
1303 bool ret = true;
1304 for (StreamParamsVec::const_iterator it = local_streams_.begin();
1305 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001306 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001307 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001308 std::ostringstream desc;
1309 desc << "Failed to remove send stream with ssrc "
1310 << it->first_ssrc() << ".";
1311 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001312 ret = false;
1313 }
1314 }
1315 }
1316 // Check for new streams.
1317 for (StreamParamsVec::const_iterator it = streams.begin();
1318 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001319 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001320 if (media_channel()->AddSendStream(*it)) {
stefanc1aeaf02015-10-15 07:26:07 -07001321 LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001322 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001323 std::ostringstream desc;
1324 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1325 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001326 ret = false;
1327 }
1328 }
1329 }
1330 local_streams_ = streams;
1331 return ret;
1332}
1333
1334bool BaseChannel::UpdateRemoteStreams_w(
1335 const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001336 ContentAction action,
1337 std::string* error_desc) {
nisse7ce109a2017-01-31 00:57:56 -08001338 if (!(action == CA_OFFER || action == CA_ANSWER ||
1339 action == CA_PRANSWER || action == CA_UPDATE))
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001340 return false;
1341
1342 // If this is an update, streams only contain streams that have changed.
1343 if (action == CA_UPDATE) {
1344 for (StreamParamsVec::const_iterator it = streams.begin();
1345 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001346 const StreamParams* existing_stream =
1347 GetStreamByIds(remote_streams_, it->groupid, it->id);
1348 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001349 if (AddRecvStream_w(*it)) {
1350 remote_streams_.push_back(*it);
1351 LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
1352 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001353 std::ostringstream desc;
1354 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1355 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001356 return false;
1357 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001358 } else if (existing_stream && !it->has_ssrcs()) {
1359 if (!RemoveRecvStream_w(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001360 std::ostringstream desc;
1361 desc << "Failed to remove remote stream with ssrc "
1362 << it->first_ssrc() << ".";
1363 SafeSetError(desc.str(), error_desc);
1364 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001365 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001366 RemoveStreamBySsrc(&remote_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001367 } else {
1368 LOG(LS_WARNING) << "Ignore unsupported stream update."
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001369 << " Stream exists? " << (existing_stream != nullptr)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001370 << " new stream = " << it->ToString();
1371 }
1372 }
1373 return true;
1374 }
1375 // Else streams are all the streams we want to receive.
1376
1377 // Check for streams that have been removed.
1378 bool ret = true;
1379 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
1380 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001381 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001382 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001383 std::ostringstream desc;
1384 desc << "Failed to remove remote stream with ssrc "
1385 << it->first_ssrc() << ".";
1386 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001387 ret = false;
1388 }
1389 }
1390 }
1391 // Check for new streams.
1392 for (StreamParamsVec::const_iterator it = streams.begin();
1393 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001394 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001395 if (AddRecvStream_w(*it)) {
1396 LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
1397 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001398 std::ostringstream desc;
1399 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1400 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001401 ret = false;
1402 }
1403 }
1404 }
1405 remote_streams_ = streams;
1406 return ret;
1407}
1408
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001409void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w(
isheriff6f8d6862016-05-26 11:24:55 -07001410 const std::vector<webrtc::RtpExtension>& extensions) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001411// Absolute Send Time extension id is used only with external auth,
1412// so do not bother searching for it and making asyncronious call to set
1413// something that is not used.
1414#if defined(ENABLE_EXTERNAL_AUTH)
isheriff6f8d6862016-05-26 11:24:55 -07001415 const webrtc::RtpExtension* send_time_extension =
1416 FindHeaderExtension(extensions, webrtc::RtpExtension::kAbsSendTimeUri);
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001417 int rtp_abs_sendtime_extn_id =
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001418 send_time_extension ? send_time_extension->id : -1;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001419 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001420 RTC_FROM_HERE, network_thread_,
1421 Bind(&BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n, this,
1422 rtp_abs_sendtime_extn_id));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001423#endif
1424}
1425
1426void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n(
1427 int rtp_abs_sendtime_extn_id) {
1428 rtp_abs_sendtime_extn_id_ = rtp_abs_sendtime_extn_id;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001429}
1430
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001431void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001432 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001433 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001434 case MSG_SEND_RTP_PACKET:
1435 case MSG_SEND_RTCP_PACKET: {
1436 RTC_DCHECK(network_thread_->IsCurrent());
1437 SendPacketMessageData* data =
1438 static_cast<SendPacketMessageData*>(pmsg->pdata);
1439 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
1440 SendPacket(rtcp, &data->packet, data->options);
1441 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001442 break;
1443 }
1444 case MSG_FIRSTPACKETRECEIVED: {
1445 SignalFirstPacketReceived(this);
1446 break;
1447 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001448 }
1449}
1450
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001451void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001452 // Flush all remaining RTCP messages. This should only be called in
1453 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001454 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001455 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001456 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
1457 for (const auto& message : rtcp_messages) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001458 network_thread_->Send(RTC_FROM_HERE, this, MSG_SEND_RTCP_PACKET,
1459 message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001460 }
1461}
1462
johand89ab142016-10-25 10:50:32 -07001463void BaseChannel::SignalSentPacket_n(
deadbeef5bd5ca32017-02-10 11:31:50 -08001464 rtc::PacketTransportInternal* /* transport */,
johand89ab142016-10-25 10:50:32 -07001465 const rtc::SentPacket& sent_packet) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001466 RTC_DCHECK(network_thread_->IsCurrent());
1467 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001468 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001469 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
1470}
1471
1472void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
1473 RTC_DCHECK(worker_thread_->IsCurrent());
1474 SignalSentPacket(sent_packet);
1475}
1476
1477VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
1478 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001479 rtc::Thread* signaling_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001480 MediaEngineInterface* media_engine,
1481 VoiceMediaChannel* media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001482 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08001483 bool rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001484 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001485 : BaseChannel(worker_thread,
1486 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001487 signaling_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001488 media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001489 content_name,
deadbeefac22f702017-01-12 21:59:29 -08001490 rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001491 srtp_required),
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001492 media_engine_(media_engine),
deadbeefcbecd352015-09-23 11:50:27 -07001493 received_media_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001494
1495VoiceChannel::~VoiceChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001496 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001497 StopAudioMonitor();
1498 StopMediaMonitor();
1499 // this can't be done in the base class, since it calls a virtual
1500 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001501 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001502}
1503
Peter Boström0c4e06b2015-10-07 12:23:21 +02001504bool VoiceChannel::SetAudioSend(uint32_t ssrc,
solenbergdfc8f4f2015-10-01 02:31:10 -07001505 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001506 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001507 AudioSource* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001508 return InvokeOnWorker(RTC_FROM_HERE,
1509 Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001510 ssrc, enable, options, source));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001511}
1512
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001513// TODO(juberti): Handle early media the right way. We should get an explicit
1514// ringing message telling us to start playing local ringback, which we cancel
1515// if any early media actually arrives. For now, we do the opposite, which is
1516// to wait 1 second for early media, and start playing local ringback if none
1517// arrives.
1518void VoiceChannel::SetEarlyMedia(bool enable) {
1519 if (enable) {
1520 // Start the early media timeout
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001521 worker_thread()->PostDelayed(RTC_FROM_HERE, kEarlyMediaTimeout, this,
1522 MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001523 } else {
1524 // Stop the timeout if currently going.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001525 worker_thread()->Clear(this, MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001526 }
1527}
1528
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001529bool VoiceChannel::CanInsertDtmf() {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001530 return InvokeOnWorker(
1531 RTC_FROM_HERE, Bind(&VoiceMediaChannel::CanInsertDtmf, media_channel()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001532}
1533
Peter Boström0c4e06b2015-10-07 12:23:21 +02001534bool VoiceChannel::InsertDtmf(uint32_t ssrc,
1535 int event_code,
solenberg1d63dd02015-12-02 12:35:09 -08001536 int duration) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001537 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceChannel::InsertDtmf_w, this,
1538 ssrc, event_code, duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539}
1540
solenberg4bac9c52015-10-09 02:32:53 -07001541bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001542 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::SetOutputVolume,
1543 media_channel(), ssrc, volume));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001544}
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001545
Tommif888bb52015-12-12 01:37:01 +01001546void VoiceChannel::SetRawAudioSink(
1547 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -08001548 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
1549 // We need to work around Bind's lack of support for unique_ptr and ownership
deadbeef2d110be2016-01-13 12:00:26 -08001550 // passing. So we invoke to our own little routine that gets a pointer to
1551 // our local variable. This is OK since we're synchronously invoking.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001552 InvokeOnWorker(RTC_FROM_HERE,
1553 Bind(&SetRawAudioSink_w, media_channel(), ssrc, &sink));
Tommif888bb52015-12-12 01:37:01 +01001554}
1555
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001556webrtc::RtpParameters VoiceChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001557 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001558 RTC_FROM_HERE, Bind(&VoiceChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001559}
1560
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001561webrtc::RtpParameters VoiceChannel::GetRtpSendParameters_w(
1562 uint32_t ssrc) const {
1563 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001564}
1565
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001566bool VoiceChannel::SetRtpSendParameters(
1567 uint32_t ssrc,
1568 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001569 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001570 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001571 Bind(&VoiceChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001572}
1573
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001574bool VoiceChannel::SetRtpSendParameters_w(uint32_t ssrc,
1575 webrtc::RtpParameters parameters) {
1576 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1577}
1578
1579webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters(
1580 uint32_t ssrc) const {
1581 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001582 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001583 Bind(&VoiceChannel::GetRtpReceiveParameters_w, this, ssrc));
1584}
1585
1586webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters_w(
1587 uint32_t ssrc) const {
1588 return media_channel()->GetRtpReceiveParameters(ssrc);
1589}
1590
1591bool VoiceChannel::SetRtpReceiveParameters(
1592 uint32_t ssrc,
1593 const webrtc::RtpParameters& parameters) {
1594 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001595 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001596 Bind(&VoiceChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1597}
1598
1599bool VoiceChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1600 webrtc::RtpParameters parameters) {
1601 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001602}
1603
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001604bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001605 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::GetStats,
1606 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607}
1608
hbos8d609f62017-04-10 07:39:05 -07001609std::vector<webrtc::RtpSource> VoiceChannel::GetSources(uint32_t ssrc) const {
1610 return worker_thread()->Invoke<std::vector<webrtc::RtpSource>>(
1611 RTC_FROM_HERE,
1612 Bind(&WebRtcVoiceMediaChannel::GetSources,
1613 static_cast<WebRtcVoiceMediaChannel*>(media_channel()), ssrc));
1614}
1615
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001616void VoiceChannel::StartMediaMonitor(int cms) {
1617 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001618 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001619 media_monitor_->SignalUpdate.connect(
1620 this, &VoiceChannel::OnMediaMonitorUpdate);
1621 media_monitor_->Start(cms);
1622}
1623
1624void VoiceChannel::StopMediaMonitor() {
1625 if (media_monitor_) {
1626 media_monitor_->Stop();
1627 media_monitor_->SignalUpdate.disconnect(this);
1628 media_monitor_.reset();
1629 }
1630}
1631
1632void VoiceChannel::StartAudioMonitor(int cms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001633 audio_monitor_.reset(new AudioMonitor(this, rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001634 audio_monitor_
1635 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1636 audio_monitor_->Start(cms);
1637}
1638
1639void VoiceChannel::StopAudioMonitor() {
1640 if (audio_monitor_) {
1641 audio_monitor_->Stop();
1642 audio_monitor_.reset();
1643 }
1644}
1645
1646bool VoiceChannel::IsAudioMonitorRunning() const {
1647 return (audio_monitor_.get() != NULL);
1648}
1649
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001650int VoiceChannel::GetInputLevel_w() {
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001651 return media_engine_->GetInputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001652}
1653
1654int VoiceChannel::GetOutputLevel_w() {
1655 return media_channel()->GetOutputLevel();
1656}
1657
1658void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1659 media_channel()->GetActiveStreams(actives);
1660}
1661
deadbeef5bd5ca32017-02-10 11:31:50 -08001662void VoiceChannel::OnPacketRead(rtc::PacketTransportInternal* transport,
johand89ab142016-10-25 10:50:32 -07001663 const char* data,
1664 size_t len,
1665 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001666 int flags) {
johand89ab142016-10-25 10:50:32 -07001667 BaseChannel::OnPacketRead(transport, data, len, packet_time, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001668 // Set a flag when we've received an RTP packet. If we're waiting for early
1669 // media, this will disable the timeout.
johand89ab142016-10-25 10:50:32 -07001670 if (!received_media_ && !PacketIsRtcp(transport, data, len)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001671 received_media_ = true;
1672 }
1673}
1674
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001675void BaseChannel::UpdateMediaSendRecvState() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001676 RTC_DCHECK(network_thread_->IsCurrent());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001677 invoker_.AsyncInvoke<void>(
1678 RTC_FROM_HERE, worker_thread_,
1679 Bind(&BaseChannel::UpdateMediaSendRecvState_w, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001680}
1681
michaelt79e05882016-11-08 02:50:09 -08001682int BaseChannel::GetTransportOverheadPerPacket() const {
1683 RTC_DCHECK(network_thread_->IsCurrent());
1684
1685 if (!selected_candidate_pair_)
1686 return 0;
1687
1688 int transport_overhead_per_packet = 0;
1689
1690 constexpr int kIpv4Overhaed = 20;
1691 constexpr int kIpv6Overhaed = 40;
1692 transport_overhead_per_packet +=
1693 selected_candidate_pair_->local_candidate().address().family() == AF_INET
1694 ? kIpv4Overhaed
1695 : kIpv6Overhaed;
1696
1697 constexpr int kUdpOverhaed = 8;
1698 constexpr int kTcpOverhaed = 20;
1699 transport_overhead_per_packet +=
1700 selected_candidate_pair_->local_candidate().protocol() ==
1701 TCP_PROTOCOL_NAME
1702 ? kTcpOverhaed
1703 : kUdpOverhaed;
1704
1705 if (secure()) {
1706 int srtp_overhead = 0;
1707 if (srtp_filter_.GetSrtpOverhead(&srtp_overhead))
1708 transport_overhead_per_packet += srtp_overhead;
1709 }
1710
1711 return transport_overhead_per_packet;
1712}
1713
1714void BaseChannel::UpdateTransportOverhead() {
1715 int transport_overhead_per_packet = GetTransportOverheadPerPacket();
1716 if (transport_overhead_per_packet)
1717 invoker_.AsyncInvoke<void>(
1718 RTC_FROM_HERE, worker_thread_,
1719 Bind(&MediaChannel::OnTransportOverheadChanged, media_channel_,
1720 transport_overhead_per_packet));
1721}
1722
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001723void VoiceChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001724 // Render incoming data if we're the active call, and we have the local
1725 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001726 bool recv = IsReadyToReceiveMedia_w();
solenberg5b14b422015-10-01 04:10:31 -07001727 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001728
1729 // Send outgoing data if we're the active call, we have the remote content,
1730 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001731 bool send = IsReadyToSendMedia_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001732 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001733
1734 LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
1735}
1736
1737const ContentInfo* VoiceChannel::GetFirstContent(
1738 const SessionDescription* sdesc) {
1739 return GetFirstAudioContent(sdesc);
1740}
1741
1742bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001743 ContentAction action,
1744 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001745 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001746 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001747 LOG(LS_INFO) << "Setting local voice description";
1748
1749 const AudioContentDescription* audio =
1750 static_cast<const AudioContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001751 RTC_DCHECK(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001752 if (!audio) {
1753 SafeSetError("Can't find audio content in local description.", error_desc);
1754 return false;
1755 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001756
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001757 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001758 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001759 }
1760
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001761 AudioRecvParameters recv_params = last_recv_params_;
1762 RtpParametersFromMediaDescription(audio, &recv_params);
1763 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001764 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001765 error_desc);
1766 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001767 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001768 for (const AudioCodec& codec : audio->codecs()) {
1769 bundle_filter()->AddPayloadType(codec.id);
1770 }
1771 last_recv_params_ = recv_params;
1772
1773 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1774 // only give it to the media channel once we have a remote
1775 // description too (without a remote description, we won't be able
1776 // to send them anyway).
1777 if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) {
1778 SafeSetError("Failed to set local audio description streams.", error_desc);
1779 return false;
1780 }
1781
1782 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001783 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001784 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001785}
1786
1787bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001788 ContentAction action,
1789 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001790 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001791 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001792 LOG(LS_INFO) << "Setting remote voice description";
1793
1794 const AudioContentDescription* audio =
1795 static_cast<const AudioContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001796 RTC_DCHECK(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001797 if (!audio) {
1798 SafeSetError("Can't find audio content in remote description.", error_desc);
1799 return false;
1800 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001801
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001802 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001803 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001804 }
1805
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001806 AudioSendParameters send_params = last_send_params_;
1807 RtpSendParametersFromMediaDescription(audio, &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001808 if (audio->agc_minus_10db()) {
Karl Wibergbe579832015-11-10 22:34:18 +01001809 send_params.options.adjust_agc_delta = rtc::Optional<int>(kAgcMinus10db);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001810 }
skvladdc1c62c2016-03-16 19:07:43 -07001811
1812 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1813 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001814 SafeSetError("Failed to set remote audio description send parameters.",
1815 error_desc);
1816 return false;
1817 }
1818 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001819
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001820 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1821 // and only give it to the media channel once we have a local
1822 // description too (without a local description, we won't be able to
1823 // recv them anyway).
1824 if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) {
1825 SafeSetError("Failed to set remote audio description streams.", error_desc);
1826 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001827 }
1828
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001829 if (audio->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001830 MaybeCacheRtpAbsSendTimeHeaderExtension_w(audio->rtp_header_extensions());
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001831 }
1832
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001833 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001834 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001835 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001836}
1837
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001838void VoiceChannel::HandleEarlyMediaTimeout() {
1839 // This occurs on the main thread, not the worker thread.
1840 if (!received_media_) {
1841 LOG(LS_INFO) << "No early media received before timeout";
1842 SignalEarlyMediaTimeout(this);
1843 }
1844}
1845
Peter Boström0c4e06b2015-10-07 12:23:21 +02001846bool VoiceChannel::InsertDtmf_w(uint32_t ssrc,
1847 int event,
solenberg1d63dd02015-12-02 12:35:09 -08001848 int duration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001849 if (!enabled()) {
1850 return false;
1851 }
solenberg1d63dd02015-12-02 12:35:09 -08001852 return media_channel()->InsertDtmf(ssrc, event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001853}
1854
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001855void VoiceChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001856 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001857 case MSG_EARLYMEDIATIMEOUT:
1858 HandleEarlyMediaTimeout();
1859 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001860 case MSG_CHANNEL_ERROR: {
1861 VoiceChannelErrorMessageData* data =
1862 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001863 delete data;
1864 break;
1865 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001866 default:
1867 BaseChannel::OnMessage(pmsg);
1868 break;
1869 }
1870}
1871
1872void VoiceChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001873 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001874 SignalConnectionMonitor(this, infos);
1875}
1876
1877void VoiceChannel::OnMediaMonitorUpdate(
1878 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001879 RTC_DCHECK(media_channel == this->media_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001880 SignalMediaMonitor(this, info);
1881}
1882
1883void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1884 const AudioInfo& info) {
1885 SignalAudioMonitor(this, info);
1886}
1887
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001888VideoChannel::VideoChannel(rtc::Thread* worker_thread,
1889 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001890 rtc::Thread* signaling_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001891 VideoMediaChannel* media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001892 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08001893 bool rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001894 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001895 : BaseChannel(worker_thread,
1896 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001897 signaling_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001898 media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001899 content_name,
deadbeefac22f702017-01-12 21:59:29 -08001900 rtcp_mux_required,
deadbeef7af91dd2016-12-13 11:29:11 -08001901 srtp_required) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001902
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001903VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001904 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001905 StopMediaMonitor();
1906 // this can't be done in the base class, since it calls a virtual
1907 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001908
1909 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001910}
1911
nisse08582ff2016-02-04 01:24:52 -08001912bool VideoChannel::SetSink(uint32_t ssrc,
nisseacd935b2016-11-11 03:55:13 -08001913 rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) {
nisse08582ff2016-02-04 01:24:52 -08001914 worker_thread()->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001915 RTC_FROM_HERE,
nisse08582ff2016-02-04 01:24:52 -08001916 Bind(&VideoMediaChannel::SetSink, media_channel(), ssrc, sink));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001917 return true;
1918}
1919
deadbeef5a4a75a2016-06-02 16:23:38 -07001920bool VideoChannel::SetVideoSend(
nisse2ded9b12016-04-08 02:23:55 -07001921 uint32_t ssrc,
deadbeef5a4a75a2016-06-02 16:23:38 -07001922 bool mute,
1923 const VideoOptions* options,
nisseacd935b2016-11-11 03:55:13 -08001924 rtc::VideoSourceInterface<webrtc::VideoFrame>* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001925 return InvokeOnWorker(RTC_FROM_HERE,
1926 Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
deadbeef5a4a75a2016-06-02 16:23:38 -07001927 ssrc, mute, options, source));
solenberg1dd98f32015-09-10 01:57:14 -07001928}
1929
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001930webrtc::RtpParameters VideoChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001931 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001932 RTC_FROM_HERE, Bind(&VideoChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001933}
1934
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001935webrtc::RtpParameters VideoChannel::GetRtpSendParameters_w(
1936 uint32_t ssrc) const {
1937 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001938}
1939
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001940bool VideoChannel::SetRtpSendParameters(
1941 uint32_t ssrc,
1942 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001943 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001944 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001945 Bind(&VideoChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001946}
1947
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001948bool VideoChannel::SetRtpSendParameters_w(uint32_t ssrc,
1949 webrtc::RtpParameters parameters) {
1950 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1951}
1952
1953webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters(
1954 uint32_t ssrc) const {
1955 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001956 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001957 Bind(&VideoChannel::GetRtpReceiveParameters_w, this, ssrc));
1958}
1959
1960webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters_w(
1961 uint32_t ssrc) const {
1962 return media_channel()->GetRtpReceiveParameters(ssrc);
1963}
1964
1965bool VideoChannel::SetRtpReceiveParameters(
1966 uint32_t ssrc,
1967 const webrtc::RtpParameters& parameters) {
1968 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001969 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001970 Bind(&VideoChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1971}
1972
1973bool VideoChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1974 webrtc::RtpParameters parameters) {
1975 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001976}
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001977
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001978void VideoChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001979 // Send outgoing data if we're the active call, we have the remote content,
1980 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001981 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001982 if (!media_channel()->SetSend(send)) {
1983 LOG(LS_ERROR) << "Failed to SetSend on video channel";
1984 // TODO(gangji): Report error back to server.
1985 }
1986
Peter Boström34fbfff2015-09-24 19:20:30 +02001987 LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001988}
1989
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00001990bool VideoChannel::GetStats(VideoMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001991 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VideoMediaChannel::GetStats,
1992 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001993}
1994
1995void VideoChannel::StartMediaMonitor(int cms) {
1996 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001997 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001998 media_monitor_->SignalUpdate.connect(
1999 this, &VideoChannel::OnMediaMonitorUpdate);
2000 media_monitor_->Start(cms);
2001}
2002
2003void VideoChannel::StopMediaMonitor() {
2004 if (media_monitor_) {
2005 media_monitor_->Stop();
2006 media_monitor_.reset();
2007 }
2008}
2009
2010const ContentInfo* VideoChannel::GetFirstContent(
2011 const SessionDescription* sdesc) {
2012 return GetFirstVideoContent(sdesc);
2013}
2014
2015bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002016 ContentAction action,
2017 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002018 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002019 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002020 LOG(LS_INFO) << "Setting local video description";
2021
2022 const VideoContentDescription* video =
2023 static_cast<const VideoContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002024 RTC_DCHECK(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002025 if (!video) {
2026 SafeSetError("Can't find video content in local description.", error_desc);
2027 return false;
2028 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002029
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002030 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002031 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002032 }
2033
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002034 VideoRecvParameters recv_params = last_recv_params_;
2035 RtpParametersFromMediaDescription(video, &recv_params);
2036 if (!media_channel()->SetRecvParameters(recv_params)) {
2037 SafeSetError("Failed to set local video description recv parameters.",
2038 error_desc);
2039 return false;
2040 }
2041 for (const VideoCodec& codec : video->codecs()) {
2042 bundle_filter()->AddPayloadType(codec.id);
2043 }
2044 last_recv_params_ = recv_params;
2045
2046 // TODO(pthatcher): Move local streams into VideoSendParameters, and
2047 // only give it to the media channel once we have a remote
2048 // description too (without a remote description, we won't be able
2049 // to send them anyway).
2050 if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) {
2051 SafeSetError("Failed to set local video description streams.", error_desc);
2052 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002053 }
2054
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002055 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002056 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002057 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002058}
2059
2060bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002061 ContentAction action,
2062 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002063 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002064 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002065 LOG(LS_INFO) << "Setting remote video description";
2066
2067 const VideoContentDescription* video =
2068 static_cast<const VideoContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002069 RTC_DCHECK(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002070 if (!video) {
2071 SafeSetError("Can't find video content in remote description.", error_desc);
2072 return false;
2073 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002074
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002075 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002076 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002077 }
2078
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002079 VideoSendParameters send_params = last_send_params_;
2080 RtpSendParametersFromMediaDescription(video, &send_params);
2081 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08002082 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002083 }
skvladdc1c62c2016-03-16 19:07:43 -07002084
2085 bool parameters_applied = media_channel()->SetSendParameters(send_params);
2086
2087 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002088 SafeSetError("Failed to set remote video description send parameters.",
2089 error_desc);
2090 return false;
2091 }
2092 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002093
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002094 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
2095 // and only give it to the media channel once we have a local
2096 // description too (without a local description, we won't be able to
2097 // recv them anyway).
2098 if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) {
2099 SafeSetError("Failed to set remote video description streams.", error_desc);
2100 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002101 }
2102
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002103 if (video->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002104 MaybeCacheRtpAbsSendTimeHeaderExtension_w(video->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002105 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002106
2107 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002108 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002109 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002110}
2111
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002112void VideoChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002113 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002114 case MSG_CHANNEL_ERROR: {
2115 const VideoChannelErrorMessageData* data =
2116 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002117 delete data;
2118 break;
2119 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002120 default:
2121 BaseChannel::OnMessage(pmsg);
2122 break;
2123 }
2124}
2125
2126void VideoChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002127 ConnectionMonitor* monitor, const std::vector<ConnectionInfo> &infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002128 SignalConnectionMonitor(this, infos);
2129}
2130
2131// TODO(pthatcher): Look into removing duplicate code between
2132// audio, video, and data, perhaps by using templates.
2133void VideoChannel::OnMediaMonitorUpdate(
2134 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002135 RTC_DCHECK(media_channel == this->media_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002136 SignalMediaMonitor(this, info);
2137}
2138
deadbeef953c2ce2017-01-09 14:53:41 -08002139RtpDataChannel::RtpDataChannel(rtc::Thread* worker_thread,
2140 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08002141 rtc::Thread* signaling_thread,
deadbeef953c2ce2017-01-09 14:53:41 -08002142 DataMediaChannel* media_channel,
deadbeef953c2ce2017-01-09 14:53:41 -08002143 const std::string& content_name,
deadbeefac22f702017-01-12 21:59:29 -08002144 bool rtcp_mux_required,
deadbeef953c2ce2017-01-09 14:53:41 -08002145 bool srtp_required)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002146 : BaseChannel(worker_thread,
2147 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08002148 signaling_thread,
deadbeefcbecd352015-09-23 11:50:27 -07002149 media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07002150 content_name,
deadbeefac22f702017-01-12 21:59:29 -08002151 rtcp_mux_required,
deadbeef953c2ce2017-01-09 14:53:41 -08002152 srtp_required) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002153
deadbeef953c2ce2017-01-09 14:53:41 -08002154RtpDataChannel::~RtpDataChannel() {
2155 TRACE_EVENT0("webrtc", "RtpDataChannel::~RtpDataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002156 StopMediaMonitor();
2157 // this can't be done in the base class, since it calls a virtual
2158 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00002159
2160 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002161}
2162
deadbeeff5346592017-01-24 21:51:21 -08002163bool RtpDataChannel::Init_w(
2164 DtlsTransportInternal* rtp_dtls_transport,
2165 DtlsTransportInternal* rtcp_dtls_transport,
deadbeef5bd5ca32017-02-10 11:31:50 -08002166 rtc::PacketTransportInternal* rtp_packet_transport,
2167 rtc::PacketTransportInternal* rtcp_packet_transport) {
deadbeeff5346592017-01-24 21:51:21 -08002168 if (!BaseChannel::Init_w(rtp_dtls_transport, rtcp_dtls_transport,
2169 rtp_packet_transport, rtcp_packet_transport)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002170 return false;
2171 }
deadbeef953c2ce2017-01-09 14:53:41 -08002172 media_channel()->SignalDataReceived.connect(this,
2173 &RtpDataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002174 media_channel()->SignalReadyToSend.connect(
deadbeef953c2ce2017-01-09 14:53:41 -08002175 this, &RtpDataChannel::OnDataChannelReadyToSend);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002176 return true;
2177}
2178
deadbeef953c2ce2017-01-09 14:53:41 -08002179bool RtpDataChannel::SendData(const SendDataParams& params,
2180 const rtc::CopyOnWriteBuffer& payload,
2181 SendDataResult* result) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002182 return InvokeOnWorker(
2183 RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params,
2184 payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002185}
2186
deadbeef953c2ce2017-01-09 14:53:41 -08002187const ContentInfo* RtpDataChannel::GetFirstContent(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002188 const SessionDescription* sdesc) {
2189 return GetFirstDataContent(sdesc);
2190}
2191
deadbeef953c2ce2017-01-09 14:53:41 -08002192bool RtpDataChannel::CheckDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002193 const DataContentDescription* content,
2194 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002195 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
2196 (content->protocol() == kMediaProtocolDtlsSctp));
deadbeef953c2ce2017-01-09 14:53:41 -08002197 // It's been set before, but doesn't match. That's bad.
2198 if (is_sctp) {
2199 SafeSetError("Data channel type mismatch. Expected RTP, got SCTP.",
2200 error_desc);
2201 return false;
2202 }
2203 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002204}
2205
deadbeef953c2ce2017-01-09 14:53:41 -08002206bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content,
2207 ContentAction action,
2208 std::string* error_desc) {
2209 TRACE_EVENT0("webrtc", "RtpDataChannel::SetLocalContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002210 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002211 LOG(LS_INFO) << "Setting local data description";
2212
2213 const DataContentDescription* data =
2214 static_cast<const DataContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002215 RTC_DCHECK(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002216 if (!data) {
2217 SafeSetError("Can't find data content in local description.", error_desc);
2218 return false;
2219 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002220
deadbeef953c2ce2017-01-09 14:53:41 -08002221 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002222 return false;
2223 }
2224
deadbeef953c2ce2017-01-09 14:53:41 -08002225 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
2226 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002227 }
2228
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002229 DataRecvParameters recv_params = last_recv_params_;
2230 RtpParametersFromMediaDescription(data, &recv_params);
2231 if (!media_channel()->SetRecvParameters(recv_params)) {
2232 SafeSetError("Failed to set remote data description recv parameters.",
2233 error_desc);
2234 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002235 }
deadbeef953c2ce2017-01-09 14:53:41 -08002236 for (const DataCodec& codec : data->codecs()) {
2237 bundle_filter()->AddPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002238 }
2239 last_recv_params_ = recv_params;
2240
2241 // TODO(pthatcher): Move local streams into DataSendParameters, and
2242 // only give it to the media channel once we have a remote
2243 // description too (without a remote description, we won't be able
2244 // to send them anyway).
2245 if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) {
2246 SafeSetError("Failed to set local data description streams.", error_desc);
2247 return false;
2248 }
2249
2250 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002251 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002252 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002253}
2254
deadbeef953c2ce2017-01-09 14:53:41 -08002255bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content,
2256 ContentAction action,
2257 std::string* error_desc) {
2258 TRACE_EVENT0("webrtc", "RtpDataChannel::SetRemoteContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002259 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002260
2261 const DataContentDescription* data =
2262 static_cast<const DataContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002263 RTC_DCHECK(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002264 if (!data) {
2265 SafeSetError("Can't find data content in remote description.", error_desc);
2266 return false;
2267 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002268
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002269 // If the remote data doesn't have codecs and isn't an update, it
2270 // must be empty, so ignore it.
2271 if (!data->has_codecs() && action != CA_UPDATE) {
2272 return true;
2273 }
2274
deadbeef953c2ce2017-01-09 14:53:41 -08002275 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002276 return false;
2277 }
2278
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002279 LOG(LS_INFO) << "Setting remote data description";
deadbeef953c2ce2017-01-09 14:53:41 -08002280 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002281 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002282 }
2283
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002284 DataSendParameters send_params = last_send_params_;
2285 RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params);
2286 if (!media_channel()->SetSendParameters(send_params)) {
2287 SafeSetError("Failed to set remote data description send parameters.",
2288 error_desc);
2289 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002290 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002291 last_send_params_ = send_params;
2292
2293 // TODO(pthatcher): Move remote streams into DataRecvParameters,
2294 // and only give it to the media channel once we have a local
2295 // description too (without a local description, we won't be able to
2296 // recv them anyway).
2297 if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) {
2298 SafeSetError("Failed to set remote data description streams.",
2299 error_desc);
2300 return false;
2301 }
2302
2303 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002304 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002305 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002306}
2307
deadbeef953c2ce2017-01-09 14:53:41 -08002308void RtpDataChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002309 // Render incoming data if we're the active call, and we have the local
2310 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002311 bool recv = IsReadyToReceiveMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002312 if (!media_channel()->SetReceive(recv)) {
2313 LOG(LS_ERROR) << "Failed to SetReceive on data channel";
2314 }
2315
2316 // Send outgoing data if we're the active call, we have the remote content,
2317 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002318 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002319 if (!media_channel()->SetSend(send)) {
2320 LOG(LS_ERROR) << "Failed to SetSend on data channel";
2321 }
2322
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002323 // Trigger SignalReadyToSendData asynchronously.
2324 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002325
2326 LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
2327}
2328
deadbeef953c2ce2017-01-09 14:53:41 -08002329void RtpDataChannel::OnMessage(rtc::Message* pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002330 switch (pmsg->message_id) {
2331 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002332 DataChannelReadyToSendMessageData* data =
2333 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002334 ready_to_send_data_ = data->data();
2335 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002336 delete data;
2337 break;
2338 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002339 case MSG_DATARECEIVED: {
2340 DataReceivedMessageData* data =
2341 static_cast<DataReceivedMessageData*>(pmsg->pdata);
deadbeef953c2ce2017-01-09 14:53:41 -08002342 SignalDataReceived(data->params, data->payload);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002343 delete data;
2344 break;
2345 }
2346 case MSG_CHANNEL_ERROR: {
2347 const DataChannelErrorMessageData* data =
2348 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002349 delete data;
2350 break;
2351 }
2352 default:
2353 BaseChannel::OnMessage(pmsg);
2354 break;
2355 }
2356}
2357
deadbeef953c2ce2017-01-09 14:53:41 -08002358void RtpDataChannel::OnConnectionMonitorUpdate(
2359 ConnectionMonitor* monitor,
2360 const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002361 SignalConnectionMonitor(this, infos);
2362}
2363
deadbeef953c2ce2017-01-09 14:53:41 -08002364void RtpDataChannel::StartMediaMonitor(int cms) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002365 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002366 rtc::Thread::Current()));
deadbeef953c2ce2017-01-09 14:53:41 -08002367 media_monitor_->SignalUpdate.connect(this,
2368 &RtpDataChannel::OnMediaMonitorUpdate);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002369 media_monitor_->Start(cms);
2370}
2371
deadbeef953c2ce2017-01-09 14:53:41 -08002372void RtpDataChannel::StopMediaMonitor() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002373 if (media_monitor_) {
2374 media_monitor_->Stop();
2375 media_monitor_->SignalUpdate.disconnect(this);
2376 media_monitor_.reset();
2377 }
2378}
2379
deadbeef953c2ce2017-01-09 14:53:41 -08002380void RtpDataChannel::OnMediaMonitorUpdate(DataMediaChannel* media_channel,
2381 const DataMediaInfo& info) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002382 RTC_DCHECK(media_channel == this->media_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002383 SignalMediaMonitor(this, info);
2384}
2385
deadbeef953c2ce2017-01-09 14:53:41 -08002386void RtpDataChannel::OnDataReceived(const ReceiveDataParams& params,
2387 const char* data,
2388 size_t len) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002389 DataReceivedMessageData* msg = new DataReceivedMessageData(
2390 params, data, len);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002391 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002392}
2393
deadbeef953c2ce2017-01-09 14:53:41 -08002394void RtpDataChannel::OnDataChannelError(uint32_t ssrc,
2395 DataMediaChannel::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002396 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2397 ssrc, err);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002398 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_CHANNEL_ERROR, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002399}
2400
deadbeef953c2ce2017-01-09 14:53:41 -08002401void RtpDataChannel::OnDataChannelReadyToSend(bool writable) {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002402 // This is usded for congestion control to indicate that the stream is ready
2403 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2404 // that the transport channel is ready.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002405 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002406 new DataChannelReadyToSendMessageData(writable));
2407}
2408
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002409} // namespace cricket