blob: c1909a2829c8f5a810d75a6c321fe8386bfdd6e1 [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
kjellander@webrtc.org7ffeab52016-02-26 22:46:09 +010015#include "webrtc/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"
18#include "webrtc/base/common.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"
Peter Boström6f28cf02015-12-07 23:17:15 +010026#include "webrtc/p2p/base/transportchannel.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010027#include "webrtc/pc/channelmanager.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000028
29namespace cricket {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000030using rtc::Bind;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000031
deadbeef2d110be2016-01-13 12:00:26 -080032namespace {
kwiberg31022942016-03-11 14:18:21 -080033// See comment below for why we need to use a pointer to a unique_ptr.
deadbeef2d110be2016-01-13 12:00:26 -080034bool SetRawAudioSink_w(VoiceMediaChannel* channel,
35 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -080036 std::unique_ptr<webrtc::AudioSinkInterface>* sink) {
37 channel->SetRawAudioSink(ssrc, std::move(*sink));
deadbeef2d110be2016-01-13 12:00:26 -080038 return true;
39}
Danil Chapovalov33b01f22016-05-11 19:55:27 +020040
41struct SendPacketMessageData : public rtc::MessageData {
42 rtc::CopyOnWriteBuffer packet;
43 rtc::PacketOptions options;
44};
45
isheriff6f8d6862016-05-26 11:24:55 -070046#if defined(ENABLE_EXTERNAL_AUTH)
47// Returns the named header extension if found among all extensions,
48// nullptr otherwise.
49const webrtc::RtpExtension* FindHeaderExtension(
50 const std::vector<webrtc::RtpExtension>& extensions,
51 const std::string& uri) {
52 for (const auto& extension : extensions) {
53 if (extension.uri == uri)
54 return &extension;
55 }
56 return nullptr;
57}
58#endif
59
deadbeef2d110be2016-01-13 12:00:26 -080060} // namespace
61
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062enum {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000063 MSG_EARLYMEDIATIMEOUT = 1,
Danil Chapovalov33b01f22016-05-11 19:55:27 +020064 MSG_SEND_RTP_PACKET,
65 MSG_SEND_RTCP_PACKET,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066 MSG_CHANNEL_ERROR,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000069 MSG_FIRSTPACKETRECEIVED,
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +000070 MSG_STREAMCLOSEDREMOTELY,
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,
deadbeefcbecd352015-09-23 11:50:27 -0700162 MediaChannel* media_channel,
163 TransportController* transport_controller,
164 const std::string& content_name,
165 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200166 : worker_thread_(worker_thread),
167 network_thread_(network_thread),
168
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000169 content_name_(content_name),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200170
171 transport_controller_(transport_controller),
deadbeefcbecd352015-09-23 11:50:27 -0700172 rtcp_transport_enabled_(rtcp),
173 transport_channel_(nullptr),
174 rtcp_transport_channel_(nullptr),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000175 rtp_ready_to_send_(false),
176 rtcp_ready_to_send_(false),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200177 writable_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000178 was_ever_writable_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000179 has_received_packet_(false),
180 dtls_keyed_(false),
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000181 secure_required_(false),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200182 rtp_abs_sendtime_extn_id_(-1),
183
184 media_channel_(media_channel),
185 enabled_(false),
186 local_content_direction_(MD_INACTIVE),
187 remote_content_direction_(MD_INACTIVE) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000188 ASSERT(worker_thread_ == rtc::Thread::Current());
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200189 if (transport_controller) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200190 RTC_DCHECK_EQ(network_thread, transport_controller->network_thread());
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200191 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000192 LOG(LS_INFO) << "Created channel for " << content_name;
193}
194
195BaseChannel::~BaseChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800196 TRACE_EVENT0("webrtc", "BaseChannel::~BaseChannel");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000197 ASSERT(worker_thread_ == rtc::Thread::Current());
wu@webrtc.org78187522013-10-07 23:32:02 +0000198 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000199 StopConnectionMonitor();
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200200 // Eats any outstanding messages or packets.
201 worker_thread_->Clear(&invoker_);
202 worker_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000203 // We must destroy the media channel before the transport channel, otherwise
204 // the media channel may try to send on the dead transport channel. NULLing
205 // is not an effective strategy since the sends will come on another thread.
206 delete media_channel_;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200207 // Note that we don't just call SetTransportChannel_n(nullptr) because that
deadbeefcbecd352015-09-23 11:50:27 -0700208 // would call a pure virtual method which we can't do from a destructor.
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200209 network_thread_->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700210 RTC_FROM_HERE, Bind(&BaseChannel::DestroyTransportChannels_n, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200211 LOG(LS_INFO) << "Destroyed channel";
212}
213
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200214void BaseChannel::DisconnectTransportChannels_n() {
215 // Send any outstanding RTCP packets.
216 FlushRtcpMessages_n();
217
218 // Stop signals from transport channels, but keep them alive because
219 // media_channel may use them from a different thread.
deadbeefcbecd352015-09-23 11:50:27 -0700220 if (transport_channel_) {
221 DisconnectFromTransportChannel(transport_channel_);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200222 }
223 if (rtcp_transport_channel_) {
224 DisconnectFromTransportChannel(rtcp_transport_channel_);
225 }
226
227 // Clear pending read packets/messages.
228 network_thread_->Clear(&invoker_);
229 network_thread_->Clear(this);
230}
231
232void BaseChannel::DestroyTransportChannels_n() {
233 if (transport_channel_) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200234 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700235 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
236 }
237 if (rtcp_transport_channel_) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200238 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700239 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
240 }
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200241 // Clear pending send packets/messages.
242 network_thread_->Clear(&invoker_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200243 network_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000244}
245
skvlad6c87a672016-05-17 17:49:52 -0700246bool BaseChannel::Init_w(const std::string* bundle_transport_name) {
247 if (!network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700248 RTC_FROM_HERE,
skvlad6c87a672016-05-17 17:49:52 -0700249 Bind(&BaseChannel::InitNetwork_n, this, bundle_transport_name))) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000250 return false;
251 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000252
wu@webrtc.orgde305012013-10-31 15:40:38 +0000253 // Both RTP and RTCP channels are set, we can call SetInterface on
254 // media channel and it can set network options.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200255 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.orgde305012013-10-31 15:40:38 +0000256 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000257 return true;
258}
259
skvlad6c87a672016-05-17 17:49:52 -0700260bool BaseChannel::InitNetwork_n(const std::string* bundle_transport_name) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200261 RTC_DCHECK(network_thread_->IsCurrent());
skvlad6c87a672016-05-17 17:49:52 -0700262 const std::string& transport_name =
263 (bundle_transport_name ? *bundle_transport_name : content_name());
264 if (!SetTransport_n(transport_name)) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200265 return false;
266 }
267
268 if (!SetDtlsSrtpCryptoSuites_n(transport_channel_, false)) {
269 return false;
270 }
271 if (rtcp_transport_enabled() &&
272 !SetDtlsSrtpCryptoSuites_n(rtcp_transport_channel_, true)) {
273 return false;
274 }
275 return true;
276}
277
wu@webrtc.org78187522013-10-07 23:32:02 +0000278void BaseChannel::Deinit() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200279 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.org78187522013-10-07 23:32:02 +0000280 media_channel_->SetInterface(NULL);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200281 // Packets arrive on the network thread, processing packets calls virtual
282 // functions, so need to stop this process in Deinit that is called in
283 // derived classes destructor.
284 network_thread_->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700285 RTC_FROM_HERE, Bind(&BaseChannel::DisconnectTransportChannels_n, this));
wu@webrtc.org78187522013-10-07 23:32:02 +0000286}
287
deadbeefcbecd352015-09-23 11:50:27 -0700288bool BaseChannel::SetTransport(const std::string& transport_name) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200289 return network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700290 RTC_FROM_HERE, Bind(&BaseChannel::SetTransport_n, this, transport_name));
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000291}
292
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200293bool BaseChannel::SetTransport_n(const std::string& transport_name) {
294 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000295
deadbeefcbecd352015-09-23 11:50:27 -0700296 if (transport_name == transport_name_) {
297 // Nothing to do if transport name isn't changing
298 return true;
299 }
300
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800301 // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport
302 // changes and wait until the DTLS handshake is complete to set the newly
303 // negotiated parameters.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200304 if (ShouldSetupDtlsSrtp_n()) {
guoweis46383312015-12-17 16:45:59 -0800305 // Set |writable_| to false such that UpdateWritableState_w can set up
306 // DTLS-SRTP when the writable_ becomes true again.
307 writable_ = false;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800308 srtp_filter_.ResetParams();
309 }
310
guoweis46383312015-12-17 16:45:59 -0800311 // TODO(guoweis): Remove this grossness when we remove non-muxed RTCP.
deadbeefcbecd352015-09-23 11:50:27 -0700312 if (rtcp_transport_enabled()) {
313 LOG(LS_INFO) << "Create RTCP TransportChannel for " << content_name()
314 << " on " << transport_name << " transport ";
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200315 SetRtcpTransportChannel_n(
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200316 transport_controller_->CreateTransportChannel_n(
guoweis46383312015-12-17 16:45:59 -0800317 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP),
318 false /* update_writablity */);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200319 if (!rtcp_transport_channel_) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000320 return false;
321 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000322 }
323
guoweis46383312015-12-17 16:45:59 -0800324 // We're not updating the writablity during the transition state.
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200325 SetTransportChannel_n(transport_controller_->CreateTransportChannel_n(
guoweis46383312015-12-17 16:45:59 -0800326 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200327 if (!transport_channel_) {
guoweis46383312015-12-17 16:45:59 -0800328 return false;
329 }
330
331 // TODO(guoweis): Remove this grossness when we remove non-muxed RTCP.
332 if (rtcp_transport_enabled()) {
333 // We can only update the RTCP ready to send after set_transport_channel has
334 // handled channel writability.
335 SetReadyToSend(
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200336 true, rtcp_transport_channel_ && rtcp_transport_channel_->writable());
guoweis46383312015-12-17 16:45:59 -0800337 }
deadbeefcbecd352015-09-23 11:50:27 -0700338 transport_name_ = transport_name;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000339 return true;
340}
341
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200342void BaseChannel::SetTransportChannel_n(TransportChannel* new_tc) {
343 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000344
345 TransportChannel* old_tc = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700346 if (!old_tc && !new_tc) {
347 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000348 return;
349 }
deadbeefcbecd352015-09-23 11:50:27 -0700350 ASSERT(old_tc != new_tc);
351
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000352 if (old_tc) {
353 DisconnectFromTransportChannel(old_tc);
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200354 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700355 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000356 }
357
358 transport_channel_ = new_tc;
359
360 if (new_tc) {
361 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700362 for (const auto& pair : socket_options_) {
363 new_tc->SetOption(pair.first, pair.second);
364 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000365 }
deadbeefcbecd352015-09-23 11:50:27 -0700366
367 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
368 // setting new channel
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200369 UpdateWritableState_n();
deadbeefcbecd352015-09-23 11:50:27 -0700370 SetReadyToSend(false, new_tc && new_tc->writable());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000371}
372
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200373void BaseChannel::SetRtcpTransportChannel_n(TransportChannel* new_tc,
374 bool update_writablity) {
375 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000376
377 TransportChannel* old_tc = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700378 if (!old_tc && !new_tc) {
379 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000380 return;
381 }
deadbeefcbecd352015-09-23 11:50:27 -0700382 ASSERT(old_tc != new_tc);
383
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000384 if (old_tc) {
385 DisconnectFromTransportChannel(old_tc);
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200386 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700387 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000388 }
389
390 rtcp_transport_channel_ = new_tc;
391
392 if (new_tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200393 RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_filter_.IsActive()))
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800394 << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
395 << "should never happen.";
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000396 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700397 for (const auto& pair : rtcp_socket_options_) {
398 new_tc->SetOption(pair.first, pair.second);
399 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000400 }
deadbeefcbecd352015-09-23 11:50:27 -0700401
guoweis46383312015-12-17 16:45:59 -0800402 if (update_writablity) {
403 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
404 // setting new channel
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200405 UpdateWritableState_n();
guoweis46383312015-12-17 16:45:59 -0800406 SetReadyToSend(true, new_tc && new_tc->writable());
407 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000408}
409
410void BaseChannel::ConnectToTransportChannel(TransportChannel* tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200411 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000412
413 tc->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
414 tc->SignalReadPacket.connect(this, &BaseChannel::OnChannelRead);
415 tc->SignalReadyToSend.connect(this, &BaseChannel::OnReadyToSend);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800416 tc->SignalDtlsState.connect(this, &BaseChannel::OnDtlsState);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700417 tc->SignalSelectedCandidatePairChanged.connect(
418 this, &BaseChannel::OnSelectedCandidatePairChanged);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200419 tc->SignalSentPacket.connect(this, &BaseChannel::SignalSentPacket_n);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000420}
421
422void BaseChannel::DisconnectFromTransportChannel(TransportChannel* tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200423 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000424
425 tc->SignalWritableState.disconnect(this);
426 tc->SignalReadPacket.disconnect(this);
427 tc->SignalReadyToSend.disconnect(this);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800428 tc->SignalDtlsState.disconnect(this);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200429 tc->SignalSelectedCandidatePairChanged.disconnect(this);
430 tc->SignalSentPacket.disconnect(this);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000431}
432
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000433bool BaseChannel::Enable(bool enable) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700434 worker_thread_->Invoke<void>(
435 RTC_FROM_HERE,
436 Bind(enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
437 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000438 return true;
439}
440
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000441bool BaseChannel::AddRecvStream(const StreamParams& sp) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700442 return InvokeOnWorker(RTC_FROM_HERE,
443 Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000444}
445
Peter Boström0c4e06b2015-10-07 12:23:21 +0200446bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700447 return InvokeOnWorker(RTC_FROM_HERE,
448 Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000449}
450
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000451bool BaseChannel::AddSendStream(const StreamParams& sp) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000452 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700453 RTC_FROM_HERE, Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000454}
455
Peter Boström0c4e06b2015-10-07 12:23:21 +0200456bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700457 return InvokeOnWorker(RTC_FROM_HERE, Bind(&MediaChannel::RemoveSendStream,
458 media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000459}
460
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000461bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000462 ContentAction action,
463 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100464 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700465 return InvokeOnWorker(RTC_FROM_HERE, Bind(&BaseChannel::SetLocalContent_w,
466 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000467}
468
469bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000470 ContentAction action,
471 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100472 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700473 return InvokeOnWorker(RTC_FROM_HERE, Bind(&BaseChannel::SetRemoteContent_w,
474 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000475}
476
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000477void BaseChannel::StartConnectionMonitor(int cms) {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000478 // We pass in the BaseChannel instead of the transport_channel_
479 // because if the transport_channel_ changes, the ConnectionMonitor
480 // would be pointing to the wrong TransportChannel.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200481 // We pass in the network thread because on that thread connection monitor
482 // will call BaseChannel::GetConnectionStats which must be called on the
483 // network thread.
484 connection_monitor_.reset(
485 new ConnectionMonitor(this, network_thread(), rtc::Thread::Current()));
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000486 connection_monitor_->SignalUpdate.connect(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000487 this, &BaseChannel::OnConnectionMonitorUpdate);
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000488 connection_monitor_->Start(cms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000489}
490
491void BaseChannel::StopConnectionMonitor() {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000492 if (connection_monitor_) {
493 connection_monitor_->Stop();
494 connection_monitor_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000495 }
496}
497
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000498bool BaseChannel::GetConnectionStats(ConnectionInfos* infos) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200499 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000500 return transport_channel_->GetStats(infos);
501}
502
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200503bool BaseChannel::IsReadyToReceive_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000504 // Receive data if we are enabled and have local content,
505 return enabled() && IsReceiveContentDirection(local_content_direction_);
506}
507
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200508bool BaseChannel::IsReadyToSend_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000509 // Send outgoing data if we are enabled, have local and remote content,
510 // and we have had some form of connectivity.
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800511 return enabled() && IsReceiveContentDirection(remote_content_direction_) &&
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000512 IsSendContentDirection(local_content_direction_) &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200513 network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700514 RTC_FROM_HERE, Bind(&BaseChannel::IsTransportReadyToSend_n, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200515}
516
517bool BaseChannel::IsTransportReadyToSend_n() const {
518 return was_ever_writable() &&
519 (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp_n());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000520}
521
jbaucheec21bd2016-03-20 06:15:43 -0700522bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700523 const rtc::PacketOptions& options) {
524 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000525}
526
jbaucheec21bd2016-03-20 06:15:43 -0700527bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700528 const rtc::PacketOptions& options) {
529 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530}
531
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000532int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000533 int value) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200534 return network_thread_->Invoke<int>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700535 RTC_FROM_HERE, Bind(&BaseChannel::SetOption_n, this, type, opt, value));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200536}
537
538int BaseChannel::SetOption_n(SocketType type,
539 rtc::Socket::Option opt,
540 int value) {
541 RTC_DCHECK(network_thread_->IsCurrent());
542 TransportChannel* channel = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000543 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000544 case ST_RTP:
545 channel = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700546 socket_options_.push_back(
547 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000548 break;
549 case ST_RTCP:
550 channel = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700551 rtcp_socket_options_.push_back(
552 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000553 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000554 }
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000555 return channel ? channel->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000556}
557
558void BaseChannel::OnWritableState(TransportChannel* channel) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200559 RTC_DCHECK(channel == transport_channel_ ||
560 channel == rtcp_transport_channel_);
561 RTC_DCHECK(network_thread_->IsCurrent());
562 UpdateWritableState_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000563}
564
565void BaseChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000566 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000567 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000568 int flags) {
Peter Boström6f28cf02015-12-07 23:17:15 +0100569 TRACE_EVENT0("webrtc", "BaseChannel::OnChannelRead");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000570 // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200571 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000572
573 // When using RTCP multiplexing we might get RTCP packets on the RTP
574 // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
575 bool rtcp = PacketIsRtcp(channel, data, len);
jbaucheec21bd2016-03-20 06:15:43 -0700576 rtc::CopyOnWriteBuffer packet(data, len);
wu@webrtc.orga9890802013-12-13 00:21:03 +0000577 HandlePacket(rtcp, &packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000578}
579
580void BaseChannel::OnReadyToSend(TransportChannel* channel) {
deadbeefcbecd352015-09-23 11:50:27 -0700581 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
582 SetReadyToSend(channel == rtcp_transport_channel_, true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000583}
584
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800585void BaseChannel::OnDtlsState(TransportChannel* channel,
586 DtlsTransportState state) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200587 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800588 return;
589 }
590
591 // Reset the srtp filter if it's not the CONNECTED state. For the CONNECTED
592 // state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to
593 // cover other scenarios like the whole channel is writable (not just this
594 // TransportChannel) or when TransportChannel is attached after DTLS is
595 // negotiated.
596 if (state != DTLS_TRANSPORT_CONNECTED) {
597 srtp_filter_.ResetParams();
598 }
599}
600
Honghai Zhangcc411c02016-03-29 17:27:21 -0700601void BaseChannel::OnSelectedCandidatePairChanged(
602 TransportChannel* channel,
Honghai Zhang52dce732016-03-31 12:37:31 -0700603 CandidatePairInterface* selected_candidate_pair,
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -0700604 int last_sent_packet_id,
605 bool ready_to_send) {
Honghai Zhangcc411c02016-03-29 17:27:21 -0700606 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200607 RTC_DCHECK(network_thread_->IsCurrent());
608 std::string transport_name = channel->transport_name();
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700609 rtc::NetworkRoute network_route;
Honghai Zhangcc411c02016-03-29 17:27:21 -0700610 if (selected_candidate_pair) {
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700611 network_route = rtc::NetworkRoute(
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -0700612 ready_to_send, selected_candidate_pair->local_candidate().network_id(),
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700613 selected_candidate_pair->remote_candidate().network_id(),
614 last_sent_packet_id);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700615 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200616 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700617 RTC_FROM_HERE, worker_thread_,
618 Bind(&MediaChannel::OnNetworkRouteChanged, media_channel_, transport_name,
619 network_route));
Honghai Zhangcc411c02016-03-29 17:27:21 -0700620}
621
deadbeefcbecd352015-09-23 11:50:27 -0700622void BaseChannel::SetReadyToSend(bool rtcp, bool ready) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200623 RTC_DCHECK(network_thread_->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -0700624 if (rtcp) {
625 rtcp_ready_to_send_ = ready;
626 } else {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000627 rtp_ready_to_send_ = ready;
628 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000629
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200630 bool ready_to_send =
631 (rtp_ready_to_send_ &&
632 // In the case of rtcp mux |rtcp_transport_channel_| will be null.
633 (rtcp_ready_to_send_ || !rtcp_transport_channel_));
634
635 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700636 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200637 Bind(&MediaChannel::OnReadyToSend, media_channel_, ready_to_send));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000638}
639
640bool BaseChannel::PacketIsRtcp(const TransportChannel* channel,
641 const char* data, size_t len) {
642 return (channel == rtcp_transport_channel_ ||
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000643 rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000644}
645
stefanc1aeaf02015-10-15 07:26:07 -0700646bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700647 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700648 const rtc::PacketOptions& options) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200649 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
650 // If the thread is not our network thread, we will post to our network
651 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000652 // synchronize access to all the pieces of the send path, including
653 // SRTP and the inner workings of the transport channels.
654 // The only downside is that we can't return a proper failure code if
655 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200656 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000657 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200658 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
659 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800660 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700661 data->options = options;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700662 network_thread_->Post(RTC_FROM_HERE, this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000663 return true;
664 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200665 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666
667 // Now that we are on the correct thread, ensure we have a place to send this
668 // packet before doing anything. (We might get RTCP packets that we don't
669 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
670 // transport.
671 TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
672 transport_channel_ : rtcp_transport_channel_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000673 if (!channel || !channel->writable()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000674 return false;
675 }
676
677 // Protect ourselves against crazy data.
678 if (!ValidPacket(rtcp, packet)) {
679 LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000680 << PacketType(rtcp)
681 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000682 return false;
683 }
684
stefanc1aeaf02015-10-15 07:26:07 -0700685 rtc::PacketOptions updated_options;
686 updated_options = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000687 // Protect if needed.
688 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200689 TRACE_EVENT0("webrtc", "SRTP Encode");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000690 bool res;
Karl Wibergc56ac1e2015-05-04 14:54:55 +0200691 uint8_t* data = packet->data();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000692 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000693 if (!rtcp) {
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000694 // If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
695 // inside libsrtp for a RTP packet. A external HMAC module will be writing
696 // a fake HMAC value. This is ONLY done for a RTP packet.
697 // Socket layer will update rtp sendtime extension header if present in
698 // packet with current time before updating the HMAC.
699#if !defined(ENABLE_EXTERNAL_AUTH)
700 res = srtp_filter_.ProtectRtp(
701 data, len, static_cast<int>(packet->capacity()), &len);
702#else
stefanc1aeaf02015-10-15 07:26:07 -0700703 updated_options.packet_time_params.rtp_sendtime_extension_id =
henrike@webrtc.org05376342014-03-10 15:53:12 +0000704 rtp_abs_sendtime_extn_id_;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000705 res = srtp_filter_.ProtectRtp(
706 data, len, static_cast<int>(packet->capacity()), &len,
stefanc1aeaf02015-10-15 07:26:07 -0700707 &updated_options.packet_time_params.srtp_packet_index);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000708 // If protection succeeds, let's get auth params from srtp.
709 if (res) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200710 uint8_t* auth_key = NULL;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000711 int key_len;
712 res = srtp_filter_.GetRtpAuthParams(
stefanc1aeaf02015-10-15 07:26:07 -0700713 &auth_key, &key_len,
714 &updated_options.packet_time_params.srtp_auth_tag_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000715 if (res) {
stefanc1aeaf02015-10-15 07:26:07 -0700716 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
717 updated_options.packet_time_params.srtp_auth_key.assign(
718 auth_key, auth_key + key_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000719 }
720 }
721#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000722 if (!res) {
723 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200724 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000725 GetRtpSeqNum(data, len, &seq_num);
726 GetRtpSsrc(data, len, &ssrc);
727 LOG(LS_ERROR) << "Failed to protect " << content_name_
728 << " RTP packet: size=" << len
729 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
730 return false;
731 }
732 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000733 res = srtp_filter_.ProtectRtcp(data, len,
734 static_cast<int>(packet->capacity()),
735 &len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000736 if (!res) {
737 int type = -1;
738 GetRtcpType(data, len, &type);
739 LOG(LS_ERROR) << "Failed to protect " << content_name_
740 << " RTCP packet: size=" << len << ", type=" << type;
741 return false;
742 }
743 }
744
745 // Update the length of the packet now that we've added the auth tag.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000746 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000747 } else if (secure_required_) {
748 // This is a double check for something that supposedly can't happen.
749 LOG(LS_ERROR) << "Can't send outgoing " << PacketType(rtcp)
750 << " packet when SRTP is inactive and crypto is required";
751
752 ASSERT(false);
753 return false;
754 }
755
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000756 // Bon voyage.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200757 int flags = (secure() && secure_dtls()) ? PF_SRTP_BYPASS : PF_NORMAL;
758 int ret = channel->SendPacket(packet->data<char>(), packet->size(),
759 updated_options, flags);
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000760 if (ret != static_cast<int>(packet->size())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000761 if (channel->GetError() == EWOULDBLOCK) {
762 LOG(LS_WARNING) << "Got EWOULDBLOCK from socket.";
deadbeefcbecd352015-09-23 11:50:27 -0700763 SetReadyToSend(rtcp, false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000764 }
765 return false;
766 }
767 return true;
768}
769
jbaucheec21bd2016-03-20 06:15:43 -0700770bool BaseChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000771 // Protect ourselves against crazy data.
772 if (!ValidPacket(rtcp, packet)) {
773 LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000774 << PacketType(rtcp)
775 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000776 return false;
777 }
pbos482b12e2015-11-16 10:19:58 -0800778 if (rtcp) {
779 // Permit all (seemingly valid) RTCP packets.
780 return true;
781 }
782 // Check whether we handle this payload.
jbaucheec21bd2016-03-20 06:15:43 -0700783 return bundle_filter_.DemuxPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000784}
785
jbaucheec21bd2016-03-20 06:15:43 -0700786void BaseChannel::HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000787 const rtc::PacketTime& packet_time) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200788 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000789 if (!WantsPacket(rtcp, packet)) {
790 return;
791 }
792
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000793 // We are only interested in the first rtp packet because that
794 // indicates the media has started flowing.
795 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000796 has_received_packet_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700797 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000798 }
799
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000800 // Unprotect the packet, if needed.
801 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200802 TRACE_EVENT0("webrtc", "SRTP Decode");
Karl Wiberg94784372015-04-20 14:03:07 +0200803 char* data = packet->data<char>();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000804 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000805 bool res;
806 if (!rtcp) {
807 res = srtp_filter_.UnprotectRtp(data, len, &len);
808 if (!res) {
809 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200810 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000811 GetRtpSeqNum(data, len, &seq_num);
812 GetRtpSsrc(data, len, &ssrc);
813 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
814 << " RTP packet: size=" << len
815 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
816 return;
817 }
818 } else {
819 res = srtp_filter_.UnprotectRtcp(data, len, &len);
820 if (!res) {
821 int type = -1;
822 GetRtcpType(data, len, &type);
823 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
824 << " RTCP packet: size=" << len << ", type=" << type;
825 return;
826 }
827 }
828
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000829 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000830 } else if (secure_required_) {
831 // Our session description indicates that SRTP is required, but we got a
832 // packet before our SRTP filter is active. This means either that
833 // a) we got SRTP packets before we received the SDES keys, in which case
834 // we can't decrypt it anyway, or
835 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
836 // channels, so we haven't yet extracted keys, even if DTLS did complete
837 // on the channel that the packets are being sent on. It's really good
838 // practice to wait for both RTP and RTCP to be good to go before sending
839 // media, to prevent weird failure modes, so it's fine for us to just eat
840 // packets here. This is all sidestepped if RTCP mux is used anyway.
841 LOG(LS_WARNING) << "Can't process incoming " << PacketType(rtcp)
842 << " packet when SRTP is inactive and crypto is required";
843 return;
844 }
845
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200846 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700847 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200848 Bind(&BaseChannel::OnPacketReceived, this, rtcp, *packet, packet_time));
849}
850
851void BaseChannel::OnPacketReceived(bool rtcp,
852 const rtc::CopyOnWriteBuffer& packet,
853 const rtc::PacketTime& packet_time) {
854 RTC_DCHECK(worker_thread_->IsCurrent());
855 // Need to copy variable because OnRtcpReceived/OnPacketReceived
856 // requires non-const pointer to buffer. This doesn't memcpy the actual data.
857 rtc::CopyOnWriteBuffer data(packet);
858 if (rtcp) {
859 media_channel_->OnRtcpReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000860 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200861 media_channel_->OnPacketReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000862 }
863}
864
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000865bool BaseChannel::PushdownLocalDescription(
866 const SessionDescription* local_desc, ContentAction action,
867 std::string* error_desc) {
868 const ContentInfo* content_info = GetFirstContent(local_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000869 const MediaContentDescription* content_desc =
870 GetContentDescription(content_info);
871 if (content_desc && content_info && !content_info->rejected &&
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000872 !SetLocalContent(content_desc, action, error_desc)) {
873 LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
874 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000875 }
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000876 return true;
877}
878
879bool BaseChannel::PushdownRemoteDescription(
880 const SessionDescription* remote_desc, ContentAction action,
881 std::string* error_desc) {
882 const ContentInfo* content_info = GetFirstContent(remote_desc);
883 const MediaContentDescription* content_desc =
884 GetContentDescription(content_info);
885 if (content_desc && content_info && !content_info->rejected &&
886 !SetRemoteContent(content_desc, action, error_desc)) {
887 LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
888 return false;
889 }
890 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000891}
892
893void BaseChannel::EnableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000894 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000895 if (enabled_)
896 return;
897
898 LOG(LS_INFO) << "Channel enabled";
899 enabled_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200900 ChangeState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000901}
902
903void BaseChannel::DisableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000904 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000905 if (!enabled_)
906 return;
907
908 LOG(LS_INFO) << "Channel disabled";
909 enabled_ = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200910 ChangeState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000911}
912
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200913void BaseChannel::UpdateWritableState_n() {
deadbeefcbecd352015-09-23 11:50:27 -0700914 if (transport_channel_ && transport_channel_->writable() &&
915 (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200916 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700917 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200918 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700919 }
920}
921
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200922void BaseChannel::ChannelWritable_n() {
923 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800924 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000925 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800926 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000927
deadbeefcbecd352015-09-23 11:50:27 -0700928 LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000929 << (was_ever_writable_ ? "" : " for the first time");
930
931 std::vector<ConnectionInfo> infos;
932 transport_channel_->GetStats(&infos);
933 for (std::vector<ConnectionInfo>::const_iterator it = infos.begin();
934 it != infos.end(); ++it) {
935 if (it->best_connection) {
936 LOG(LS_INFO) << "Using " << it->local_candidate.ToSensitiveString()
937 << "->" << it->remote_candidate.ToSensitiveString();
938 break;
939 }
940 }
941
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000942 was_ever_writable_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200943 MaybeSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000944 writable_ = true;
945 ChangeState();
946}
947
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200948void BaseChannel::SignalDtlsSetupFailure_n(bool rtcp) {
949 RTC_DCHECK(network_thread_->IsCurrent());
950 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700951 RTC_FROM_HERE, signaling_thread(),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200952 Bind(&BaseChannel::SignalDtlsSetupFailure_s, this, rtcp));
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000953}
954
955void BaseChannel::SignalDtlsSetupFailure_s(bool rtcp) {
956 ASSERT(signaling_thread() == rtc::Thread::Current());
957 SignalDtlsSetupFailure(this, rtcp);
958}
959
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200960bool BaseChannel::SetDtlsSrtpCryptoSuites_n(TransportChannel* tc, bool rtcp) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800961 std::vector<int> crypto_suites;
962 // We always use the default SRTP crypto suites for RTCP, but we may use
963 // different crypto suites for RTP depending on the media type.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000964 if (!rtcp) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200965 GetSrtpCryptoSuites_n(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000966 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800967 GetDefaultSrtpCryptoSuites(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000968 }
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800969 return tc->SetSrtpCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000970}
971
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200972bool BaseChannel::ShouldSetupDtlsSrtp_n() const {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800973 // Since DTLS is applied to all channels, checking RTP should be enough.
974 return transport_channel_ && transport_channel_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000975}
976
977// This function returns true if either DTLS-SRTP is not in use
978// *or* DTLS-SRTP is successfully set up.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200979bool BaseChannel::SetupDtlsSrtp_n(bool rtcp_channel) {
980 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000981 bool ret = false;
982
deadbeefcbecd352015-09-23 11:50:27 -0700983 TransportChannel* channel =
984 rtcp_channel ? rtcp_transport_channel_ : transport_channel_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000985
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800986 RTC_DCHECK(channel->IsDtlsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000987
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800988 int selected_crypto_suite;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000989
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800990 if (!channel->GetSrtpCryptoSuite(&selected_crypto_suite)) {
991 LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000992 return false;
993 }
994
995 LOG(LS_INFO) << "Installing keys from DTLS-SRTP on "
996 << content_name() << " "
997 << PacketType(rtcp_channel);
998
999 // OK, we're now doing DTLS (RFC 5764)
1000 std::vector<unsigned char> dtls_buffer(SRTP_MASTER_KEY_KEY_LEN * 2 +
1001 SRTP_MASTER_KEY_SALT_LEN * 2);
1002
1003 // RFC 5705 exporter using the RFC 5764 parameters
1004 if (!channel->ExportKeyingMaterial(
1005 kDtlsSrtpExporterLabel,
1006 NULL, 0, false,
1007 &dtls_buffer[0], dtls_buffer.size())) {
1008 LOG(LS_WARNING) << "DTLS-SRTP key export failed";
1009 ASSERT(false); // This should never happen
1010 return false;
1011 }
1012
1013 // Sync up the keys with the DTLS-SRTP interface
1014 std::vector<unsigned char> client_write_key(SRTP_MASTER_KEY_KEY_LEN +
1015 SRTP_MASTER_KEY_SALT_LEN);
1016 std::vector<unsigned char> server_write_key(SRTP_MASTER_KEY_KEY_LEN +
1017 SRTP_MASTER_KEY_SALT_LEN);
1018 size_t offset = 0;
1019 memcpy(&client_write_key[0], &dtls_buffer[offset],
1020 SRTP_MASTER_KEY_KEY_LEN);
1021 offset += SRTP_MASTER_KEY_KEY_LEN;
1022 memcpy(&server_write_key[0], &dtls_buffer[offset],
1023 SRTP_MASTER_KEY_KEY_LEN);
1024 offset += SRTP_MASTER_KEY_KEY_LEN;
1025 memcpy(&client_write_key[SRTP_MASTER_KEY_KEY_LEN],
1026 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
1027 offset += SRTP_MASTER_KEY_SALT_LEN;
1028 memcpy(&server_write_key[SRTP_MASTER_KEY_KEY_LEN],
1029 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
1030
1031 std::vector<unsigned char> *send_key, *recv_key;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001032 rtc::SSLRole role;
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00001033 if (!channel->GetSslRole(&role)) {
1034 LOG(LS_WARNING) << "GetSslRole failed";
1035 return false;
1036 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001037
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001038 if (role == rtc::SSL_SERVER) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001039 send_key = &server_write_key;
1040 recv_key = &client_write_key;
1041 } else {
1042 send_key = &client_write_key;
1043 recv_key = &server_write_key;
1044 }
1045
1046 if (rtcp_channel) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001047 ret = srtp_filter_.SetRtcpParams(selected_crypto_suite, &(*send_key)[0],
1048 static_cast<int>(send_key->size()),
1049 selected_crypto_suite, &(*recv_key)[0],
1050 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001051 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001052 ret = srtp_filter_.SetRtpParams(selected_crypto_suite, &(*send_key)[0],
1053 static_cast<int>(send_key->size()),
1054 selected_crypto_suite, &(*recv_key)[0],
1055 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001056 }
1057
1058 if (!ret)
1059 LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
1060 else
1061 dtls_keyed_ = true;
1062
1063 return ret;
1064}
1065
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001066void BaseChannel::MaybeSetupDtlsSrtp_n() {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001067 if (srtp_filter_.IsActive()) {
1068 return;
1069 }
1070
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001071 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001072 return;
1073 }
1074
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001075 if (!SetupDtlsSrtp_n(false)) {
1076 SignalDtlsSetupFailure_n(false);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001077 return;
1078 }
1079
1080 if (rtcp_transport_channel_) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001081 if (!SetupDtlsSrtp_n(true)) {
1082 SignalDtlsSetupFailure_n(true);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001083 return;
1084 }
1085 }
1086}
1087
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001088void BaseChannel::ChannelNotWritable_n() {
1089 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001090 if (!writable_)
1091 return;
1092
deadbeefcbecd352015-09-23 11:50:27 -07001093 LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001094 writable_ = false;
1095 ChangeState();
1096}
1097
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001098bool BaseChannel::SetRtpTransportParameters(
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001099 const MediaContentDescription* content,
1100 ContentAction action,
1101 ContentSource src,
1102 std::string* error_desc) {
1103 if (action == CA_UPDATE) {
1104 // These parameters never get changed by a CA_UDPATE.
1105 return true;
1106 }
1107
1108 // Cache secure_required_ for belt and suspenders check on SendPacket
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001109 return network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001110 RTC_FROM_HERE, Bind(&BaseChannel::SetRtpTransportParameters_n, this,
1111 content, action, src, error_desc));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001112}
1113
1114bool BaseChannel::SetRtpTransportParameters_n(
1115 const MediaContentDescription* content,
1116 ContentAction action,
1117 ContentSource src,
1118 std::string* error_desc) {
1119 RTC_DCHECK(network_thread_->IsCurrent());
1120
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001121 if (src == CS_LOCAL) {
1122 set_secure_required(content->crypto_required() != CT_NONE);
1123 }
1124
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001125 if (!SetSrtp_n(content->cryptos(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001126 return false;
1127 }
1128
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001129 if (!SetRtcpMux_n(content->rtcp_mux(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001130 return false;
1131 }
1132
1133 return true;
1134}
1135
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001136// |dtls| will be set to true if DTLS is active for transport channel and
1137// crypto is empty.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001138bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
1139 bool* dtls,
1140 std::string* error_desc) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001141 *dtls = transport_channel_->IsDtlsActive();
1142 if (*dtls && !cryptos.empty()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001143 SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001144 return false;
1145 }
1146 return true;
1147}
1148
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001149bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001150 ContentAction action,
1151 ContentSource src,
1152 std::string* error_desc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001153 TRACE_EVENT0("webrtc", "BaseChannel::SetSrtp_w");
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001154 if (action == CA_UPDATE) {
1155 // no crypto params.
1156 return true;
1157 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001158 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001159 bool dtls = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001160 ret = CheckSrtpConfig_n(cryptos, &dtls, error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001161 if (!ret) {
1162 return false;
1163 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001164 switch (action) {
1165 case CA_OFFER:
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001166 // If DTLS is already active on the channel, we could be renegotiating
1167 // here. We don't update the srtp filter.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001168 if (!dtls) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001169 ret = srtp_filter_.SetOffer(cryptos, src);
1170 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001171 break;
1172 case CA_PRANSWER:
1173 // If we're doing DTLS-SRTP, we don't want to update the filter
1174 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001175 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001176 ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
1177 }
1178 break;
1179 case CA_ANSWER:
1180 // If we're doing DTLS-SRTP, we don't want to update the filter
1181 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001182 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001183 ret = srtp_filter_.SetAnswer(cryptos, src);
1184 }
1185 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001186 default:
1187 break;
1188 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001189 if (!ret) {
1190 SafeSetError("Failed to setup SRTP filter.", error_desc);
1191 return false;
1192 }
1193 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001194}
1195
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001196void BaseChannel::ActivateRtcpMux() {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001197 network_thread_->Invoke<void>(RTC_FROM_HERE,
1198 Bind(&BaseChannel::ActivateRtcpMux_n, this));
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001199}
1200
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001201void BaseChannel::ActivateRtcpMux_n() {
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001202 if (!rtcp_mux_filter_.IsActive()) {
1203 rtcp_mux_filter_.SetActive();
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001204 SetRtcpTransportChannel_n(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001205 rtcp_transport_enabled_ = false;
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001206 }
1207}
1208
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001209bool BaseChannel::SetRtcpMux_n(bool enable,
1210 ContentAction action,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001211 ContentSource src,
1212 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001213 bool ret = false;
1214 switch (action) {
1215 case CA_OFFER:
1216 ret = rtcp_mux_filter_.SetOffer(enable, src);
1217 break;
1218 case CA_PRANSWER:
1219 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
1220 break;
1221 case CA_ANSWER:
1222 ret = rtcp_mux_filter_.SetAnswer(enable, src);
1223 if (ret && rtcp_mux_filter_.IsActive()) {
1224 // We activated RTCP mux, close down the RTCP transport.
deadbeefcbecd352015-09-23 11:50:27 -07001225 LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
1226 << " by destroying RTCP transport channel for "
1227 << transport_name();
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001228 SetRtcpTransportChannel_n(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001229 rtcp_transport_enabled_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001230 }
1231 break;
1232 case CA_UPDATE:
1233 // No RTCP mux info.
1234 ret = true;
Henrik Kjellander7c027b62015-04-22 13:21:30 +02001235 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001236 default:
1237 break;
1238 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001239 if (!ret) {
1240 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
1241 return false;
1242 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001243 // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
1244 // CA_ANSWER, but we only want to tear down the RTCP transport channel if we
1245 // received a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001246 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001247 // If the RTP transport is already writable, then so are we.
1248 if (transport_channel_->writable()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001249 ChannelWritable_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001250 }
1251 }
1252
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001253 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001254}
1255
1256bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001257 ASSERT(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -08001258 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001259}
1260
Peter Boström0c4e06b2015-10-07 12:23:21 +02001261bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001262 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001263 return media_channel()->RemoveRecvStream(ssrc);
1264}
1265
1266bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001267 ContentAction action,
1268 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001269 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1270 action == CA_PRANSWER || action == CA_UPDATE))
1271 return false;
1272
1273 // If this is an update, streams only contain streams that have changed.
1274 if (action == CA_UPDATE) {
1275 for (StreamParamsVec::const_iterator it = streams.begin();
1276 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001277 const StreamParams* existing_stream =
1278 GetStreamByIds(local_streams_, it->groupid, it->id);
1279 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001280 if (media_channel()->AddSendStream(*it)) {
1281 local_streams_.push_back(*it);
1282 LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
1283 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001284 std::ostringstream desc;
1285 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1286 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001287 return false;
1288 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001289 } else if (existing_stream && !it->has_ssrcs()) {
1290 if (!media_channel()->RemoveSendStream(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001291 std::ostringstream desc;
1292 desc << "Failed to remove send stream with ssrc "
1293 << it->first_ssrc() << ".";
1294 SafeSetError(desc.str(), error_desc);
1295 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001296 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001297 RemoveStreamBySsrc(&local_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001298 } else {
1299 LOG(LS_WARNING) << "Ignore unsupported stream update";
1300 }
1301 }
1302 return true;
1303 }
1304 // Else streams are all the streams we want to send.
1305
1306 // Check for streams that have been removed.
1307 bool ret = true;
1308 for (StreamParamsVec::const_iterator it = local_streams_.begin();
1309 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001310 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001311 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001312 std::ostringstream desc;
1313 desc << "Failed to remove send stream with ssrc "
1314 << it->first_ssrc() << ".";
1315 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001316 ret = false;
1317 }
1318 }
1319 }
1320 // Check for new streams.
1321 for (StreamParamsVec::const_iterator it = streams.begin();
1322 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001323 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001324 if (media_channel()->AddSendStream(*it)) {
stefanc1aeaf02015-10-15 07:26:07 -07001325 LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001326 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001327 std::ostringstream desc;
1328 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1329 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001330 ret = false;
1331 }
1332 }
1333 }
1334 local_streams_ = streams;
1335 return ret;
1336}
1337
1338bool BaseChannel::UpdateRemoteStreams_w(
1339 const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001340 ContentAction action,
1341 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001342 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1343 action == CA_PRANSWER || action == CA_UPDATE))
1344 return false;
1345
1346 // If this is an update, streams only contain streams that have changed.
1347 if (action == CA_UPDATE) {
1348 for (StreamParamsVec::const_iterator it = streams.begin();
1349 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001350 const StreamParams* existing_stream =
1351 GetStreamByIds(remote_streams_, it->groupid, it->id);
1352 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001353 if (AddRecvStream_w(*it)) {
1354 remote_streams_.push_back(*it);
1355 LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
1356 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001357 std::ostringstream desc;
1358 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1359 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001360 return false;
1361 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001362 } else if (existing_stream && !it->has_ssrcs()) {
1363 if (!RemoveRecvStream_w(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001364 std::ostringstream desc;
1365 desc << "Failed to remove remote stream with ssrc "
1366 << it->first_ssrc() << ".";
1367 SafeSetError(desc.str(), error_desc);
1368 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001369 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001370 RemoveStreamBySsrc(&remote_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001371 } else {
1372 LOG(LS_WARNING) << "Ignore unsupported stream update."
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001373 << " Stream exists? " << (existing_stream != nullptr)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001374 << " new stream = " << it->ToString();
1375 }
1376 }
1377 return true;
1378 }
1379 // Else streams are all the streams we want to receive.
1380
1381 // Check for streams that have been removed.
1382 bool ret = true;
1383 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
1384 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001385 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001386 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001387 std::ostringstream desc;
1388 desc << "Failed to remove remote stream with ssrc "
1389 << it->first_ssrc() << ".";
1390 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001391 ret = false;
1392 }
1393 }
1394 }
1395 // Check for new streams.
1396 for (StreamParamsVec::const_iterator it = streams.begin();
1397 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001398 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001399 if (AddRecvStream_w(*it)) {
1400 LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
1401 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001402 std::ostringstream desc;
1403 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1404 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001405 ret = false;
1406 }
1407 }
1408 }
1409 remote_streams_ = streams;
1410 return ret;
1411}
1412
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001413void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w(
isheriff6f8d6862016-05-26 11:24:55 -07001414 const std::vector<webrtc::RtpExtension>& extensions) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001415// Absolute Send Time extension id is used only with external auth,
1416// so do not bother searching for it and making asyncronious call to set
1417// something that is not used.
1418#if defined(ENABLE_EXTERNAL_AUTH)
isheriff6f8d6862016-05-26 11:24:55 -07001419 const webrtc::RtpExtension* send_time_extension =
1420 FindHeaderExtension(extensions, webrtc::RtpExtension::kAbsSendTimeUri);
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001421 int rtp_abs_sendtime_extn_id =
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001422 send_time_extension ? send_time_extension->id : -1;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001423 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001424 RTC_FROM_HERE, network_thread_,
1425 Bind(&BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n, this,
1426 rtp_abs_sendtime_extn_id));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001427#endif
1428}
1429
1430void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n(
1431 int rtp_abs_sendtime_extn_id) {
1432 rtp_abs_sendtime_extn_id_ = rtp_abs_sendtime_extn_id;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001433}
1434
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001435void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001436 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001437 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001438 case MSG_SEND_RTP_PACKET:
1439 case MSG_SEND_RTCP_PACKET: {
1440 RTC_DCHECK(network_thread_->IsCurrent());
1441 SendPacketMessageData* data =
1442 static_cast<SendPacketMessageData*>(pmsg->pdata);
1443 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
1444 SendPacket(rtcp, &data->packet, data->options);
1445 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001446 break;
1447 }
1448 case MSG_FIRSTPACKETRECEIVED: {
1449 SignalFirstPacketReceived(this);
1450 break;
1451 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001452 }
1453}
1454
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001455void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001456 // Flush all remaining RTCP messages. This should only be called in
1457 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001458 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001459 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001460 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
1461 for (const auto& message : rtcp_messages) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001462 network_thread_->Send(RTC_FROM_HERE, this, MSG_SEND_RTCP_PACKET,
1463 message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001464 }
1465}
1466
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001467void BaseChannel::SignalSentPacket_n(TransportChannel* /* channel */,
1468 const rtc::SentPacket& sent_packet) {
1469 RTC_DCHECK(network_thread_->IsCurrent());
1470 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001471 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001472 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
1473}
1474
1475void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
1476 RTC_DCHECK(worker_thread_->IsCurrent());
1477 SignalSentPacket(sent_packet);
1478}
1479
1480VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
1481 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001482 MediaEngineInterface* media_engine,
1483 VoiceMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001484 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001485 const std::string& content_name,
1486 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001487 : BaseChannel(worker_thread,
1488 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001489 media_channel,
1490 transport_controller,
1491 content_name,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001492 rtcp),
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001493 media_engine_(media_engine),
deadbeefcbecd352015-09-23 11:50:27 -07001494 received_media_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001495
1496VoiceChannel::~VoiceChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001497 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001498 StopAudioMonitor();
1499 StopMediaMonitor();
1500 // this can't be done in the base class, since it calls a virtual
1501 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001502 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001503}
1504
skvlad6c87a672016-05-17 17:49:52 -07001505bool VoiceChannel::Init_w(const std::string* bundle_transport_name) {
1506 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001507 return false;
1508 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001509 return true;
1510}
1511
Peter Boström0c4e06b2015-10-07 12:23:21 +02001512bool VoiceChannel::SetAudioSend(uint32_t ssrc,
solenbergdfc8f4f2015-10-01 02:31:10 -07001513 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001514 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001515 AudioSource* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001516 return InvokeOnWorker(RTC_FROM_HERE,
1517 Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001518 ssrc, enable, options, source));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001519}
1520
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001521// TODO(juberti): Handle early media the right way. We should get an explicit
1522// ringing message telling us to start playing local ringback, which we cancel
1523// if any early media actually arrives. For now, we do the opposite, which is
1524// to wait 1 second for early media, and start playing local ringback if none
1525// arrives.
1526void VoiceChannel::SetEarlyMedia(bool enable) {
1527 if (enable) {
1528 // Start the early media timeout
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001529 worker_thread()->PostDelayed(RTC_FROM_HERE, kEarlyMediaTimeout, this,
1530 MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001531 } else {
1532 // Stop the timeout if currently going.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001533 worker_thread()->Clear(this, MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001534 }
1535}
1536
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001537bool VoiceChannel::CanInsertDtmf() {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001538 return InvokeOnWorker(
1539 RTC_FROM_HERE, Bind(&VoiceMediaChannel::CanInsertDtmf, media_channel()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001540}
1541
Peter Boström0c4e06b2015-10-07 12:23:21 +02001542bool VoiceChannel::InsertDtmf(uint32_t ssrc,
1543 int event_code,
solenberg1d63dd02015-12-02 12:35:09 -08001544 int duration) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001545 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceChannel::InsertDtmf_w, this,
1546 ssrc, event_code, duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001547}
1548
solenberg4bac9c52015-10-09 02:32:53 -07001549bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001550 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::SetOutputVolume,
1551 media_channel(), ssrc, volume));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001552}
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001553
Tommif888bb52015-12-12 01:37:01 +01001554void VoiceChannel::SetRawAudioSink(
1555 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -08001556 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
1557 // We need to work around Bind's lack of support for unique_ptr and ownership
deadbeef2d110be2016-01-13 12:00:26 -08001558 // passing. So we invoke to our own little routine that gets a pointer to
1559 // our local variable. This is OK since we're synchronously invoking.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001560 InvokeOnWorker(RTC_FROM_HERE,
1561 Bind(&SetRawAudioSink_w, media_channel(), ssrc, &sink));
Tommif888bb52015-12-12 01:37:01 +01001562}
1563
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001564webrtc::RtpParameters VoiceChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001565 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001566 RTC_FROM_HERE, Bind(&VoiceChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001567}
1568
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001569webrtc::RtpParameters VoiceChannel::GetRtpSendParameters_w(
1570 uint32_t ssrc) const {
1571 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001572}
1573
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001574bool VoiceChannel::SetRtpSendParameters(
1575 uint32_t ssrc,
1576 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001577 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001578 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001579 Bind(&VoiceChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001580}
1581
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001582bool VoiceChannel::SetRtpSendParameters_w(uint32_t ssrc,
1583 webrtc::RtpParameters parameters) {
1584 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1585}
1586
1587webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters(
1588 uint32_t ssrc) const {
1589 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001590 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001591 Bind(&VoiceChannel::GetRtpReceiveParameters_w, this, ssrc));
1592}
1593
1594webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters_w(
1595 uint32_t ssrc) const {
1596 return media_channel()->GetRtpReceiveParameters(ssrc);
1597}
1598
1599bool VoiceChannel::SetRtpReceiveParameters(
1600 uint32_t ssrc,
1601 const webrtc::RtpParameters& parameters) {
1602 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001603 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001604 Bind(&VoiceChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1605}
1606
1607bool VoiceChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1608 webrtc::RtpParameters parameters) {
1609 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001610}
1611
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001612bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001613 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::GetStats,
1614 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001615}
1616
1617void VoiceChannel::StartMediaMonitor(int cms) {
1618 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001619 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001620 media_monitor_->SignalUpdate.connect(
1621 this, &VoiceChannel::OnMediaMonitorUpdate);
1622 media_monitor_->Start(cms);
1623}
1624
1625void VoiceChannel::StopMediaMonitor() {
1626 if (media_monitor_) {
1627 media_monitor_->Stop();
1628 media_monitor_->SignalUpdate.disconnect(this);
1629 media_monitor_.reset();
1630 }
1631}
1632
1633void VoiceChannel::StartAudioMonitor(int cms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001634 audio_monitor_.reset(new AudioMonitor(this, rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001635 audio_monitor_
1636 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1637 audio_monitor_->Start(cms);
1638}
1639
1640void VoiceChannel::StopAudioMonitor() {
1641 if (audio_monitor_) {
1642 audio_monitor_->Stop();
1643 audio_monitor_.reset();
1644 }
1645}
1646
1647bool VoiceChannel::IsAudioMonitorRunning() const {
1648 return (audio_monitor_.get() != NULL);
1649}
1650
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001651int VoiceChannel::GetInputLevel_w() {
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001652 return media_engine_->GetInputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001653}
1654
1655int VoiceChannel::GetOutputLevel_w() {
1656 return media_channel()->GetOutputLevel();
1657}
1658
1659void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1660 media_channel()->GetActiveStreams(actives);
1661}
1662
1663void VoiceChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001664 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001665 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001666 int flags) {
1667 BaseChannel::OnChannelRead(channel, data, len, packet_time, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001668
1669 // Set a flag when we've received an RTP packet. If we're waiting for early
1670 // media, this will disable the timeout.
1671 if (!received_media_ && !PacketIsRtcp(channel, data, len)) {
1672 received_media_ = true;
1673 }
1674}
1675
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001676void BaseChannel::ChangeState() {
1677 RTC_DCHECK(network_thread_->IsCurrent());
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001678 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001679 Bind(&BaseChannel::ChangeState_w, this));
1680}
1681
1682void VoiceChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001683 // Render incoming data if we're the active call, and we have the local
1684 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001685 bool recv = IsReadyToReceive_w();
solenberg5b14b422015-10-01 04:10:31 -07001686 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001687
1688 // Send outgoing data if we're the active call, we have the remote content,
1689 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001690 bool send = IsReadyToSend_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001691 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001692
1693 LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
1694}
1695
1696const ContentInfo* VoiceChannel::GetFirstContent(
1697 const SessionDescription* sdesc) {
1698 return GetFirstAudioContent(sdesc);
1699}
1700
1701bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001702 ContentAction action,
1703 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001704 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001705 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001706 LOG(LS_INFO) << "Setting local voice description";
1707
1708 const AudioContentDescription* audio =
1709 static_cast<const AudioContentDescription*>(content);
1710 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001711 if (!audio) {
1712 SafeSetError("Can't find audio content in local description.", error_desc);
1713 return false;
1714 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001715
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001716 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001717 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001718 }
1719
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001720 AudioRecvParameters recv_params = last_recv_params_;
1721 RtpParametersFromMediaDescription(audio, &recv_params);
1722 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001723 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001724 error_desc);
1725 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001726 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001727 for (const AudioCodec& codec : audio->codecs()) {
1728 bundle_filter()->AddPayloadType(codec.id);
1729 }
1730 last_recv_params_ = recv_params;
1731
1732 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1733 // only give it to the media channel once we have a remote
1734 // description too (without a remote description, we won't be able
1735 // to send them anyway).
1736 if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) {
1737 SafeSetError("Failed to set local audio description streams.", error_desc);
1738 return false;
1739 }
1740
1741 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001742 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001743 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001744}
1745
1746bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001747 ContentAction action,
1748 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001749 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001750 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001751 LOG(LS_INFO) << "Setting remote voice description";
1752
1753 const AudioContentDescription* audio =
1754 static_cast<const AudioContentDescription*>(content);
1755 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001756 if (!audio) {
1757 SafeSetError("Can't find audio content in remote description.", error_desc);
1758 return false;
1759 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001760
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001761 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001762 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001763 }
1764
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001765 AudioSendParameters send_params = last_send_params_;
1766 RtpSendParametersFromMediaDescription(audio, &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001767 if (audio->agc_minus_10db()) {
Karl Wibergbe579832015-11-10 22:34:18 +01001768 send_params.options.adjust_agc_delta = rtc::Optional<int>(kAgcMinus10db);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001769 }
skvladdc1c62c2016-03-16 19:07:43 -07001770
1771 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1772 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001773 SafeSetError("Failed to set remote audio description send parameters.",
1774 error_desc);
1775 return false;
1776 }
1777 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001778
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001779 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1780 // and only give it to the media channel once we have a local
1781 // description too (without a local description, we won't be able to
1782 // recv them anyway).
1783 if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) {
1784 SafeSetError("Failed to set remote audio description streams.", error_desc);
1785 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001786 }
1787
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001788 if (audio->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001789 MaybeCacheRtpAbsSendTimeHeaderExtension_w(audio->rtp_header_extensions());
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001790 }
1791
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001792 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001793 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001794 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001795}
1796
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001797void VoiceChannel::HandleEarlyMediaTimeout() {
1798 // This occurs on the main thread, not the worker thread.
1799 if (!received_media_) {
1800 LOG(LS_INFO) << "No early media received before timeout";
1801 SignalEarlyMediaTimeout(this);
1802 }
1803}
1804
Peter Boström0c4e06b2015-10-07 12:23:21 +02001805bool VoiceChannel::InsertDtmf_w(uint32_t ssrc,
1806 int event,
solenberg1d63dd02015-12-02 12:35:09 -08001807 int duration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001808 if (!enabled()) {
1809 return false;
1810 }
solenberg1d63dd02015-12-02 12:35:09 -08001811 return media_channel()->InsertDtmf(ssrc, event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001812}
1813
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001814void VoiceChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001815 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001816 case MSG_EARLYMEDIATIMEOUT:
1817 HandleEarlyMediaTimeout();
1818 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001819 case MSG_CHANNEL_ERROR: {
1820 VoiceChannelErrorMessageData* data =
1821 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001822 delete data;
1823 break;
1824 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001825 default:
1826 BaseChannel::OnMessage(pmsg);
1827 break;
1828 }
1829}
1830
1831void VoiceChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001832 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001833 SignalConnectionMonitor(this, infos);
1834}
1835
1836void VoiceChannel::OnMediaMonitorUpdate(
1837 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
1838 ASSERT(media_channel == this->media_channel());
1839 SignalMediaMonitor(this, info);
1840}
1841
1842void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1843 const AudioInfo& info) {
1844 SignalAudioMonitor(this, info);
1845}
1846
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001847void VoiceChannel::GetSrtpCryptoSuites_n(
1848 std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001849 GetSupportedAudioCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001850}
1851
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001852VideoChannel::VideoChannel(rtc::Thread* worker_thread,
1853 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001854 VideoMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001855 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001856 const std::string& content_name,
Fredrik Solenberg7fb711f2015-04-22 15:30:51 +02001857 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001858 : BaseChannel(worker_thread,
1859 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001860 media_channel,
1861 transport_controller,
1862 content_name,
perkjc11b1842016-03-07 17:34:13 -08001863 rtcp) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001864
skvlad6c87a672016-05-17 17:49:52 -07001865bool VideoChannel::Init_w(const std::string* bundle_transport_name) {
1866 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001867 return false;
1868 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001869 return true;
1870}
1871
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001872VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001873 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001874 StopMediaMonitor();
1875 // this can't be done in the base class, since it calls a virtual
1876 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001877
1878 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001879}
1880
nisse08582ff2016-02-04 01:24:52 -08001881bool VideoChannel::SetSink(uint32_t ssrc,
1882 rtc::VideoSinkInterface<VideoFrame>* sink) {
1883 worker_thread()->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001884 RTC_FROM_HERE,
nisse08582ff2016-02-04 01:24:52 -08001885 Bind(&VideoMediaChannel::SetSink, media_channel(), ssrc, sink));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001886 return true;
1887}
1888
deadbeef5a4a75a2016-06-02 16:23:38 -07001889bool VideoChannel::SetVideoSend(
nisse2ded9b12016-04-08 02:23:55 -07001890 uint32_t ssrc,
deadbeef5a4a75a2016-06-02 16:23:38 -07001891 bool mute,
1892 const VideoOptions* options,
nisse2ded9b12016-04-08 02:23:55 -07001893 rtc::VideoSourceInterface<cricket::VideoFrame>* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001894 return InvokeOnWorker(RTC_FROM_HERE,
1895 Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
deadbeef5a4a75a2016-06-02 16:23:38 -07001896 ssrc, mute, options, source));
solenberg1dd98f32015-09-10 01:57:14 -07001897}
1898
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001899webrtc::RtpParameters VideoChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001900 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001901 RTC_FROM_HERE, Bind(&VideoChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001902}
1903
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001904webrtc::RtpParameters VideoChannel::GetRtpSendParameters_w(
1905 uint32_t ssrc) const {
1906 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001907}
1908
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001909bool VideoChannel::SetRtpSendParameters(
1910 uint32_t ssrc,
1911 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001912 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001913 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001914 Bind(&VideoChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001915}
1916
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001917bool VideoChannel::SetRtpSendParameters_w(uint32_t ssrc,
1918 webrtc::RtpParameters parameters) {
1919 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1920}
1921
1922webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters(
1923 uint32_t ssrc) const {
1924 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001925 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001926 Bind(&VideoChannel::GetRtpReceiveParameters_w, this, ssrc));
1927}
1928
1929webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters_w(
1930 uint32_t ssrc) const {
1931 return media_channel()->GetRtpReceiveParameters(ssrc);
1932}
1933
1934bool VideoChannel::SetRtpReceiveParameters(
1935 uint32_t ssrc,
1936 const webrtc::RtpParameters& parameters) {
1937 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001938 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001939 Bind(&VideoChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1940}
1941
1942bool VideoChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1943 webrtc::RtpParameters parameters) {
1944 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001945}
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001946
1947void VideoChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001948 // Send outgoing data if we're the active call, we have the remote content,
1949 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001950 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001951 if (!media_channel()->SetSend(send)) {
1952 LOG(LS_ERROR) << "Failed to SetSend on video channel";
1953 // TODO(gangji): Report error back to server.
1954 }
1955
Peter Boström34fbfff2015-09-24 19:20:30 +02001956 LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001957}
1958
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00001959bool VideoChannel::GetStats(VideoMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001960 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VideoMediaChannel::GetStats,
1961 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001962}
1963
1964void VideoChannel::StartMediaMonitor(int cms) {
1965 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001966 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001967 media_monitor_->SignalUpdate.connect(
1968 this, &VideoChannel::OnMediaMonitorUpdate);
1969 media_monitor_->Start(cms);
1970}
1971
1972void VideoChannel::StopMediaMonitor() {
1973 if (media_monitor_) {
1974 media_monitor_->Stop();
1975 media_monitor_.reset();
1976 }
1977}
1978
1979const ContentInfo* VideoChannel::GetFirstContent(
1980 const SessionDescription* sdesc) {
1981 return GetFirstVideoContent(sdesc);
1982}
1983
1984bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001985 ContentAction action,
1986 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001987 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001988 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001989 LOG(LS_INFO) << "Setting local video description";
1990
1991 const VideoContentDescription* video =
1992 static_cast<const VideoContentDescription*>(content);
1993 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001994 if (!video) {
1995 SafeSetError("Can't find video content in local description.", error_desc);
1996 return false;
1997 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001998
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001999 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002000 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002001 }
2002
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002003 VideoRecvParameters recv_params = last_recv_params_;
2004 RtpParametersFromMediaDescription(video, &recv_params);
2005 if (!media_channel()->SetRecvParameters(recv_params)) {
2006 SafeSetError("Failed to set local video description recv parameters.",
2007 error_desc);
2008 return false;
2009 }
2010 for (const VideoCodec& codec : video->codecs()) {
2011 bundle_filter()->AddPayloadType(codec.id);
2012 }
2013 last_recv_params_ = recv_params;
2014
2015 // TODO(pthatcher): Move local streams into VideoSendParameters, and
2016 // only give it to the media channel once we have a remote
2017 // description too (without a remote description, we won't be able
2018 // to send them anyway).
2019 if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) {
2020 SafeSetError("Failed to set local video description streams.", error_desc);
2021 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002022 }
2023
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002024 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002025 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002026 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002027}
2028
2029bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002030 ContentAction action,
2031 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002032 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002033 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002034 LOG(LS_INFO) << "Setting remote video description";
2035
2036 const VideoContentDescription* video =
2037 static_cast<const VideoContentDescription*>(content);
2038 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002039 if (!video) {
2040 SafeSetError("Can't find video content in remote description.", error_desc);
2041 return false;
2042 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002043
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002044 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002045 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002046 }
2047
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002048 VideoSendParameters send_params = last_send_params_;
2049 RtpSendParametersFromMediaDescription(video, &send_params);
2050 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08002051 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002052 }
skvladdc1c62c2016-03-16 19:07:43 -07002053
2054 bool parameters_applied = media_channel()->SetSendParameters(send_params);
2055
2056 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002057 SafeSetError("Failed to set remote video description send parameters.",
2058 error_desc);
2059 return false;
2060 }
2061 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002062
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002063 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
2064 // and only give it to the media channel once we have a local
2065 // description too (without a local description, we won't be able to
2066 // recv them anyway).
2067 if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) {
2068 SafeSetError("Failed to set remote video description streams.", error_desc);
2069 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002070 }
2071
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002072 if (video->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002073 MaybeCacheRtpAbsSendTimeHeaderExtension_w(video->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002074 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002075
2076 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002077 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002078 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002079}
2080
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002081void VideoChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002082 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002083 case MSG_CHANNEL_ERROR: {
2084 const VideoChannelErrorMessageData* data =
2085 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002086 delete data;
2087 break;
2088 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002089 default:
2090 BaseChannel::OnMessage(pmsg);
2091 break;
2092 }
2093}
2094
2095void VideoChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002096 ConnectionMonitor* monitor, const std::vector<ConnectionInfo> &infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002097 SignalConnectionMonitor(this, infos);
2098}
2099
2100// TODO(pthatcher): Look into removing duplicate code between
2101// audio, video, and data, perhaps by using templates.
2102void VideoChannel::OnMediaMonitorUpdate(
2103 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
2104 ASSERT(media_channel == this->media_channel());
2105 SignalMediaMonitor(this, info);
2106}
2107
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002108void VideoChannel::GetSrtpCryptoSuites_n(
2109 std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002110 GetSupportedVideoCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002111}
2112
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002113DataChannel::DataChannel(rtc::Thread* worker_thread,
2114 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002115 DataMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07002116 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002117 const std::string& content_name,
2118 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002119 : BaseChannel(worker_thread,
2120 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07002121 media_channel,
2122 transport_controller,
2123 content_name,
2124 rtcp),
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002125 data_channel_type_(cricket::DCT_NONE),
deadbeefcbecd352015-09-23 11:50:27 -07002126 ready_to_send_data_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002127
2128DataChannel::~DataChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08002129 TRACE_EVENT0("webrtc", "DataChannel::~DataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002130 StopMediaMonitor();
2131 // this can't be done in the base class, since it calls a virtual
2132 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00002133
2134 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002135}
2136
skvlad6c87a672016-05-17 17:49:52 -07002137bool DataChannel::Init_w(const std::string* bundle_transport_name) {
2138 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002139 return false;
2140 }
2141 media_channel()->SignalDataReceived.connect(
2142 this, &DataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002143 media_channel()->SignalReadyToSend.connect(
2144 this, &DataChannel::OnDataChannelReadyToSend);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002145 media_channel()->SignalStreamClosedRemotely.connect(
2146 this, &DataChannel::OnStreamClosedRemotely);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002147 return true;
2148}
2149
2150bool DataChannel::SendData(const SendDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -07002151 const rtc::CopyOnWriteBuffer& payload,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002152 SendDataResult* result) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002153 return InvokeOnWorker(
2154 RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params,
2155 payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002156}
2157
2158const ContentInfo* DataChannel::GetFirstContent(
2159 const SessionDescription* sdesc) {
2160 return GetFirstDataContent(sdesc);
2161}
2162
jbaucheec21bd2016-03-20 06:15:43 -07002163bool DataChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002164 if (data_channel_type_ == DCT_SCTP) {
2165 // TODO(pthatcher): Do this in a more robust way by checking for
2166 // SCTP or DTLS.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +00002167 return !IsRtpPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002168 } else if (data_channel_type_ == DCT_RTP) {
2169 return BaseChannel::WantsPacket(rtcp, packet);
2170 }
2171 return false;
2172}
2173
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002174bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
2175 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002176 // It hasn't been set before, so set it now.
2177 if (data_channel_type_ == DCT_NONE) {
2178 data_channel_type_ = new_data_channel_type;
2179 return true;
2180 }
2181
2182 // It's been set before, but doesn't match. That's bad.
2183 if (data_channel_type_ != new_data_channel_type) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002184 std::ostringstream desc;
2185 desc << "Data channel type mismatch."
2186 << " Expected " << data_channel_type_
2187 << " Got " << new_data_channel_type;
2188 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002189 return false;
2190 }
2191
2192 // It's hasn't changed. Nothing to do.
2193 return true;
2194}
2195
2196bool DataChannel::SetDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002197 const DataContentDescription* content,
2198 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002199 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
2200 (content->protocol() == kMediaProtocolDtlsSctp));
2201 DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002202 return SetDataChannelType(data_channel_type, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002203}
2204
2205bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002206 ContentAction action,
2207 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002208 TRACE_EVENT0("webrtc", "DataChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002209 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002210 LOG(LS_INFO) << "Setting local data description";
2211
2212 const DataContentDescription* data =
2213 static_cast<const DataContentDescription*>(content);
2214 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002215 if (!data) {
2216 SafeSetError("Can't find data content in local description.", error_desc);
2217 return false;
2218 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002219
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002220 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002221 return false;
2222 }
2223
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002224 if (data_channel_type_ == DCT_RTP) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002225 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002226 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002227 }
2228 }
2229
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002230 // FYI: We send the SCTP port number (not to be confused with the
2231 // underlying UDP port number) as a codec parameter. So even SCTP
2232 // data channels need codecs.
2233 DataRecvParameters recv_params = last_recv_params_;
2234 RtpParametersFromMediaDescription(data, &recv_params);
2235 if (!media_channel()->SetRecvParameters(recv_params)) {
2236 SafeSetError("Failed to set remote data description recv parameters.",
2237 error_desc);
2238 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002239 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002240 if (data_channel_type_ == DCT_RTP) {
2241 for (const DataCodec& codec : data->codecs()) {
2242 bundle_filter()->AddPayloadType(codec.id);
2243 }
2244 }
2245 last_recv_params_ = recv_params;
2246
2247 // TODO(pthatcher): Move local streams into DataSendParameters, and
2248 // only give it to the media channel once we have a remote
2249 // description too (without a remote description, we won't be able
2250 // to send them anyway).
2251 if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) {
2252 SafeSetError("Failed to set local data description streams.", error_desc);
2253 return false;
2254 }
2255
2256 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002257 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002258 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002259}
2260
2261bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002262 ContentAction action,
2263 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002264 TRACE_EVENT0("webrtc", "DataChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002265 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002266
2267 const DataContentDescription* data =
2268 static_cast<const DataContentDescription*>(content);
2269 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002270 if (!data) {
2271 SafeSetError("Can't find data content in remote description.", error_desc);
2272 return false;
2273 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002274
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002275 // If the remote data doesn't have codecs and isn't an update, it
2276 // must be empty, so ignore it.
2277 if (!data->has_codecs() && action != CA_UPDATE) {
2278 return true;
2279 }
2280
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002281 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002282 return false;
2283 }
2284
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002285 LOG(LS_INFO) << "Setting remote data description";
2286 if (data_channel_type_ == DCT_RTP &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002287 !SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002288 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002289 }
2290
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002291
2292 DataSendParameters send_params = last_send_params_;
2293 RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params);
2294 if (!media_channel()->SetSendParameters(send_params)) {
2295 SafeSetError("Failed to set remote data description send parameters.",
2296 error_desc);
2297 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002298 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002299 last_send_params_ = send_params;
2300
2301 // TODO(pthatcher): Move remote streams into DataRecvParameters,
2302 // and only give it to the media channel once we have a local
2303 // description too (without a local description, we won't be able to
2304 // recv them anyway).
2305 if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) {
2306 SafeSetError("Failed to set remote data description streams.",
2307 error_desc);
2308 return false;
2309 }
2310
2311 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002312 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002313 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002314}
2315
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002316void DataChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002317 // Render incoming data if we're the active call, and we have the local
2318 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002319 bool recv = IsReadyToReceive_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002320 if (!media_channel()->SetReceive(recv)) {
2321 LOG(LS_ERROR) << "Failed to SetReceive on data channel";
2322 }
2323
2324 // Send outgoing data if we're the active call, we have the remote content,
2325 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002326 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002327 if (!media_channel()->SetSend(send)) {
2328 LOG(LS_ERROR) << "Failed to SetSend on data channel";
2329 }
2330
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002331 // Trigger SignalReadyToSendData asynchronously.
2332 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002333
2334 LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
2335}
2336
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002337void DataChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002338 switch (pmsg->message_id) {
2339 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002340 DataChannelReadyToSendMessageData* data =
2341 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002342 ready_to_send_data_ = data->data();
2343 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002344 delete data;
2345 break;
2346 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002347 case MSG_DATARECEIVED: {
2348 DataReceivedMessageData* data =
2349 static_cast<DataReceivedMessageData*>(pmsg->pdata);
2350 SignalDataReceived(this, data->params, data->payload);
2351 delete data;
2352 break;
2353 }
2354 case MSG_CHANNEL_ERROR: {
2355 const DataChannelErrorMessageData* data =
2356 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002357 delete data;
2358 break;
2359 }
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002360 case MSG_STREAMCLOSEDREMOTELY: {
Peter Boström0c4e06b2015-10-07 12:23:21 +02002361 rtc::TypedMessageData<uint32_t>* data =
2362 static_cast<rtc::TypedMessageData<uint32_t>*>(pmsg->pdata);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002363 SignalStreamClosedRemotely(data->data());
2364 delete data;
2365 break;
2366 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002367 default:
2368 BaseChannel::OnMessage(pmsg);
2369 break;
2370 }
2371}
2372
2373void DataChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002374 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002375 SignalConnectionMonitor(this, infos);
2376}
2377
2378void DataChannel::StartMediaMonitor(int cms) {
2379 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002380 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002381 media_monitor_->SignalUpdate.connect(
2382 this, &DataChannel::OnMediaMonitorUpdate);
2383 media_monitor_->Start(cms);
2384}
2385
2386void DataChannel::StopMediaMonitor() {
2387 if (media_monitor_) {
2388 media_monitor_->Stop();
2389 media_monitor_->SignalUpdate.disconnect(this);
2390 media_monitor_.reset();
2391 }
2392}
2393
2394void DataChannel::OnMediaMonitorUpdate(
2395 DataMediaChannel* media_channel, const DataMediaInfo& info) {
2396 ASSERT(media_channel == this->media_channel());
2397 SignalMediaMonitor(this, info);
2398}
2399
2400void DataChannel::OnDataReceived(
2401 const ReceiveDataParams& params, const char* data, size_t len) {
2402 DataReceivedMessageData* msg = new DataReceivedMessageData(
2403 params, data, len);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002404 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002405}
2406
Peter Boström0c4e06b2015-10-07 12:23:21 +02002407void DataChannel::OnDataChannelError(uint32_t ssrc,
2408 DataMediaChannel::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002409 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2410 ssrc, err);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002411 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_CHANNEL_ERROR, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002412}
2413
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002414void DataChannel::OnDataChannelReadyToSend(bool writable) {
2415 // This is usded for congestion control to indicate that the stream is ready
2416 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2417 // that the transport channel is ready.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002418 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002419 new DataChannelReadyToSendMessageData(writable));
2420}
2421
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002422void DataChannel::GetSrtpCryptoSuites_n(std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002423 GetSupportedDataCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002424}
2425
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002426bool DataChannel::ShouldSetupDtlsSrtp_n() const {
2427 return data_channel_type_ == DCT_RTP && BaseChannel::ShouldSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002428}
2429
Peter Boström0c4e06b2015-10-07 12:23:21 +02002430void DataChannel::OnStreamClosedRemotely(uint32_t sid) {
2431 rtc::TypedMessageData<uint32_t>* message =
2432 new rtc::TypedMessageData<uint32_t>(sid);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002433 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_STREAMCLOSEDREMOTELY,
2434 message);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002435}
2436
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002437} // namespace cricket