blob: e464124bd617ff545f47c52b7e88c2e3c29c5fd9 [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
jbauchcb560652016-08-04 05:20:32 -0700558bool BaseChannel::SetCryptoOptions(const rtc::CryptoOptions& crypto_options) {
559 crypto_options_ = crypto_options;
560 return true;
561}
562
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000563void BaseChannel::OnWritableState(TransportChannel* channel) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200564 RTC_DCHECK(channel == transport_channel_ ||
565 channel == rtcp_transport_channel_);
566 RTC_DCHECK(network_thread_->IsCurrent());
567 UpdateWritableState_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000568}
569
570void BaseChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000571 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000572 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000573 int flags) {
Peter Boström6f28cf02015-12-07 23:17:15 +0100574 TRACE_EVENT0("webrtc", "BaseChannel::OnChannelRead");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000575 // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200576 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000577
578 // When using RTCP multiplexing we might get RTCP packets on the RTP
579 // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
580 bool rtcp = PacketIsRtcp(channel, data, len);
jbaucheec21bd2016-03-20 06:15:43 -0700581 rtc::CopyOnWriteBuffer packet(data, len);
wu@webrtc.orga9890802013-12-13 00:21:03 +0000582 HandlePacket(rtcp, &packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000583}
584
585void BaseChannel::OnReadyToSend(TransportChannel* channel) {
deadbeefcbecd352015-09-23 11:50:27 -0700586 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
587 SetReadyToSend(channel == rtcp_transport_channel_, true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000588}
589
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800590void BaseChannel::OnDtlsState(TransportChannel* channel,
591 DtlsTransportState state) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200592 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800593 return;
594 }
595
596 // Reset the srtp filter if it's not the CONNECTED state. For the CONNECTED
597 // state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to
598 // cover other scenarios like the whole channel is writable (not just this
599 // TransportChannel) or when TransportChannel is attached after DTLS is
600 // negotiated.
601 if (state != DTLS_TRANSPORT_CONNECTED) {
602 srtp_filter_.ResetParams();
603 }
604}
605
Honghai Zhangcc411c02016-03-29 17:27:21 -0700606void BaseChannel::OnSelectedCandidatePairChanged(
607 TransportChannel* channel,
Honghai Zhang52dce732016-03-31 12:37:31 -0700608 CandidatePairInterface* selected_candidate_pair,
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -0700609 int last_sent_packet_id,
610 bool ready_to_send) {
Honghai Zhangcc411c02016-03-29 17:27:21 -0700611 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200612 RTC_DCHECK(network_thread_->IsCurrent());
613 std::string transport_name = channel->transport_name();
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700614 rtc::NetworkRoute network_route;
Honghai Zhangcc411c02016-03-29 17:27:21 -0700615 if (selected_candidate_pair) {
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700616 network_route = rtc::NetworkRoute(
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -0700617 ready_to_send, selected_candidate_pair->local_candidate().network_id(),
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700618 selected_candidate_pair->remote_candidate().network_id(),
619 last_sent_packet_id);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700620 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200621 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700622 RTC_FROM_HERE, worker_thread_,
623 Bind(&MediaChannel::OnNetworkRouteChanged, media_channel_, transport_name,
624 network_route));
Honghai Zhangcc411c02016-03-29 17:27:21 -0700625}
626
deadbeefcbecd352015-09-23 11:50:27 -0700627void BaseChannel::SetReadyToSend(bool rtcp, bool ready) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200628 RTC_DCHECK(network_thread_->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -0700629 if (rtcp) {
630 rtcp_ready_to_send_ = ready;
631 } else {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000632 rtp_ready_to_send_ = ready;
633 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000634
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200635 bool ready_to_send =
636 (rtp_ready_to_send_ &&
637 // In the case of rtcp mux |rtcp_transport_channel_| will be null.
638 (rtcp_ready_to_send_ || !rtcp_transport_channel_));
639
640 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700641 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200642 Bind(&MediaChannel::OnReadyToSend, media_channel_, ready_to_send));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000643}
644
645bool BaseChannel::PacketIsRtcp(const TransportChannel* channel,
646 const char* data, size_t len) {
647 return (channel == rtcp_transport_channel_ ||
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000648 rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000649}
650
stefanc1aeaf02015-10-15 07:26:07 -0700651bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700652 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700653 const rtc::PacketOptions& options) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200654 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
655 // If the thread is not our network thread, we will post to our network
656 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000657 // synchronize access to all the pieces of the send path, including
658 // SRTP and the inner workings of the transport channels.
659 // The only downside is that we can't return a proper failure code if
660 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200661 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000662 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200663 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
664 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800665 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700666 data->options = options;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700667 network_thread_->Post(RTC_FROM_HERE, this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000668 return true;
669 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200670 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000671
672 // Now that we are on the correct thread, ensure we have a place to send this
673 // packet before doing anything. (We might get RTCP packets that we don't
674 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
675 // transport.
676 TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
677 transport_channel_ : rtcp_transport_channel_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000678 if (!channel || !channel->writable()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 return false;
680 }
681
682 // Protect ourselves against crazy data.
683 if (!ValidPacket(rtcp, packet)) {
684 LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000685 << PacketType(rtcp)
686 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000687 return false;
688 }
689
stefanc1aeaf02015-10-15 07:26:07 -0700690 rtc::PacketOptions updated_options;
691 updated_options = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000692 // Protect if needed.
693 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200694 TRACE_EVENT0("webrtc", "SRTP Encode");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000695 bool res;
Karl Wibergc56ac1e2015-05-04 14:54:55 +0200696 uint8_t* data = packet->data();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000697 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000698 if (!rtcp) {
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000699 // If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
700 // inside libsrtp for a RTP packet. A external HMAC module will be writing
701 // a fake HMAC value. This is ONLY done for a RTP packet.
702 // Socket layer will update rtp sendtime extension header if present in
703 // packet with current time before updating the HMAC.
704#if !defined(ENABLE_EXTERNAL_AUTH)
705 res = srtp_filter_.ProtectRtp(
706 data, len, static_cast<int>(packet->capacity()), &len);
707#else
stefanc1aeaf02015-10-15 07:26:07 -0700708 updated_options.packet_time_params.rtp_sendtime_extension_id =
henrike@webrtc.org05376342014-03-10 15:53:12 +0000709 rtp_abs_sendtime_extn_id_;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000710 res = srtp_filter_.ProtectRtp(
711 data, len, static_cast<int>(packet->capacity()), &len,
stefanc1aeaf02015-10-15 07:26:07 -0700712 &updated_options.packet_time_params.srtp_packet_index);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000713 // If protection succeeds, let's get auth params from srtp.
714 if (res) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200715 uint8_t* auth_key = NULL;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000716 int key_len;
717 res = srtp_filter_.GetRtpAuthParams(
stefanc1aeaf02015-10-15 07:26:07 -0700718 &auth_key, &key_len,
719 &updated_options.packet_time_params.srtp_auth_tag_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000720 if (res) {
stefanc1aeaf02015-10-15 07:26:07 -0700721 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
722 updated_options.packet_time_params.srtp_auth_key.assign(
723 auth_key, auth_key + key_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000724 }
725 }
726#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000727 if (!res) {
728 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200729 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000730 GetRtpSeqNum(data, len, &seq_num);
731 GetRtpSsrc(data, len, &ssrc);
732 LOG(LS_ERROR) << "Failed to protect " << content_name_
733 << " RTP packet: size=" << len
734 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
735 return false;
736 }
737 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000738 res = srtp_filter_.ProtectRtcp(data, len,
739 static_cast<int>(packet->capacity()),
740 &len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000741 if (!res) {
742 int type = -1;
743 GetRtcpType(data, len, &type);
744 LOG(LS_ERROR) << "Failed to protect " << content_name_
745 << " RTCP packet: size=" << len << ", type=" << type;
746 return false;
747 }
748 }
749
750 // Update the length of the packet now that we've added the auth tag.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000751 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000752 } else if (secure_required_) {
753 // This is a double check for something that supposedly can't happen.
754 LOG(LS_ERROR) << "Can't send outgoing " << PacketType(rtcp)
755 << " packet when SRTP is inactive and crypto is required";
756
757 ASSERT(false);
758 return false;
759 }
760
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000761 // Bon voyage.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200762 int flags = (secure() && secure_dtls()) ? PF_SRTP_BYPASS : PF_NORMAL;
763 int ret = channel->SendPacket(packet->data<char>(), packet->size(),
764 updated_options, flags);
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000765 if (ret != static_cast<int>(packet->size())) {
skvladc309e0e2016-07-28 17:15:20 -0700766 if (channel->GetError() == ENOTCONN) {
767 LOG(LS_WARNING) << "Got ENOTCONN from transport.";
deadbeefcbecd352015-09-23 11:50:27 -0700768 SetReadyToSend(rtcp, false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000769 }
770 return false;
771 }
772 return true;
773}
774
jbaucheec21bd2016-03-20 06:15:43 -0700775bool BaseChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000776 // Protect ourselves against crazy data.
777 if (!ValidPacket(rtcp, packet)) {
778 LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000779 << PacketType(rtcp)
780 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000781 return false;
782 }
pbos482b12e2015-11-16 10:19:58 -0800783 if (rtcp) {
784 // Permit all (seemingly valid) RTCP packets.
785 return true;
786 }
787 // Check whether we handle this payload.
jbaucheec21bd2016-03-20 06:15:43 -0700788 return bundle_filter_.DemuxPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000789}
790
jbaucheec21bd2016-03-20 06:15:43 -0700791void BaseChannel::HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000792 const rtc::PacketTime& packet_time) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200793 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000794 if (!WantsPacket(rtcp, packet)) {
795 return;
796 }
797
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000798 // We are only interested in the first rtp packet because that
799 // indicates the media has started flowing.
800 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000801 has_received_packet_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700802 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000803 }
804
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000805 // Unprotect the packet, if needed.
806 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200807 TRACE_EVENT0("webrtc", "SRTP Decode");
Karl Wiberg94784372015-04-20 14:03:07 +0200808 char* data = packet->data<char>();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000809 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000810 bool res;
811 if (!rtcp) {
812 res = srtp_filter_.UnprotectRtp(data, len, &len);
813 if (!res) {
814 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200815 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000816 GetRtpSeqNum(data, len, &seq_num);
817 GetRtpSsrc(data, len, &ssrc);
818 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
819 << " RTP packet: size=" << len
820 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
821 return;
822 }
823 } else {
824 res = srtp_filter_.UnprotectRtcp(data, len, &len);
825 if (!res) {
826 int type = -1;
827 GetRtcpType(data, len, &type);
828 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
829 << " RTCP packet: size=" << len << ", type=" << type;
830 return;
831 }
832 }
833
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000834 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000835 } else if (secure_required_) {
836 // Our session description indicates that SRTP is required, but we got a
837 // packet before our SRTP filter is active. This means either that
838 // a) we got SRTP packets before we received the SDES keys, in which case
839 // we can't decrypt it anyway, or
840 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
841 // channels, so we haven't yet extracted keys, even if DTLS did complete
842 // on the channel that the packets are being sent on. It's really good
843 // practice to wait for both RTP and RTCP to be good to go before sending
844 // media, to prevent weird failure modes, so it's fine for us to just eat
845 // packets here. This is all sidestepped if RTCP mux is used anyway.
846 LOG(LS_WARNING) << "Can't process incoming " << PacketType(rtcp)
847 << " packet when SRTP is inactive and crypto is required";
848 return;
849 }
850
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200851 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700852 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200853 Bind(&BaseChannel::OnPacketReceived, this, rtcp, *packet, packet_time));
854}
855
856void BaseChannel::OnPacketReceived(bool rtcp,
857 const rtc::CopyOnWriteBuffer& packet,
858 const rtc::PacketTime& packet_time) {
859 RTC_DCHECK(worker_thread_->IsCurrent());
860 // Need to copy variable because OnRtcpReceived/OnPacketReceived
861 // requires non-const pointer to buffer. This doesn't memcpy the actual data.
862 rtc::CopyOnWriteBuffer data(packet);
863 if (rtcp) {
864 media_channel_->OnRtcpReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000865 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200866 media_channel_->OnPacketReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000867 }
868}
869
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000870bool BaseChannel::PushdownLocalDescription(
871 const SessionDescription* local_desc, ContentAction action,
872 std::string* error_desc) {
873 const ContentInfo* content_info = GetFirstContent(local_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000874 const MediaContentDescription* content_desc =
875 GetContentDescription(content_info);
876 if (content_desc && content_info && !content_info->rejected &&
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000877 !SetLocalContent(content_desc, action, error_desc)) {
878 LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
879 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000880 }
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000881 return true;
882}
883
884bool BaseChannel::PushdownRemoteDescription(
885 const SessionDescription* remote_desc, ContentAction action,
886 std::string* error_desc) {
887 const ContentInfo* content_info = GetFirstContent(remote_desc);
888 const MediaContentDescription* content_desc =
889 GetContentDescription(content_info);
890 if (content_desc && content_info && !content_info->rejected &&
891 !SetRemoteContent(content_desc, action, error_desc)) {
892 LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
893 return false;
894 }
895 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000896}
897
898void BaseChannel::EnableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000899 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000900 if (enabled_)
901 return;
902
903 LOG(LS_INFO) << "Channel enabled";
904 enabled_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200905 ChangeState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000906}
907
908void BaseChannel::DisableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000909 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000910 if (!enabled_)
911 return;
912
913 LOG(LS_INFO) << "Channel disabled";
914 enabled_ = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200915 ChangeState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000916}
917
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200918void BaseChannel::UpdateWritableState_n() {
deadbeefcbecd352015-09-23 11:50:27 -0700919 if (transport_channel_ && transport_channel_->writable() &&
920 (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200921 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700922 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200923 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700924 }
925}
926
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200927void BaseChannel::ChannelWritable_n() {
928 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800929 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000930 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800931 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000932
deadbeefcbecd352015-09-23 11:50:27 -0700933 LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000934 << (was_ever_writable_ ? "" : " for the first time");
935
936 std::vector<ConnectionInfo> infos;
937 transport_channel_->GetStats(&infos);
938 for (std::vector<ConnectionInfo>::const_iterator it = infos.begin();
939 it != infos.end(); ++it) {
940 if (it->best_connection) {
941 LOG(LS_INFO) << "Using " << it->local_candidate.ToSensitiveString()
942 << "->" << it->remote_candidate.ToSensitiveString();
943 break;
944 }
945 }
946
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000947 was_ever_writable_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200948 MaybeSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000949 writable_ = true;
950 ChangeState();
951}
952
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200953void BaseChannel::SignalDtlsSetupFailure_n(bool rtcp) {
954 RTC_DCHECK(network_thread_->IsCurrent());
955 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700956 RTC_FROM_HERE, signaling_thread(),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200957 Bind(&BaseChannel::SignalDtlsSetupFailure_s, this, rtcp));
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000958}
959
960void BaseChannel::SignalDtlsSetupFailure_s(bool rtcp) {
961 ASSERT(signaling_thread() == rtc::Thread::Current());
962 SignalDtlsSetupFailure(this, rtcp);
963}
964
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200965bool BaseChannel::SetDtlsSrtpCryptoSuites_n(TransportChannel* tc, bool rtcp) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800966 std::vector<int> crypto_suites;
967 // We always use the default SRTP crypto suites for RTCP, but we may use
968 // different crypto suites for RTP depending on the media type.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000969 if (!rtcp) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200970 GetSrtpCryptoSuites_n(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000971 } else {
jbauchcb560652016-08-04 05:20:32 -0700972 GetDefaultSrtpCryptoSuites(crypto_options(), &crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000973 }
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800974 return tc->SetSrtpCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000975}
976
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200977bool BaseChannel::ShouldSetupDtlsSrtp_n() const {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800978 // Since DTLS is applied to all channels, checking RTP should be enough.
979 return transport_channel_ && transport_channel_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000980}
981
982// This function returns true if either DTLS-SRTP is not in use
983// *or* DTLS-SRTP is successfully set up.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200984bool BaseChannel::SetupDtlsSrtp_n(bool rtcp_channel) {
985 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 bool ret = false;
987
deadbeefcbecd352015-09-23 11:50:27 -0700988 TransportChannel* channel =
989 rtcp_channel ? rtcp_transport_channel_ : transport_channel_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000990
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800991 RTC_DCHECK(channel->IsDtlsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000992
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800993 int selected_crypto_suite;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000994
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800995 if (!channel->GetSrtpCryptoSuite(&selected_crypto_suite)) {
996 LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000997 return false;
998 }
999
1000 LOG(LS_INFO) << "Installing keys from DTLS-SRTP on "
1001 << content_name() << " "
1002 << PacketType(rtcp_channel);
1003
jbauchcb560652016-08-04 05:20:32 -07001004 int key_len;
1005 int salt_len;
1006 if (!rtc::GetSrtpKeyAndSaltLengths(selected_crypto_suite, &key_len,
1007 &salt_len)) {
1008 LOG(LS_ERROR) << "Unknown DTLS-SRTP crypto suite" << selected_crypto_suite;
1009 return false;
1010 }
1011
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001012 // OK, we're now doing DTLS (RFC 5764)
jbauchcb560652016-08-04 05:20:32 -07001013 std::vector<unsigned char> dtls_buffer(key_len * 2 + salt_len * 2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001014
1015 // RFC 5705 exporter using the RFC 5764 parameters
1016 if (!channel->ExportKeyingMaterial(
1017 kDtlsSrtpExporterLabel,
1018 NULL, 0, false,
1019 &dtls_buffer[0], dtls_buffer.size())) {
1020 LOG(LS_WARNING) << "DTLS-SRTP key export failed";
1021 ASSERT(false); // This should never happen
1022 return false;
1023 }
1024
1025 // Sync up the keys with the DTLS-SRTP interface
jbauchcb560652016-08-04 05:20:32 -07001026 std::vector<unsigned char> client_write_key(key_len + salt_len);
1027 std::vector<unsigned char> server_write_key(key_len + salt_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001028 size_t offset = 0;
jbauchcb560652016-08-04 05:20:32 -07001029 memcpy(&client_write_key[0], &dtls_buffer[offset], key_len);
1030 offset += key_len;
1031 memcpy(&server_write_key[0], &dtls_buffer[offset], key_len);
1032 offset += key_len;
1033 memcpy(&client_write_key[key_len], &dtls_buffer[offset], salt_len);
1034 offset += salt_len;
1035 memcpy(&server_write_key[key_len], &dtls_buffer[offset], salt_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001036
1037 std::vector<unsigned char> *send_key, *recv_key;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001038 rtc::SSLRole role;
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00001039 if (!channel->GetSslRole(&role)) {
1040 LOG(LS_WARNING) << "GetSslRole failed";
1041 return false;
1042 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001043
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001044 if (role == rtc::SSL_SERVER) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001045 send_key = &server_write_key;
1046 recv_key = &client_write_key;
1047 } else {
1048 send_key = &client_write_key;
1049 recv_key = &server_write_key;
1050 }
1051
1052 if (rtcp_channel) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001053 ret = srtp_filter_.SetRtcpParams(selected_crypto_suite, &(*send_key)[0],
1054 static_cast<int>(send_key->size()),
1055 selected_crypto_suite, &(*recv_key)[0],
1056 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001057 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001058 ret = srtp_filter_.SetRtpParams(selected_crypto_suite, &(*send_key)[0],
1059 static_cast<int>(send_key->size()),
1060 selected_crypto_suite, &(*recv_key)[0],
1061 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001062 }
1063
1064 if (!ret)
1065 LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
1066 else
1067 dtls_keyed_ = true;
1068
1069 return ret;
1070}
1071
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001072void BaseChannel::MaybeSetupDtlsSrtp_n() {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001073 if (srtp_filter_.IsActive()) {
1074 return;
1075 }
1076
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001077 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001078 return;
1079 }
1080
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001081 if (!SetupDtlsSrtp_n(false)) {
1082 SignalDtlsSetupFailure_n(false);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001083 return;
1084 }
1085
1086 if (rtcp_transport_channel_) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001087 if (!SetupDtlsSrtp_n(true)) {
1088 SignalDtlsSetupFailure_n(true);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001089 return;
1090 }
1091 }
1092}
1093
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001094void BaseChannel::ChannelNotWritable_n() {
1095 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001096 if (!writable_)
1097 return;
1098
deadbeefcbecd352015-09-23 11:50:27 -07001099 LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001100 writable_ = false;
1101 ChangeState();
1102}
1103
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001104bool BaseChannel::SetRtpTransportParameters(
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001105 const MediaContentDescription* content,
1106 ContentAction action,
1107 ContentSource src,
1108 std::string* error_desc) {
1109 if (action == CA_UPDATE) {
1110 // These parameters never get changed by a CA_UDPATE.
1111 return true;
1112 }
1113
1114 // Cache secure_required_ for belt and suspenders check on SendPacket
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001115 return network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001116 RTC_FROM_HERE, Bind(&BaseChannel::SetRtpTransportParameters_n, this,
1117 content, action, src, error_desc));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001118}
1119
1120bool BaseChannel::SetRtpTransportParameters_n(
1121 const MediaContentDescription* content,
1122 ContentAction action,
1123 ContentSource src,
1124 std::string* error_desc) {
1125 RTC_DCHECK(network_thread_->IsCurrent());
1126
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001127 if (src == CS_LOCAL) {
1128 set_secure_required(content->crypto_required() != CT_NONE);
1129 }
1130
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001131 if (!SetSrtp_n(content->cryptos(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001132 return false;
1133 }
1134
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001135 if (!SetRtcpMux_n(content->rtcp_mux(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001136 return false;
1137 }
1138
1139 return true;
1140}
1141
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001142// |dtls| will be set to true if DTLS is active for transport channel and
1143// crypto is empty.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001144bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
1145 bool* dtls,
1146 std::string* error_desc) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001147 *dtls = transport_channel_->IsDtlsActive();
1148 if (*dtls && !cryptos.empty()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001149 SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001150 return false;
1151 }
1152 return true;
1153}
1154
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001155bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001156 ContentAction action,
1157 ContentSource src,
1158 std::string* error_desc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001159 TRACE_EVENT0("webrtc", "BaseChannel::SetSrtp_w");
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001160 if (action == CA_UPDATE) {
1161 // no crypto params.
1162 return true;
1163 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001164 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001165 bool dtls = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001166 ret = CheckSrtpConfig_n(cryptos, &dtls, error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001167 if (!ret) {
1168 return false;
1169 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001170 switch (action) {
1171 case CA_OFFER:
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001172 // If DTLS is already active on the channel, we could be renegotiating
1173 // here. We don't update the srtp filter.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001174 if (!dtls) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001175 ret = srtp_filter_.SetOffer(cryptos, src);
1176 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001177 break;
1178 case CA_PRANSWER:
1179 // If we're doing DTLS-SRTP, we don't want to update the filter
1180 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001181 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001182 ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
1183 }
1184 break;
1185 case CA_ANSWER:
1186 // If we're doing DTLS-SRTP, we don't want to update the filter
1187 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001188 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001189 ret = srtp_filter_.SetAnswer(cryptos, src);
1190 }
1191 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001192 default:
1193 break;
1194 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001195 if (!ret) {
1196 SafeSetError("Failed to setup SRTP filter.", error_desc);
1197 return false;
1198 }
1199 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001200}
1201
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001202void BaseChannel::ActivateRtcpMux() {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001203 network_thread_->Invoke<void>(RTC_FROM_HERE,
1204 Bind(&BaseChannel::ActivateRtcpMux_n, this));
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001205}
1206
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001207void BaseChannel::ActivateRtcpMux_n() {
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001208 if (!rtcp_mux_filter_.IsActive()) {
1209 rtcp_mux_filter_.SetActive();
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001210 SetRtcpTransportChannel_n(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001211 rtcp_transport_enabled_ = false;
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001212 }
1213}
1214
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001215bool BaseChannel::SetRtcpMux_n(bool enable,
1216 ContentAction action,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001217 ContentSource src,
1218 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001219 bool ret = false;
1220 switch (action) {
1221 case CA_OFFER:
1222 ret = rtcp_mux_filter_.SetOffer(enable, src);
1223 break;
1224 case CA_PRANSWER:
1225 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
1226 break;
1227 case CA_ANSWER:
1228 ret = rtcp_mux_filter_.SetAnswer(enable, src);
1229 if (ret && rtcp_mux_filter_.IsActive()) {
1230 // We activated RTCP mux, close down the RTCP transport.
deadbeefcbecd352015-09-23 11:50:27 -07001231 LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
1232 << " by destroying RTCP transport channel for "
1233 << transport_name();
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001234 SetRtcpTransportChannel_n(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001235 rtcp_transport_enabled_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001236 }
1237 break;
1238 case CA_UPDATE:
1239 // No RTCP mux info.
1240 ret = true;
Henrik Kjellander7c027b62015-04-22 13:21:30 +02001241 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001242 default:
1243 break;
1244 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001245 if (!ret) {
1246 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
1247 return false;
1248 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001249 // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
1250 // CA_ANSWER, but we only want to tear down the RTCP transport channel if we
1251 // received a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001252 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001253 // If the RTP transport is already writable, then so are we.
1254 if (transport_channel_->writable()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001255 ChannelWritable_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001256 }
1257 }
1258
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001259 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001260}
1261
1262bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001263 ASSERT(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -08001264 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001265}
1266
Peter Boström0c4e06b2015-10-07 12:23:21 +02001267bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001268 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001269 return media_channel()->RemoveRecvStream(ssrc);
1270}
1271
1272bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001273 ContentAction action,
1274 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001275 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1276 action == CA_PRANSWER || action == CA_UPDATE))
1277 return false;
1278
1279 // If this is an update, streams only contain streams that have changed.
1280 if (action == CA_UPDATE) {
1281 for (StreamParamsVec::const_iterator it = streams.begin();
1282 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001283 const StreamParams* existing_stream =
1284 GetStreamByIds(local_streams_, it->groupid, it->id);
1285 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001286 if (media_channel()->AddSendStream(*it)) {
1287 local_streams_.push_back(*it);
1288 LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
1289 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001290 std::ostringstream desc;
1291 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1292 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001293 return false;
1294 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001295 } else if (existing_stream && !it->has_ssrcs()) {
1296 if (!media_channel()->RemoveSendStream(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001297 std::ostringstream desc;
1298 desc << "Failed to remove send stream with ssrc "
1299 << it->first_ssrc() << ".";
1300 SafeSetError(desc.str(), error_desc);
1301 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001302 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001303 RemoveStreamBySsrc(&local_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001304 } else {
1305 LOG(LS_WARNING) << "Ignore unsupported stream update";
1306 }
1307 }
1308 return true;
1309 }
1310 // Else streams are all the streams we want to send.
1311
1312 // Check for streams that have been removed.
1313 bool ret = true;
1314 for (StreamParamsVec::const_iterator it = local_streams_.begin();
1315 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001316 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001317 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001318 std::ostringstream desc;
1319 desc << "Failed to remove send stream with ssrc "
1320 << it->first_ssrc() << ".";
1321 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001322 ret = false;
1323 }
1324 }
1325 }
1326 // Check for new streams.
1327 for (StreamParamsVec::const_iterator it = streams.begin();
1328 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001329 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001330 if (media_channel()->AddSendStream(*it)) {
stefanc1aeaf02015-10-15 07:26:07 -07001331 LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001332 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001333 std::ostringstream desc;
1334 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1335 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001336 ret = false;
1337 }
1338 }
1339 }
1340 local_streams_ = streams;
1341 return ret;
1342}
1343
1344bool BaseChannel::UpdateRemoteStreams_w(
1345 const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001346 ContentAction action,
1347 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001348 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1349 action == CA_PRANSWER || action == CA_UPDATE))
1350 return false;
1351
1352 // If this is an update, streams only contain streams that have changed.
1353 if (action == CA_UPDATE) {
1354 for (StreamParamsVec::const_iterator it = streams.begin();
1355 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001356 const StreamParams* existing_stream =
1357 GetStreamByIds(remote_streams_, it->groupid, it->id);
1358 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001359 if (AddRecvStream_w(*it)) {
1360 remote_streams_.push_back(*it);
1361 LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
1362 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001363 std::ostringstream desc;
1364 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1365 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001366 return false;
1367 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001368 } else if (existing_stream && !it->has_ssrcs()) {
1369 if (!RemoveRecvStream_w(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001370 std::ostringstream desc;
1371 desc << "Failed to remove remote stream with ssrc "
1372 << it->first_ssrc() << ".";
1373 SafeSetError(desc.str(), error_desc);
1374 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001375 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001376 RemoveStreamBySsrc(&remote_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001377 } else {
1378 LOG(LS_WARNING) << "Ignore unsupported stream update."
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001379 << " Stream exists? " << (existing_stream != nullptr)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001380 << " new stream = " << it->ToString();
1381 }
1382 }
1383 return true;
1384 }
1385 // Else streams are all the streams we want to receive.
1386
1387 // Check for streams that have been removed.
1388 bool ret = true;
1389 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
1390 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001391 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001392 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001393 std::ostringstream desc;
1394 desc << "Failed to remove remote stream with ssrc "
1395 << it->first_ssrc() << ".";
1396 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001397 ret = false;
1398 }
1399 }
1400 }
1401 // Check for new streams.
1402 for (StreamParamsVec::const_iterator it = streams.begin();
1403 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001404 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001405 if (AddRecvStream_w(*it)) {
1406 LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
1407 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001408 std::ostringstream desc;
1409 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1410 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001411 ret = false;
1412 }
1413 }
1414 }
1415 remote_streams_ = streams;
1416 return ret;
1417}
1418
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001419void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w(
isheriff6f8d6862016-05-26 11:24:55 -07001420 const std::vector<webrtc::RtpExtension>& extensions) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001421// Absolute Send Time extension id is used only with external auth,
1422// so do not bother searching for it and making asyncronious call to set
1423// something that is not used.
1424#if defined(ENABLE_EXTERNAL_AUTH)
isheriff6f8d6862016-05-26 11:24:55 -07001425 const webrtc::RtpExtension* send_time_extension =
1426 FindHeaderExtension(extensions, webrtc::RtpExtension::kAbsSendTimeUri);
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001427 int rtp_abs_sendtime_extn_id =
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001428 send_time_extension ? send_time_extension->id : -1;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001429 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001430 RTC_FROM_HERE, network_thread_,
1431 Bind(&BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n, this,
1432 rtp_abs_sendtime_extn_id));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001433#endif
1434}
1435
1436void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n(
1437 int rtp_abs_sendtime_extn_id) {
1438 rtp_abs_sendtime_extn_id_ = rtp_abs_sendtime_extn_id;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001439}
1440
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001441void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001442 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001443 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001444 case MSG_SEND_RTP_PACKET:
1445 case MSG_SEND_RTCP_PACKET: {
1446 RTC_DCHECK(network_thread_->IsCurrent());
1447 SendPacketMessageData* data =
1448 static_cast<SendPacketMessageData*>(pmsg->pdata);
1449 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
1450 SendPacket(rtcp, &data->packet, data->options);
1451 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001452 break;
1453 }
1454 case MSG_FIRSTPACKETRECEIVED: {
1455 SignalFirstPacketReceived(this);
1456 break;
1457 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001458 }
1459}
1460
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001461void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001462 // Flush all remaining RTCP messages. This should only be called in
1463 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001464 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001465 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001466 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
1467 for (const auto& message : rtcp_messages) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001468 network_thread_->Send(RTC_FROM_HERE, this, MSG_SEND_RTCP_PACKET,
1469 message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001470 }
1471}
1472
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001473void BaseChannel::SignalSentPacket_n(TransportChannel* /* channel */,
1474 const rtc::SentPacket& sent_packet) {
1475 RTC_DCHECK(network_thread_->IsCurrent());
1476 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001477 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001478 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
1479}
1480
1481void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
1482 RTC_DCHECK(worker_thread_->IsCurrent());
1483 SignalSentPacket(sent_packet);
1484}
1485
1486VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
1487 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001488 MediaEngineInterface* media_engine,
1489 VoiceMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001490 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001491 const std::string& content_name,
1492 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001493 : BaseChannel(worker_thread,
1494 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001495 media_channel,
1496 transport_controller,
1497 content_name,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001498 rtcp),
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001499 media_engine_(media_engine),
deadbeefcbecd352015-09-23 11:50:27 -07001500 received_media_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001501
1502VoiceChannel::~VoiceChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001503 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001504 StopAudioMonitor();
1505 StopMediaMonitor();
1506 // this can't be done in the base class, since it calls a virtual
1507 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001508 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001509}
1510
skvlad6c87a672016-05-17 17:49:52 -07001511bool VoiceChannel::Init_w(const std::string* bundle_transport_name) {
1512 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001513 return false;
1514 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001515 return true;
1516}
1517
Peter Boström0c4e06b2015-10-07 12:23:21 +02001518bool VoiceChannel::SetAudioSend(uint32_t ssrc,
solenbergdfc8f4f2015-10-01 02:31:10 -07001519 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001520 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001521 AudioSource* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001522 return InvokeOnWorker(RTC_FROM_HERE,
1523 Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001524 ssrc, enable, options, source));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001525}
1526
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001527// TODO(juberti): Handle early media the right way. We should get an explicit
1528// ringing message telling us to start playing local ringback, which we cancel
1529// if any early media actually arrives. For now, we do the opposite, which is
1530// to wait 1 second for early media, and start playing local ringback if none
1531// arrives.
1532void VoiceChannel::SetEarlyMedia(bool enable) {
1533 if (enable) {
1534 // Start the early media timeout
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001535 worker_thread()->PostDelayed(RTC_FROM_HERE, kEarlyMediaTimeout, this,
1536 MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001537 } else {
1538 // Stop the timeout if currently going.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001539 worker_thread()->Clear(this, MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001540 }
1541}
1542
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001543bool VoiceChannel::CanInsertDtmf() {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001544 return InvokeOnWorker(
1545 RTC_FROM_HERE, Bind(&VoiceMediaChannel::CanInsertDtmf, media_channel()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546}
1547
Peter Boström0c4e06b2015-10-07 12:23:21 +02001548bool VoiceChannel::InsertDtmf(uint32_t ssrc,
1549 int event_code,
solenberg1d63dd02015-12-02 12:35:09 -08001550 int duration) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001551 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceChannel::InsertDtmf_w, this,
1552 ssrc, event_code, duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001553}
1554
solenberg4bac9c52015-10-09 02:32:53 -07001555bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001556 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::SetOutputVolume,
1557 media_channel(), ssrc, volume));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001558}
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001559
Tommif888bb52015-12-12 01:37:01 +01001560void VoiceChannel::SetRawAudioSink(
1561 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -08001562 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
1563 // We need to work around Bind's lack of support for unique_ptr and ownership
deadbeef2d110be2016-01-13 12:00:26 -08001564 // passing. So we invoke to our own little routine that gets a pointer to
1565 // our local variable. This is OK since we're synchronously invoking.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001566 InvokeOnWorker(RTC_FROM_HERE,
1567 Bind(&SetRawAudioSink_w, media_channel(), ssrc, &sink));
Tommif888bb52015-12-12 01:37:01 +01001568}
1569
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001570webrtc::RtpParameters VoiceChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001571 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001572 RTC_FROM_HERE, Bind(&VoiceChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001573}
1574
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001575webrtc::RtpParameters VoiceChannel::GetRtpSendParameters_w(
1576 uint32_t ssrc) const {
1577 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001578}
1579
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001580bool VoiceChannel::SetRtpSendParameters(
1581 uint32_t ssrc,
1582 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001583 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001584 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001585 Bind(&VoiceChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001586}
1587
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001588bool VoiceChannel::SetRtpSendParameters_w(uint32_t ssrc,
1589 webrtc::RtpParameters parameters) {
1590 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1591}
1592
1593webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters(
1594 uint32_t ssrc) const {
1595 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001596 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001597 Bind(&VoiceChannel::GetRtpReceiveParameters_w, this, ssrc));
1598}
1599
1600webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters_w(
1601 uint32_t ssrc) const {
1602 return media_channel()->GetRtpReceiveParameters(ssrc);
1603}
1604
1605bool VoiceChannel::SetRtpReceiveParameters(
1606 uint32_t ssrc,
1607 const webrtc::RtpParameters& parameters) {
1608 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001609 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001610 Bind(&VoiceChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1611}
1612
1613bool VoiceChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1614 webrtc::RtpParameters parameters) {
1615 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001616}
1617
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001618bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001619 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::GetStats,
1620 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001621}
1622
1623void VoiceChannel::StartMediaMonitor(int cms) {
1624 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001625 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001626 media_monitor_->SignalUpdate.connect(
1627 this, &VoiceChannel::OnMediaMonitorUpdate);
1628 media_monitor_->Start(cms);
1629}
1630
1631void VoiceChannel::StopMediaMonitor() {
1632 if (media_monitor_) {
1633 media_monitor_->Stop();
1634 media_monitor_->SignalUpdate.disconnect(this);
1635 media_monitor_.reset();
1636 }
1637}
1638
1639void VoiceChannel::StartAudioMonitor(int cms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001640 audio_monitor_.reset(new AudioMonitor(this, rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001641 audio_monitor_
1642 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1643 audio_monitor_->Start(cms);
1644}
1645
1646void VoiceChannel::StopAudioMonitor() {
1647 if (audio_monitor_) {
1648 audio_monitor_->Stop();
1649 audio_monitor_.reset();
1650 }
1651}
1652
1653bool VoiceChannel::IsAudioMonitorRunning() const {
1654 return (audio_monitor_.get() != NULL);
1655}
1656
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001657int VoiceChannel::GetInputLevel_w() {
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001658 return media_engine_->GetInputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001659}
1660
1661int VoiceChannel::GetOutputLevel_w() {
1662 return media_channel()->GetOutputLevel();
1663}
1664
1665void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1666 media_channel()->GetActiveStreams(actives);
1667}
1668
1669void VoiceChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001670 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001671 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001672 int flags) {
1673 BaseChannel::OnChannelRead(channel, data, len, packet_time, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001674
1675 // Set a flag when we've received an RTP packet. If we're waiting for early
1676 // media, this will disable the timeout.
1677 if (!received_media_ && !PacketIsRtcp(channel, data, len)) {
1678 received_media_ = true;
1679 }
1680}
1681
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001682void BaseChannel::ChangeState() {
1683 RTC_DCHECK(network_thread_->IsCurrent());
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001684 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001685 Bind(&BaseChannel::ChangeState_w, this));
1686}
1687
1688void VoiceChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001689 // Render incoming data if we're the active call, and we have the local
1690 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001691 bool recv = IsReadyToReceive_w();
solenberg5b14b422015-10-01 04:10:31 -07001692 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001693
1694 // Send outgoing data if we're the active call, we have the remote content,
1695 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001696 bool send = IsReadyToSend_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001697 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001698
1699 LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
1700}
1701
1702const ContentInfo* VoiceChannel::GetFirstContent(
1703 const SessionDescription* sdesc) {
1704 return GetFirstAudioContent(sdesc);
1705}
1706
1707bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001708 ContentAction action,
1709 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001710 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001711 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001712 LOG(LS_INFO) << "Setting local voice description";
1713
1714 const AudioContentDescription* audio =
1715 static_cast<const AudioContentDescription*>(content);
1716 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001717 if (!audio) {
1718 SafeSetError("Can't find audio content in local description.", error_desc);
1719 return false;
1720 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001721
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001722 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001723 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001724 }
1725
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001726 AudioRecvParameters recv_params = last_recv_params_;
1727 RtpParametersFromMediaDescription(audio, &recv_params);
1728 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001729 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001730 error_desc);
1731 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001732 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001733 for (const AudioCodec& codec : audio->codecs()) {
1734 bundle_filter()->AddPayloadType(codec.id);
1735 }
1736 last_recv_params_ = recv_params;
1737
1738 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1739 // only give it to the media channel once we have a remote
1740 // description too (without a remote description, we won't be able
1741 // to send them anyway).
1742 if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) {
1743 SafeSetError("Failed to set local audio description streams.", error_desc);
1744 return false;
1745 }
1746
1747 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001748 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001749 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001750}
1751
1752bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001753 ContentAction action,
1754 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001755 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001756 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001757 LOG(LS_INFO) << "Setting remote voice description";
1758
1759 const AudioContentDescription* audio =
1760 static_cast<const AudioContentDescription*>(content);
1761 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001762 if (!audio) {
1763 SafeSetError("Can't find audio content in remote description.", error_desc);
1764 return false;
1765 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001766
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001767 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001768 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001769 }
1770
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001771 AudioSendParameters send_params = last_send_params_;
1772 RtpSendParametersFromMediaDescription(audio, &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001773 if (audio->agc_minus_10db()) {
Karl Wibergbe579832015-11-10 22:34:18 +01001774 send_params.options.adjust_agc_delta = rtc::Optional<int>(kAgcMinus10db);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001775 }
skvladdc1c62c2016-03-16 19:07:43 -07001776
1777 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1778 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001779 SafeSetError("Failed to set remote audio description send parameters.",
1780 error_desc);
1781 return false;
1782 }
1783 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001784
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001785 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1786 // and only give it to the media channel once we have a local
1787 // description too (without a local description, we won't be able to
1788 // recv them anyway).
1789 if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) {
1790 SafeSetError("Failed to set remote audio description streams.", error_desc);
1791 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001792 }
1793
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001794 if (audio->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001795 MaybeCacheRtpAbsSendTimeHeaderExtension_w(audio->rtp_header_extensions());
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001796 }
1797
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001798 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001799 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001800 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001801}
1802
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001803void VoiceChannel::HandleEarlyMediaTimeout() {
1804 // This occurs on the main thread, not the worker thread.
1805 if (!received_media_) {
1806 LOG(LS_INFO) << "No early media received before timeout";
1807 SignalEarlyMediaTimeout(this);
1808 }
1809}
1810
Peter Boström0c4e06b2015-10-07 12:23:21 +02001811bool VoiceChannel::InsertDtmf_w(uint32_t ssrc,
1812 int event,
solenberg1d63dd02015-12-02 12:35:09 -08001813 int duration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001814 if (!enabled()) {
1815 return false;
1816 }
solenberg1d63dd02015-12-02 12:35:09 -08001817 return media_channel()->InsertDtmf(ssrc, event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001818}
1819
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001820void VoiceChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001821 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001822 case MSG_EARLYMEDIATIMEOUT:
1823 HandleEarlyMediaTimeout();
1824 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001825 case MSG_CHANNEL_ERROR: {
1826 VoiceChannelErrorMessageData* data =
1827 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001828 delete data;
1829 break;
1830 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001831 default:
1832 BaseChannel::OnMessage(pmsg);
1833 break;
1834 }
1835}
1836
1837void VoiceChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001838 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001839 SignalConnectionMonitor(this, infos);
1840}
1841
1842void VoiceChannel::OnMediaMonitorUpdate(
1843 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
1844 ASSERT(media_channel == this->media_channel());
1845 SignalMediaMonitor(this, info);
1846}
1847
1848void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1849 const AudioInfo& info) {
1850 SignalAudioMonitor(this, info);
1851}
1852
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001853void VoiceChannel::GetSrtpCryptoSuites_n(
1854 std::vector<int>* crypto_suites) const {
jbauchcb560652016-08-04 05:20:32 -07001855 GetSupportedAudioCryptoSuites(crypto_options(), crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001856}
1857
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001858VideoChannel::VideoChannel(rtc::Thread* worker_thread,
1859 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001860 VideoMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001861 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001862 const std::string& content_name,
Fredrik Solenberg7fb711f2015-04-22 15:30:51 +02001863 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001864 : BaseChannel(worker_thread,
1865 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001866 media_channel,
1867 transport_controller,
1868 content_name,
perkjc11b1842016-03-07 17:34:13 -08001869 rtcp) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001870
skvlad6c87a672016-05-17 17:49:52 -07001871bool VideoChannel::Init_w(const std::string* bundle_transport_name) {
1872 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001873 return false;
1874 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001875 return true;
1876}
1877
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001878VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001879 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001880 StopMediaMonitor();
1881 // this can't be done in the base class, since it calls a virtual
1882 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001883
1884 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001885}
1886
nisse08582ff2016-02-04 01:24:52 -08001887bool VideoChannel::SetSink(uint32_t ssrc,
1888 rtc::VideoSinkInterface<VideoFrame>* sink) {
1889 worker_thread()->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001890 RTC_FROM_HERE,
nisse08582ff2016-02-04 01:24:52 -08001891 Bind(&VideoMediaChannel::SetSink, media_channel(), ssrc, sink));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001892 return true;
1893}
1894
deadbeef5a4a75a2016-06-02 16:23:38 -07001895bool VideoChannel::SetVideoSend(
nisse2ded9b12016-04-08 02:23:55 -07001896 uint32_t ssrc,
deadbeef5a4a75a2016-06-02 16:23:38 -07001897 bool mute,
1898 const VideoOptions* options,
nisse2ded9b12016-04-08 02:23:55 -07001899 rtc::VideoSourceInterface<cricket::VideoFrame>* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001900 return InvokeOnWorker(RTC_FROM_HERE,
1901 Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
deadbeef5a4a75a2016-06-02 16:23:38 -07001902 ssrc, mute, options, source));
solenberg1dd98f32015-09-10 01:57:14 -07001903}
1904
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001905webrtc::RtpParameters VideoChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001906 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001907 RTC_FROM_HERE, Bind(&VideoChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001908}
1909
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001910webrtc::RtpParameters VideoChannel::GetRtpSendParameters_w(
1911 uint32_t ssrc) const {
1912 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001913}
1914
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001915bool VideoChannel::SetRtpSendParameters(
1916 uint32_t ssrc,
1917 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001918 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001919 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001920 Bind(&VideoChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001921}
1922
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001923bool VideoChannel::SetRtpSendParameters_w(uint32_t ssrc,
1924 webrtc::RtpParameters parameters) {
1925 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1926}
1927
1928webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters(
1929 uint32_t ssrc) const {
1930 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001931 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001932 Bind(&VideoChannel::GetRtpReceiveParameters_w, this, ssrc));
1933}
1934
1935webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters_w(
1936 uint32_t ssrc) const {
1937 return media_channel()->GetRtpReceiveParameters(ssrc);
1938}
1939
1940bool VideoChannel::SetRtpReceiveParameters(
1941 uint32_t ssrc,
1942 const webrtc::RtpParameters& parameters) {
1943 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001944 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001945 Bind(&VideoChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1946}
1947
1948bool VideoChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1949 webrtc::RtpParameters parameters) {
1950 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001951}
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001952
1953void VideoChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001954 // Send outgoing data if we're the active call, we have the remote content,
1955 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001956 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001957 if (!media_channel()->SetSend(send)) {
1958 LOG(LS_ERROR) << "Failed to SetSend on video channel";
1959 // TODO(gangji): Report error back to server.
1960 }
1961
Peter Boström34fbfff2015-09-24 19:20:30 +02001962 LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001963}
1964
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00001965bool VideoChannel::GetStats(VideoMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001966 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VideoMediaChannel::GetStats,
1967 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001968}
1969
1970void VideoChannel::StartMediaMonitor(int cms) {
1971 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001972 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001973 media_monitor_->SignalUpdate.connect(
1974 this, &VideoChannel::OnMediaMonitorUpdate);
1975 media_monitor_->Start(cms);
1976}
1977
1978void VideoChannel::StopMediaMonitor() {
1979 if (media_monitor_) {
1980 media_monitor_->Stop();
1981 media_monitor_.reset();
1982 }
1983}
1984
1985const ContentInfo* VideoChannel::GetFirstContent(
1986 const SessionDescription* sdesc) {
1987 return GetFirstVideoContent(sdesc);
1988}
1989
1990bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001991 ContentAction action,
1992 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001993 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001994 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001995 LOG(LS_INFO) << "Setting local video description";
1996
1997 const VideoContentDescription* video =
1998 static_cast<const VideoContentDescription*>(content);
1999 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002000 if (!video) {
2001 SafeSetError("Can't find video content in local description.", error_desc);
2002 return false;
2003 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002004
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002005 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002006 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002007 }
2008
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002009 VideoRecvParameters recv_params = last_recv_params_;
2010 RtpParametersFromMediaDescription(video, &recv_params);
2011 if (!media_channel()->SetRecvParameters(recv_params)) {
2012 SafeSetError("Failed to set local video description recv parameters.",
2013 error_desc);
2014 return false;
2015 }
2016 for (const VideoCodec& codec : video->codecs()) {
2017 bundle_filter()->AddPayloadType(codec.id);
2018 }
2019 last_recv_params_ = recv_params;
2020
2021 // TODO(pthatcher): Move local streams into VideoSendParameters, and
2022 // only give it to the media channel once we have a remote
2023 // description too (without a remote description, we won't be able
2024 // to send them anyway).
2025 if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) {
2026 SafeSetError("Failed to set local video description streams.", error_desc);
2027 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002028 }
2029
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002030 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002031 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002032 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002033}
2034
2035bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002036 ContentAction action,
2037 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002038 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002039 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002040 LOG(LS_INFO) << "Setting remote video description";
2041
2042 const VideoContentDescription* video =
2043 static_cast<const VideoContentDescription*>(content);
2044 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002045 if (!video) {
2046 SafeSetError("Can't find video content in remote description.", error_desc);
2047 return false;
2048 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002049
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002050 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002051 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002052 }
2053
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002054 VideoSendParameters send_params = last_send_params_;
2055 RtpSendParametersFromMediaDescription(video, &send_params);
2056 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08002057 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002058 }
skvladdc1c62c2016-03-16 19:07:43 -07002059
2060 bool parameters_applied = media_channel()->SetSendParameters(send_params);
2061
2062 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002063 SafeSetError("Failed to set remote video description send parameters.",
2064 error_desc);
2065 return false;
2066 }
2067 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002068
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002069 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
2070 // and only give it to the media channel once we have a local
2071 // description too (without a local description, we won't be able to
2072 // recv them anyway).
2073 if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) {
2074 SafeSetError("Failed to set remote video description streams.", error_desc);
2075 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002076 }
2077
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002078 if (video->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002079 MaybeCacheRtpAbsSendTimeHeaderExtension_w(video->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002080 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002081
2082 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002083 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002084 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002085}
2086
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002087void VideoChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002088 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002089 case MSG_CHANNEL_ERROR: {
2090 const VideoChannelErrorMessageData* data =
2091 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002092 delete data;
2093 break;
2094 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002095 default:
2096 BaseChannel::OnMessage(pmsg);
2097 break;
2098 }
2099}
2100
2101void VideoChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002102 ConnectionMonitor* monitor, const std::vector<ConnectionInfo> &infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002103 SignalConnectionMonitor(this, infos);
2104}
2105
2106// TODO(pthatcher): Look into removing duplicate code between
2107// audio, video, and data, perhaps by using templates.
2108void VideoChannel::OnMediaMonitorUpdate(
2109 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
2110 ASSERT(media_channel == this->media_channel());
2111 SignalMediaMonitor(this, info);
2112}
2113
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002114void VideoChannel::GetSrtpCryptoSuites_n(
2115 std::vector<int>* crypto_suites) const {
jbauchcb560652016-08-04 05:20:32 -07002116 GetSupportedVideoCryptoSuites(crypto_options(), crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002117}
2118
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002119DataChannel::DataChannel(rtc::Thread* worker_thread,
2120 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002121 DataMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07002122 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002123 const std::string& content_name,
2124 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002125 : BaseChannel(worker_thread,
2126 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07002127 media_channel,
2128 transport_controller,
2129 content_name,
2130 rtcp),
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002131 data_channel_type_(cricket::DCT_NONE),
deadbeefcbecd352015-09-23 11:50:27 -07002132 ready_to_send_data_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002133
2134DataChannel::~DataChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08002135 TRACE_EVENT0("webrtc", "DataChannel::~DataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002136 StopMediaMonitor();
2137 // this can't be done in the base class, since it calls a virtual
2138 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00002139
2140 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002141}
2142
skvlad6c87a672016-05-17 17:49:52 -07002143bool DataChannel::Init_w(const std::string* bundle_transport_name) {
2144 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002145 return false;
2146 }
2147 media_channel()->SignalDataReceived.connect(
2148 this, &DataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002149 media_channel()->SignalReadyToSend.connect(
2150 this, &DataChannel::OnDataChannelReadyToSend);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002151 media_channel()->SignalStreamClosedRemotely.connect(
2152 this, &DataChannel::OnStreamClosedRemotely);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002153 return true;
2154}
2155
2156bool DataChannel::SendData(const SendDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -07002157 const rtc::CopyOnWriteBuffer& payload,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002158 SendDataResult* result) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002159 return InvokeOnWorker(
2160 RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params,
2161 payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002162}
2163
2164const ContentInfo* DataChannel::GetFirstContent(
2165 const SessionDescription* sdesc) {
2166 return GetFirstDataContent(sdesc);
2167}
2168
jbaucheec21bd2016-03-20 06:15:43 -07002169bool DataChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002170 if (data_channel_type_ == DCT_SCTP) {
2171 // TODO(pthatcher): Do this in a more robust way by checking for
2172 // SCTP or DTLS.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +00002173 return !IsRtpPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002174 } else if (data_channel_type_ == DCT_RTP) {
2175 return BaseChannel::WantsPacket(rtcp, packet);
2176 }
2177 return false;
2178}
2179
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002180bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
2181 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002182 // It hasn't been set before, so set it now.
2183 if (data_channel_type_ == DCT_NONE) {
2184 data_channel_type_ = new_data_channel_type;
2185 return true;
2186 }
2187
2188 // It's been set before, but doesn't match. That's bad.
2189 if (data_channel_type_ != new_data_channel_type) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002190 std::ostringstream desc;
2191 desc << "Data channel type mismatch."
2192 << " Expected " << data_channel_type_
2193 << " Got " << new_data_channel_type;
2194 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002195 return false;
2196 }
2197
2198 // It's hasn't changed. Nothing to do.
2199 return true;
2200}
2201
2202bool DataChannel::SetDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002203 const DataContentDescription* content,
2204 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002205 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
2206 (content->protocol() == kMediaProtocolDtlsSctp));
2207 DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002208 return SetDataChannelType(data_channel_type, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002209}
2210
2211bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002212 ContentAction action,
2213 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002214 TRACE_EVENT0("webrtc", "DataChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002215 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002216 LOG(LS_INFO) << "Setting local data description";
2217
2218 const DataContentDescription* data =
2219 static_cast<const DataContentDescription*>(content);
2220 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002221 if (!data) {
2222 SafeSetError("Can't find data content in local description.", error_desc);
2223 return false;
2224 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002225
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002226 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002227 return false;
2228 }
2229
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002230 if (data_channel_type_ == DCT_RTP) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002231 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002232 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002233 }
2234 }
2235
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002236 // FYI: We send the SCTP port number (not to be confused with the
2237 // underlying UDP port number) as a codec parameter. So even SCTP
2238 // data channels need codecs.
2239 DataRecvParameters recv_params = last_recv_params_;
2240 RtpParametersFromMediaDescription(data, &recv_params);
2241 if (!media_channel()->SetRecvParameters(recv_params)) {
2242 SafeSetError("Failed to set remote data description recv parameters.",
2243 error_desc);
2244 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002245 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002246 if (data_channel_type_ == DCT_RTP) {
2247 for (const DataCodec& codec : data->codecs()) {
2248 bundle_filter()->AddPayloadType(codec.id);
2249 }
2250 }
2251 last_recv_params_ = recv_params;
2252
2253 // TODO(pthatcher): Move local streams into DataSendParameters, and
2254 // only give it to the media channel once we have a remote
2255 // description too (without a remote description, we won't be able
2256 // to send them anyway).
2257 if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) {
2258 SafeSetError("Failed to set local data description streams.", error_desc);
2259 return false;
2260 }
2261
2262 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002263 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002264 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002265}
2266
2267bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002268 ContentAction action,
2269 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002270 TRACE_EVENT0("webrtc", "DataChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002271 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002272
2273 const DataContentDescription* data =
2274 static_cast<const DataContentDescription*>(content);
2275 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002276 if (!data) {
2277 SafeSetError("Can't find data content in remote description.", error_desc);
2278 return false;
2279 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002280
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002281 // If the remote data doesn't have codecs and isn't an update, it
2282 // must be empty, so ignore it.
2283 if (!data->has_codecs() && action != CA_UPDATE) {
2284 return true;
2285 }
2286
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002287 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002288 return false;
2289 }
2290
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002291 LOG(LS_INFO) << "Setting remote data description";
2292 if (data_channel_type_ == DCT_RTP &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002293 !SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002294 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002295 }
2296
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002297
2298 DataSendParameters send_params = last_send_params_;
2299 RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params);
2300 if (!media_channel()->SetSendParameters(send_params)) {
2301 SafeSetError("Failed to set remote data description send parameters.",
2302 error_desc);
2303 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002304 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002305 last_send_params_ = send_params;
2306
2307 // TODO(pthatcher): Move remote streams into DataRecvParameters,
2308 // and only give it to the media channel once we have a local
2309 // description too (without a local description, we won't be able to
2310 // recv them anyway).
2311 if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) {
2312 SafeSetError("Failed to set remote data description streams.",
2313 error_desc);
2314 return false;
2315 }
2316
2317 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002318 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002319 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002320}
2321
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002322void DataChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002323 // Render incoming data if we're the active call, and we have the local
2324 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002325 bool recv = IsReadyToReceive_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002326 if (!media_channel()->SetReceive(recv)) {
2327 LOG(LS_ERROR) << "Failed to SetReceive on data channel";
2328 }
2329
2330 // Send outgoing data if we're the active call, we have the remote content,
2331 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002332 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002333 if (!media_channel()->SetSend(send)) {
2334 LOG(LS_ERROR) << "Failed to SetSend on data channel";
2335 }
2336
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002337 // Trigger SignalReadyToSendData asynchronously.
2338 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002339
2340 LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
2341}
2342
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002343void DataChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002344 switch (pmsg->message_id) {
2345 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002346 DataChannelReadyToSendMessageData* data =
2347 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002348 ready_to_send_data_ = data->data();
2349 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002350 delete data;
2351 break;
2352 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002353 case MSG_DATARECEIVED: {
2354 DataReceivedMessageData* data =
2355 static_cast<DataReceivedMessageData*>(pmsg->pdata);
2356 SignalDataReceived(this, data->params, data->payload);
2357 delete data;
2358 break;
2359 }
2360 case MSG_CHANNEL_ERROR: {
2361 const DataChannelErrorMessageData* data =
2362 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002363 delete data;
2364 break;
2365 }
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002366 case MSG_STREAMCLOSEDREMOTELY: {
Peter Boström0c4e06b2015-10-07 12:23:21 +02002367 rtc::TypedMessageData<uint32_t>* data =
2368 static_cast<rtc::TypedMessageData<uint32_t>*>(pmsg->pdata);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002369 SignalStreamClosedRemotely(data->data());
2370 delete data;
2371 break;
2372 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002373 default:
2374 BaseChannel::OnMessage(pmsg);
2375 break;
2376 }
2377}
2378
2379void DataChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002380 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002381 SignalConnectionMonitor(this, infos);
2382}
2383
2384void DataChannel::StartMediaMonitor(int cms) {
2385 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002386 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002387 media_monitor_->SignalUpdate.connect(
2388 this, &DataChannel::OnMediaMonitorUpdate);
2389 media_monitor_->Start(cms);
2390}
2391
2392void DataChannel::StopMediaMonitor() {
2393 if (media_monitor_) {
2394 media_monitor_->Stop();
2395 media_monitor_->SignalUpdate.disconnect(this);
2396 media_monitor_.reset();
2397 }
2398}
2399
2400void DataChannel::OnMediaMonitorUpdate(
2401 DataMediaChannel* media_channel, const DataMediaInfo& info) {
2402 ASSERT(media_channel == this->media_channel());
2403 SignalMediaMonitor(this, info);
2404}
2405
2406void DataChannel::OnDataReceived(
2407 const ReceiveDataParams& params, const char* data, size_t len) {
2408 DataReceivedMessageData* msg = new DataReceivedMessageData(
2409 params, data, len);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002410 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002411}
2412
Peter Boström0c4e06b2015-10-07 12:23:21 +02002413void DataChannel::OnDataChannelError(uint32_t ssrc,
2414 DataMediaChannel::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002415 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2416 ssrc, err);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002417 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_CHANNEL_ERROR, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002418}
2419
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002420void DataChannel::OnDataChannelReadyToSend(bool writable) {
2421 // This is usded for congestion control to indicate that the stream is ready
2422 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2423 // that the transport channel is ready.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002424 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002425 new DataChannelReadyToSendMessageData(writable));
2426}
2427
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002428void DataChannel::GetSrtpCryptoSuites_n(std::vector<int>* crypto_suites) const {
jbauchcb560652016-08-04 05:20:32 -07002429 GetSupportedDataCryptoSuites(crypto_options(), crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002430}
2431
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002432bool DataChannel::ShouldSetupDtlsSrtp_n() const {
2433 return data_channel_type_ == DCT_RTP && BaseChannel::ShouldSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002434}
2435
Peter Boström0c4e06b2015-10-07 12:23:21 +02002436void DataChannel::OnStreamClosedRemotely(uint32_t sid) {
2437 rtc::TypedMessageData<uint32_t>* message =
2438 new rtc::TypedMessageData<uint32_t>(sid);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002439 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_STREAMCLOSEDREMOTELY,
2440 message);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002441}
2442
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002443} // namespace cricket