blob: 6f980e1223a3e146a27f2a62c5e3d54de1065c76 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander65c7f672016-02-12 00:05:01 -08002 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander65c7f672016-02-12 00:05:01 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
kwiberg0eb15ed2015-12-17 03:04:15 -080011#include <utility>
12
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010013#include "webrtc/pc/channel.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014
kjellander@webrtc.org7ffeab52016-02-26 22:46:09 +010015#include "webrtc/audio_sink.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000016#include "webrtc/base/bind.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000017#include "webrtc/base/byteorder.h"
18#include "webrtc/base/common.h"
jbaucheec21bd2016-03-20 06:15:43 -070019#include "webrtc/base/copyonwritebuffer.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000020#include "webrtc/base/dscp.h"
21#include "webrtc/base/logging.h"
Honghai Zhangcc411c02016-03-29 17:27:21 -070022#include "webrtc/base/networkroute.h"
Peter Boström6f28cf02015-12-07 23:17:15 +010023#include "webrtc/base/trace_event.h"
kjellanderf4752772016-03-02 05:42:30 -080024#include "webrtc/media/base/mediaconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080025#include "webrtc/media/base/rtputils.h"
Peter Boström6f28cf02015-12-07 23:17:15 +010026#include "webrtc/p2p/base/transportchannel.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010027#include "webrtc/pc/channelmanager.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000028
29namespace cricket {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000030using rtc::Bind;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000031
deadbeef2d110be2016-01-13 12:00:26 -080032namespace {
kwiberg31022942016-03-11 14:18:21 -080033// See comment below for why we need to use a pointer to a unique_ptr.
deadbeef2d110be2016-01-13 12:00:26 -080034bool SetRawAudioSink_w(VoiceMediaChannel* channel,
35 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -080036 std::unique_ptr<webrtc::AudioSinkInterface>* sink) {
37 channel->SetRawAudioSink(ssrc, std::move(*sink));
deadbeef2d110be2016-01-13 12:00:26 -080038 return true;
39}
Danil Chapovalov33b01f22016-05-11 19:55:27 +020040
41struct SendPacketMessageData : public rtc::MessageData {
42 rtc::CopyOnWriteBuffer packet;
43 rtc::PacketOptions options;
44};
45
isheriff6f8d6862016-05-26 11:24:55 -070046#if defined(ENABLE_EXTERNAL_AUTH)
47// Returns the named header extension if found among all extensions,
48// nullptr otherwise.
49const webrtc::RtpExtension* FindHeaderExtension(
50 const std::vector<webrtc::RtpExtension>& extensions,
51 const std::string& uri) {
52 for (const auto& extension : extensions) {
53 if (extension.uri == uri)
54 return &extension;
55 }
56 return nullptr;
57}
58#endif
59
deadbeef2d110be2016-01-13 12:00:26 -080060} // namespace
61
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062enum {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000063 MSG_EARLYMEDIATIMEOUT = 1,
Danil Chapovalov33b01f22016-05-11 19:55:27 +020064 MSG_SEND_RTP_PACKET,
65 MSG_SEND_RTCP_PACKET,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066 MSG_CHANNEL_ERROR,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000069 MSG_FIRSTPACKETRECEIVED,
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +000070 MSG_STREAMCLOSEDREMOTELY,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000071};
72
73// Value specified in RFC 5764.
74static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
75
76static const int kAgcMinus10db = -10;
77
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000078static void SafeSetError(const std::string& message, std::string* error_desc) {
79 if (error_desc) {
80 *error_desc = message;
81 }
82}
83
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000084struct VoiceChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020085 VoiceChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086 VoiceMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020087 : ssrc(in_ssrc), error(in_error) {}
88 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089 VoiceMediaChannel::Error error;
90};
91
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000092struct VideoChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020093 VideoChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094 VideoMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020095 : ssrc(in_ssrc), error(in_error) {}
96 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097 VideoMediaChannel::Error error;
98};
99
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000100struct DataChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200101 DataChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102 DataMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +0200103 : ssrc(in_ssrc), error(in_error) {}
104 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000105 DataMediaChannel::Error error;
106};
107
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108static const char* PacketType(bool rtcp) {
109 return (!rtcp) ? "RTP" : "RTCP";
110}
111
jbaucheec21bd2016-03-20 06:15:43 -0700112static bool ValidPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113 // Check the packet size. We could check the header too if needed.
114 return (packet &&
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000115 packet->size() >= (!rtcp ? kMinRtpPacketLen : kMinRtcpPacketLen) &&
116 packet->size() <= kMaxRtpPacketLen);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000117}
118
119static bool IsReceiveContentDirection(MediaContentDirection direction) {
120 return direction == MD_SENDRECV || direction == MD_RECVONLY;
121}
122
123static bool IsSendContentDirection(MediaContentDirection direction) {
124 return direction == MD_SENDRECV || direction == MD_SENDONLY;
125}
126
127static const MediaContentDescription* GetContentDescription(
128 const ContentInfo* cinfo) {
129 if (cinfo == NULL)
130 return NULL;
131 return static_cast<const MediaContentDescription*>(cinfo->description);
132}
133
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700134template <class Codec>
135void RtpParametersFromMediaDescription(
136 const MediaContentDescriptionImpl<Codec>* desc,
137 RtpParameters<Codec>* params) {
138 // TODO(pthatcher): Remove this once we're sure no one will give us
139 // a description without codecs (currently a CA_UPDATE with just
140 // streams can).
141 if (desc->has_codecs()) {
142 params->codecs = desc->codecs();
143 }
144 // TODO(pthatcher): See if we really need
145 // rtp_header_extensions_set() and remove it if we don't.
146 if (desc->rtp_header_extensions_set()) {
147 params->extensions = desc->rtp_header_extensions();
148 }
deadbeef13871492015-12-09 12:37:51 -0800149 params->rtcp.reduced_size = desc->rtcp_reduced_size();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700150}
151
nisse05103312016-03-16 02:22:50 -0700152template <class Codec>
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700153void RtpSendParametersFromMediaDescription(
154 const MediaContentDescriptionImpl<Codec>* desc,
nisse05103312016-03-16 02:22:50 -0700155 RtpSendParameters<Codec>* send_params) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700156 RtpParametersFromMediaDescription(desc, send_params);
157 send_params->max_bandwidth_bps = desc->bandwidth();
158}
159
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200160BaseChannel::BaseChannel(rtc::Thread* worker_thread,
161 rtc::Thread* network_thread,
deadbeefcbecd352015-09-23 11:50:27 -0700162 MediaChannel* media_channel,
163 TransportController* transport_controller,
164 const std::string& content_name,
165 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200166 : worker_thread_(worker_thread),
167 network_thread_(network_thread),
168
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000169 content_name_(content_name),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200170
171 transport_controller_(transport_controller),
deadbeefcbecd352015-09-23 11:50:27 -0700172 rtcp_transport_enabled_(rtcp),
173 transport_channel_(nullptr),
174 rtcp_transport_channel_(nullptr),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000175 rtp_ready_to_send_(false),
176 rtcp_ready_to_send_(false),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200177 writable_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000178 was_ever_writable_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000179 has_received_packet_(false),
180 dtls_keyed_(false),
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000181 secure_required_(false),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200182 rtp_abs_sendtime_extn_id_(-1),
183
184 media_channel_(media_channel),
185 enabled_(false),
186 local_content_direction_(MD_INACTIVE),
187 remote_content_direction_(MD_INACTIVE) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000188 ASSERT(worker_thread_ == rtc::Thread::Current());
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200189 if (transport_controller) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200190 RTC_DCHECK_EQ(network_thread, transport_controller->network_thread());
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200191 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000192 LOG(LS_INFO) << "Created channel for " << content_name;
193}
194
195BaseChannel::~BaseChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800196 TRACE_EVENT0("webrtc", "BaseChannel::~BaseChannel");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000197 ASSERT(worker_thread_ == rtc::Thread::Current());
wu@webrtc.org78187522013-10-07 23:32:02 +0000198 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000199 StopConnectionMonitor();
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200200 // Eats any outstanding messages or packets.
201 worker_thread_->Clear(&invoker_);
202 worker_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000203 // We must destroy the media channel before the transport channel, otherwise
204 // the media channel may try to send on the dead transport channel. NULLing
205 // is not an effective strategy since the sends will come on another thread.
206 delete media_channel_;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200207 // Note that we don't just call SetTransportChannel_n(nullptr) because that
deadbeefcbecd352015-09-23 11:50:27 -0700208 // would call a pure virtual method which we can't do from a destructor.
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200209 network_thread_->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700210 RTC_FROM_HERE, Bind(&BaseChannel::DestroyTransportChannels_n, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200211 LOG(LS_INFO) << "Destroyed channel";
212}
213
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200214void BaseChannel::DisconnectTransportChannels_n() {
215 // Send any outstanding RTCP packets.
216 FlushRtcpMessages_n();
217
218 // Stop signals from transport channels, but keep them alive because
219 // media_channel may use them from a different thread.
deadbeefcbecd352015-09-23 11:50:27 -0700220 if (transport_channel_) {
221 DisconnectFromTransportChannel(transport_channel_);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200222 }
223 if (rtcp_transport_channel_) {
224 DisconnectFromTransportChannel(rtcp_transport_channel_);
225 }
226
227 // Clear pending read packets/messages.
228 network_thread_->Clear(&invoker_);
229 network_thread_->Clear(this);
230}
231
232void BaseChannel::DestroyTransportChannels_n() {
233 if (transport_channel_) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200234 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700235 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
236 }
237 if (rtcp_transport_channel_) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200238 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700239 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
240 }
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200241 // Clear pending send packets/messages.
242 network_thread_->Clear(&invoker_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200243 network_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000244}
245
skvlad6c87a672016-05-17 17:49:52 -0700246bool BaseChannel::Init_w(const std::string* bundle_transport_name) {
247 if (!network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700248 RTC_FROM_HERE,
skvlad6c87a672016-05-17 17:49:52 -0700249 Bind(&BaseChannel::InitNetwork_n, this, bundle_transport_name))) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000250 return false;
251 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000252
wu@webrtc.orgde305012013-10-31 15:40:38 +0000253 // Both RTP and RTCP channels are set, we can call SetInterface on
254 // media channel and it can set network options.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200255 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.orgde305012013-10-31 15:40:38 +0000256 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000257 return true;
258}
259
skvlad6c87a672016-05-17 17:49:52 -0700260bool BaseChannel::InitNetwork_n(const std::string* bundle_transport_name) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200261 RTC_DCHECK(network_thread_->IsCurrent());
skvlad6c87a672016-05-17 17:49:52 -0700262 const std::string& transport_name =
263 (bundle_transport_name ? *bundle_transport_name : content_name());
264 if (!SetTransport_n(transport_name)) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200265 return false;
266 }
267
268 if (!SetDtlsSrtpCryptoSuites_n(transport_channel_, false)) {
269 return false;
270 }
271 if (rtcp_transport_enabled() &&
272 !SetDtlsSrtpCryptoSuites_n(rtcp_transport_channel_, true)) {
273 return false;
274 }
275 return true;
276}
277
wu@webrtc.org78187522013-10-07 23:32:02 +0000278void BaseChannel::Deinit() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200279 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.org78187522013-10-07 23:32:02 +0000280 media_channel_->SetInterface(NULL);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200281 // Packets arrive on the network thread, processing packets calls virtual
282 // functions, so need to stop this process in Deinit that is called in
283 // derived classes destructor.
284 network_thread_->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700285 RTC_FROM_HERE, Bind(&BaseChannel::DisconnectTransportChannels_n, this));
wu@webrtc.org78187522013-10-07 23:32:02 +0000286}
287
deadbeefcbecd352015-09-23 11:50:27 -0700288bool BaseChannel::SetTransport(const std::string& transport_name) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200289 return network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700290 RTC_FROM_HERE, Bind(&BaseChannel::SetTransport_n, this, transport_name));
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000291}
292
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200293bool BaseChannel::SetTransport_n(const std::string& transport_name) {
294 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000295
deadbeefcbecd352015-09-23 11:50:27 -0700296 if (transport_name == transport_name_) {
297 // Nothing to do if transport name isn't changing
298 return true;
299 }
300
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800301 // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport
302 // changes and wait until the DTLS handshake is complete to set the newly
303 // negotiated parameters.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200304 if (ShouldSetupDtlsSrtp_n()) {
guoweis46383312015-12-17 16:45:59 -0800305 // Set |writable_| to false such that UpdateWritableState_w can set up
306 // DTLS-SRTP when the writable_ becomes true again.
307 writable_ = false;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800308 srtp_filter_.ResetParams();
309 }
310
guoweis46383312015-12-17 16:45:59 -0800311 // TODO(guoweis): Remove this grossness when we remove non-muxed RTCP.
deadbeefcbecd352015-09-23 11:50:27 -0700312 if (rtcp_transport_enabled()) {
313 LOG(LS_INFO) << "Create RTCP TransportChannel for " << content_name()
314 << " on " << transport_name << " transport ";
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200315 SetRtcpTransportChannel_n(
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200316 transport_controller_->CreateTransportChannel_n(
guoweis46383312015-12-17 16:45:59 -0800317 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP),
318 false /* update_writablity */);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200319 if (!rtcp_transport_channel_) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000320 return false;
321 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000322 }
323
guoweis46383312015-12-17 16:45:59 -0800324 // We're not updating the writablity during the transition state.
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200325 SetTransportChannel_n(transport_controller_->CreateTransportChannel_n(
guoweis46383312015-12-17 16:45:59 -0800326 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200327 if (!transport_channel_) {
guoweis46383312015-12-17 16:45:59 -0800328 return false;
329 }
330
331 // TODO(guoweis): Remove this grossness when we remove non-muxed RTCP.
332 if (rtcp_transport_enabled()) {
333 // We can only update the RTCP ready to send after set_transport_channel has
334 // handled channel writability.
335 SetReadyToSend(
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200336 true, rtcp_transport_channel_ && rtcp_transport_channel_->writable());
guoweis46383312015-12-17 16:45:59 -0800337 }
deadbeefcbecd352015-09-23 11:50:27 -0700338 transport_name_ = transport_name;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000339 return true;
340}
341
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200342void BaseChannel::SetTransportChannel_n(TransportChannel* new_tc) {
343 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000344
345 TransportChannel* old_tc = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700346 if (!old_tc && !new_tc) {
347 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000348 return;
349 }
deadbeefcbecd352015-09-23 11:50:27 -0700350 ASSERT(old_tc != new_tc);
351
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000352 if (old_tc) {
353 DisconnectFromTransportChannel(old_tc);
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200354 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700355 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000356 }
357
358 transport_channel_ = new_tc;
359
360 if (new_tc) {
361 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700362 for (const auto& pair : socket_options_) {
363 new_tc->SetOption(pair.first, pair.second);
364 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000365 }
deadbeefcbecd352015-09-23 11:50:27 -0700366
367 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
368 // setting new channel
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200369 UpdateWritableState_n();
deadbeefcbecd352015-09-23 11:50:27 -0700370 SetReadyToSend(false, new_tc && new_tc->writable());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000371}
372
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200373void BaseChannel::SetRtcpTransportChannel_n(TransportChannel* new_tc,
374 bool update_writablity) {
375 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000376
377 TransportChannel* old_tc = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700378 if (!old_tc && !new_tc) {
379 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000380 return;
381 }
deadbeefcbecd352015-09-23 11:50:27 -0700382 ASSERT(old_tc != new_tc);
383
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000384 if (old_tc) {
385 DisconnectFromTransportChannel(old_tc);
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200386 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700387 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000388 }
389
390 rtcp_transport_channel_ = new_tc;
391
392 if (new_tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200393 RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_filter_.IsActive()))
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800394 << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
395 << "should never happen.";
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000396 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700397 for (const auto& pair : rtcp_socket_options_) {
398 new_tc->SetOption(pair.first, pair.second);
399 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000400 }
deadbeefcbecd352015-09-23 11:50:27 -0700401
guoweis46383312015-12-17 16:45:59 -0800402 if (update_writablity) {
403 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
404 // setting new channel
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200405 UpdateWritableState_n();
guoweis46383312015-12-17 16:45:59 -0800406 SetReadyToSend(true, new_tc && new_tc->writable());
407 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000408}
409
410void BaseChannel::ConnectToTransportChannel(TransportChannel* tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200411 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000412
413 tc->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
414 tc->SignalReadPacket.connect(this, &BaseChannel::OnChannelRead);
415 tc->SignalReadyToSend.connect(this, &BaseChannel::OnReadyToSend);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800416 tc->SignalDtlsState.connect(this, &BaseChannel::OnDtlsState);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700417 tc->SignalSelectedCandidatePairChanged.connect(
418 this, &BaseChannel::OnSelectedCandidatePairChanged);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200419 tc->SignalSentPacket.connect(this, &BaseChannel::SignalSentPacket_n);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000420}
421
422void BaseChannel::DisconnectFromTransportChannel(TransportChannel* tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200423 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000424
425 tc->SignalWritableState.disconnect(this);
426 tc->SignalReadPacket.disconnect(this);
427 tc->SignalReadyToSend.disconnect(this);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800428 tc->SignalDtlsState.disconnect(this);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200429 tc->SignalSelectedCandidatePairChanged.disconnect(this);
430 tc->SignalSentPacket.disconnect(this);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000431}
432
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000433bool BaseChannel::Enable(bool enable) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700434 worker_thread_->Invoke<void>(
435 RTC_FROM_HERE,
436 Bind(enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
437 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000438 return true;
439}
440
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000441bool BaseChannel::AddRecvStream(const StreamParams& sp) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700442 return InvokeOnWorker(RTC_FROM_HERE,
443 Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000444}
445
Peter Boström0c4e06b2015-10-07 12:23:21 +0200446bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700447 return InvokeOnWorker(RTC_FROM_HERE,
448 Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000449}
450
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000451bool BaseChannel::AddSendStream(const StreamParams& sp) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000452 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700453 RTC_FROM_HERE, Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000454}
455
Peter Boström0c4e06b2015-10-07 12:23:21 +0200456bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700457 return InvokeOnWorker(RTC_FROM_HERE, Bind(&MediaChannel::RemoveSendStream,
458 media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000459}
460
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000461bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000462 ContentAction action,
463 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100464 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700465 return InvokeOnWorker(RTC_FROM_HERE, Bind(&BaseChannel::SetLocalContent_w,
466 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000467}
468
469bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000470 ContentAction action,
471 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100472 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700473 return InvokeOnWorker(RTC_FROM_HERE, Bind(&BaseChannel::SetRemoteContent_w,
474 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000475}
476
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000477void BaseChannel::StartConnectionMonitor(int cms) {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000478 // We pass in the BaseChannel instead of the transport_channel_
479 // because if the transport_channel_ changes, the ConnectionMonitor
480 // would be pointing to the wrong TransportChannel.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200481 // We pass in the network thread because on that thread connection monitor
482 // will call BaseChannel::GetConnectionStats which must be called on the
483 // network thread.
484 connection_monitor_.reset(
485 new ConnectionMonitor(this, network_thread(), rtc::Thread::Current()));
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000486 connection_monitor_->SignalUpdate.connect(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000487 this, &BaseChannel::OnConnectionMonitorUpdate);
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000488 connection_monitor_->Start(cms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000489}
490
491void BaseChannel::StopConnectionMonitor() {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000492 if (connection_monitor_) {
493 connection_monitor_->Stop();
494 connection_monitor_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000495 }
496}
497
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000498bool BaseChannel::GetConnectionStats(ConnectionInfos* infos) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200499 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000500 return transport_channel_->GetStats(infos);
501}
502
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200503bool BaseChannel::IsReadyToReceive_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000504 // Receive data if we are enabled and have local content,
505 return enabled() && IsReceiveContentDirection(local_content_direction_);
506}
507
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200508bool BaseChannel::IsReadyToSend_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000509 // Send outgoing data if we are enabled, have local and remote content,
510 // and we have had some form of connectivity.
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800511 return enabled() && IsReceiveContentDirection(remote_content_direction_) &&
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000512 IsSendContentDirection(local_content_direction_) &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200513 network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700514 RTC_FROM_HERE, Bind(&BaseChannel::IsTransportReadyToSend_n, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200515}
516
517bool BaseChannel::IsTransportReadyToSend_n() const {
518 return was_ever_writable() &&
519 (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp_n());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000520}
521
jbaucheec21bd2016-03-20 06:15:43 -0700522bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700523 const rtc::PacketOptions& options) {
524 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000525}
526
jbaucheec21bd2016-03-20 06:15:43 -0700527bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700528 const rtc::PacketOptions& options) {
529 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530}
531
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000532int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000533 int value) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200534 return network_thread_->Invoke<int>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700535 RTC_FROM_HERE, Bind(&BaseChannel::SetOption_n, this, type, opt, value));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200536}
537
538int BaseChannel::SetOption_n(SocketType type,
539 rtc::Socket::Option opt,
540 int value) {
541 RTC_DCHECK(network_thread_->IsCurrent());
542 TransportChannel* channel = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000543 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000544 case ST_RTP:
545 channel = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700546 socket_options_.push_back(
547 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000548 break;
549 case ST_RTCP:
550 channel = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700551 rtcp_socket_options_.push_back(
552 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000553 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000554 }
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000555 return channel ? channel->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000556}
557
558void BaseChannel::OnWritableState(TransportChannel* channel) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200559 RTC_DCHECK(channel == transport_channel_ ||
560 channel == rtcp_transport_channel_);
561 RTC_DCHECK(network_thread_->IsCurrent());
562 UpdateWritableState_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000563}
564
565void BaseChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000566 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000567 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000568 int flags) {
Peter Boström6f28cf02015-12-07 23:17:15 +0100569 TRACE_EVENT0("webrtc", "BaseChannel::OnChannelRead");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000570 // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200571 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000572
573 // When using RTCP multiplexing we might get RTCP packets on the RTP
574 // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
575 bool rtcp = PacketIsRtcp(channel, data, len);
jbaucheec21bd2016-03-20 06:15:43 -0700576 rtc::CopyOnWriteBuffer packet(data, len);
wu@webrtc.orga9890802013-12-13 00:21:03 +0000577 HandlePacket(rtcp, &packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000578}
579
580void BaseChannel::OnReadyToSend(TransportChannel* channel) {
deadbeefcbecd352015-09-23 11:50:27 -0700581 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
582 SetReadyToSend(channel == rtcp_transport_channel_, true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000583}
584
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800585void BaseChannel::OnDtlsState(TransportChannel* channel,
586 DtlsTransportState state) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200587 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800588 return;
589 }
590
591 // Reset the srtp filter if it's not the CONNECTED state. For the CONNECTED
592 // state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to
593 // cover other scenarios like the whole channel is writable (not just this
594 // TransportChannel) or when TransportChannel is attached after DTLS is
595 // negotiated.
596 if (state != DTLS_TRANSPORT_CONNECTED) {
597 srtp_filter_.ResetParams();
598 }
599}
600
Honghai Zhangcc411c02016-03-29 17:27:21 -0700601void BaseChannel::OnSelectedCandidatePairChanged(
602 TransportChannel* channel,
Honghai Zhang52dce732016-03-31 12:37:31 -0700603 CandidatePairInterface* selected_candidate_pair,
604 int last_sent_packet_id) {
Honghai Zhangcc411c02016-03-29 17:27:21 -0700605 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200606 RTC_DCHECK(network_thread_->IsCurrent());
607 std::string transport_name = channel->transport_name();
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700608 rtc::NetworkRoute network_route;
Honghai Zhangcc411c02016-03-29 17:27:21 -0700609 if (selected_candidate_pair) {
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700610 network_route = rtc::NetworkRoute(
611 selected_candidate_pair->local_candidate().network_id(),
612 selected_candidate_pair->remote_candidate().network_id(),
613 last_sent_packet_id);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700614 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200615 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700616 RTC_FROM_HERE, worker_thread_,
617 Bind(&MediaChannel::OnNetworkRouteChanged, media_channel_, transport_name,
618 network_route));
Honghai Zhangcc411c02016-03-29 17:27:21 -0700619}
620
deadbeefcbecd352015-09-23 11:50:27 -0700621void BaseChannel::SetReadyToSend(bool rtcp, bool ready) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200622 RTC_DCHECK(network_thread_->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -0700623 if (rtcp) {
624 rtcp_ready_to_send_ = ready;
625 } else {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000626 rtp_ready_to_send_ = ready;
627 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000628
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200629 bool ready_to_send =
630 (rtp_ready_to_send_ &&
631 // In the case of rtcp mux |rtcp_transport_channel_| will be null.
632 (rtcp_ready_to_send_ || !rtcp_transport_channel_));
633
634 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700635 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200636 Bind(&MediaChannel::OnReadyToSend, media_channel_, ready_to_send));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000637}
638
639bool BaseChannel::PacketIsRtcp(const TransportChannel* channel,
640 const char* data, size_t len) {
641 return (channel == rtcp_transport_channel_ ||
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000642 rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000643}
644
stefanc1aeaf02015-10-15 07:26:07 -0700645bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700646 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700647 const rtc::PacketOptions& options) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200648 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
649 // If the thread is not our network thread, we will post to our network
650 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000651 // synchronize access to all the pieces of the send path, including
652 // SRTP and the inner workings of the transport channels.
653 // The only downside is that we can't return a proper failure code if
654 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200655 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000656 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200657 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
658 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800659 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700660 data->options = options;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700661 network_thread_->Post(RTC_FROM_HERE, this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000662 return true;
663 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200664 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000665
666 // Now that we are on the correct thread, ensure we have a place to send this
667 // packet before doing anything. (We might get RTCP packets that we don't
668 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
669 // transport.
670 TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
671 transport_channel_ : rtcp_transport_channel_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000672 if (!channel || !channel->writable()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673 return false;
674 }
675
676 // Protect ourselves against crazy data.
677 if (!ValidPacket(rtcp, packet)) {
678 LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000679 << PacketType(rtcp)
680 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681 return false;
682 }
683
stefanc1aeaf02015-10-15 07:26:07 -0700684 rtc::PacketOptions updated_options;
685 updated_options = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686 // Protect if needed.
687 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200688 TRACE_EVENT0("webrtc", "SRTP Encode");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000689 bool res;
Karl Wibergc56ac1e2015-05-04 14:54:55 +0200690 uint8_t* data = packet->data();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000691 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000692 if (!rtcp) {
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000693 // If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
694 // inside libsrtp for a RTP packet. A external HMAC module will be writing
695 // a fake HMAC value. This is ONLY done for a RTP packet.
696 // Socket layer will update rtp sendtime extension header if present in
697 // packet with current time before updating the HMAC.
698#if !defined(ENABLE_EXTERNAL_AUTH)
699 res = srtp_filter_.ProtectRtp(
700 data, len, static_cast<int>(packet->capacity()), &len);
701#else
stefanc1aeaf02015-10-15 07:26:07 -0700702 updated_options.packet_time_params.rtp_sendtime_extension_id =
henrike@webrtc.org05376342014-03-10 15:53:12 +0000703 rtp_abs_sendtime_extn_id_;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000704 res = srtp_filter_.ProtectRtp(
705 data, len, static_cast<int>(packet->capacity()), &len,
stefanc1aeaf02015-10-15 07:26:07 -0700706 &updated_options.packet_time_params.srtp_packet_index);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000707 // If protection succeeds, let's get auth params from srtp.
708 if (res) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200709 uint8_t* auth_key = NULL;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000710 int key_len;
711 res = srtp_filter_.GetRtpAuthParams(
stefanc1aeaf02015-10-15 07:26:07 -0700712 &auth_key, &key_len,
713 &updated_options.packet_time_params.srtp_auth_tag_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000714 if (res) {
stefanc1aeaf02015-10-15 07:26:07 -0700715 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
716 updated_options.packet_time_params.srtp_auth_key.assign(
717 auth_key, auth_key + key_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000718 }
719 }
720#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000721 if (!res) {
722 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200723 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000724 GetRtpSeqNum(data, len, &seq_num);
725 GetRtpSsrc(data, len, &ssrc);
726 LOG(LS_ERROR) << "Failed to protect " << content_name_
727 << " RTP packet: size=" << len
728 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
729 return false;
730 }
731 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000732 res = srtp_filter_.ProtectRtcp(data, len,
733 static_cast<int>(packet->capacity()),
734 &len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000735 if (!res) {
736 int type = -1;
737 GetRtcpType(data, len, &type);
738 LOG(LS_ERROR) << "Failed to protect " << content_name_
739 << " RTCP packet: size=" << len << ", type=" << type;
740 return false;
741 }
742 }
743
744 // Update the length of the packet now that we've added the auth tag.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000745 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000746 } else if (secure_required_) {
747 // This is a double check for something that supposedly can't happen.
748 LOG(LS_ERROR) << "Can't send outgoing " << PacketType(rtcp)
749 << " packet when SRTP is inactive and crypto is required";
750
751 ASSERT(false);
752 return false;
753 }
754
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000755 // Bon voyage.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200756 int flags = (secure() && secure_dtls()) ? PF_SRTP_BYPASS : PF_NORMAL;
757 int ret = channel->SendPacket(packet->data<char>(), packet->size(),
758 updated_options, flags);
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000759 if (ret != static_cast<int>(packet->size())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000760 if (channel->GetError() == EWOULDBLOCK) {
761 LOG(LS_WARNING) << "Got EWOULDBLOCK from socket.";
deadbeefcbecd352015-09-23 11:50:27 -0700762 SetReadyToSend(rtcp, false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000763 }
764 return false;
765 }
766 return true;
767}
768
jbaucheec21bd2016-03-20 06:15:43 -0700769bool BaseChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000770 // Protect ourselves against crazy data.
771 if (!ValidPacket(rtcp, packet)) {
772 LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000773 << PacketType(rtcp)
774 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000775 return false;
776 }
pbos482b12e2015-11-16 10:19:58 -0800777 if (rtcp) {
778 // Permit all (seemingly valid) RTCP packets.
779 return true;
780 }
781 // Check whether we handle this payload.
jbaucheec21bd2016-03-20 06:15:43 -0700782 return bundle_filter_.DemuxPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000783}
784
jbaucheec21bd2016-03-20 06:15:43 -0700785void BaseChannel::HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000786 const rtc::PacketTime& packet_time) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200787 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000788 if (!WantsPacket(rtcp, packet)) {
789 return;
790 }
791
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000792 // We are only interested in the first rtp packet because that
793 // indicates the media has started flowing.
794 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000795 has_received_packet_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700796 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000797 }
798
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000799 // Unprotect the packet, if needed.
800 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200801 TRACE_EVENT0("webrtc", "SRTP Decode");
Karl Wiberg94784372015-04-20 14:03:07 +0200802 char* data = packet->data<char>();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000803 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000804 bool res;
805 if (!rtcp) {
806 res = srtp_filter_.UnprotectRtp(data, len, &len);
807 if (!res) {
808 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200809 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000810 GetRtpSeqNum(data, len, &seq_num);
811 GetRtpSsrc(data, len, &ssrc);
812 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
813 << " RTP packet: size=" << len
814 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
815 return;
816 }
817 } else {
818 res = srtp_filter_.UnprotectRtcp(data, len, &len);
819 if (!res) {
820 int type = -1;
821 GetRtcpType(data, len, &type);
822 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
823 << " RTCP packet: size=" << len << ", type=" << type;
824 return;
825 }
826 }
827
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000828 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000829 } else if (secure_required_) {
830 // Our session description indicates that SRTP is required, but we got a
831 // packet before our SRTP filter is active. This means either that
832 // a) we got SRTP packets before we received the SDES keys, in which case
833 // we can't decrypt it anyway, or
834 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
835 // channels, so we haven't yet extracted keys, even if DTLS did complete
836 // on the channel that the packets are being sent on. It's really good
837 // practice to wait for both RTP and RTCP to be good to go before sending
838 // media, to prevent weird failure modes, so it's fine for us to just eat
839 // packets here. This is all sidestepped if RTCP mux is used anyway.
840 LOG(LS_WARNING) << "Can't process incoming " << PacketType(rtcp)
841 << " packet when SRTP is inactive and crypto is required";
842 return;
843 }
844
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200845 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700846 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200847 Bind(&BaseChannel::OnPacketReceived, this, rtcp, *packet, packet_time));
848}
849
850void BaseChannel::OnPacketReceived(bool rtcp,
851 const rtc::CopyOnWriteBuffer& packet,
852 const rtc::PacketTime& packet_time) {
853 RTC_DCHECK(worker_thread_->IsCurrent());
854 // Need to copy variable because OnRtcpReceived/OnPacketReceived
855 // requires non-const pointer to buffer. This doesn't memcpy the actual data.
856 rtc::CopyOnWriteBuffer data(packet);
857 if (rtcp) {
858 media_channel_->OnRtcpReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000859 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200860 media_channel_->OnPacketReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861 }
862}
863
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000864bool BaseChannel::PushdownLocalDescription(
865 const SessionDescription* local_desc, ContentAction action,
866 std::string* error_desc) {
867 const ContentInfo* content_info = GetFirstContent(local_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000868 const MediaContentDescription* content_desc =
869 GetContentDescription(content_info);
870 if (content_desc && content_info && !content_info->rejected &&
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000871 !SetLocalContent(content_desc, action, error_desc)) {
872 LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
873 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000874 }
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000875 return true;
876}
877
878bool BaseChannel::PushdownRemoteDescription(
879 const SessionDescription* remote_desc, ContentAction action,
880 std::string* error_desc) {
881 const ContentInfo* content_info = GetFirstContent(remote_desc);
882 const MediaContentDescription* content_desc =
883 GetContentDescription(content_info);
884 if (content_desc && content_info && !content_info->rejected &&
885 !SetRemoteContent(content_desc, action, error_desc)) {
886 LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
887 return false;
888 }
889 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000890}
891
892void BaseChannel::EnableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000893 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894 if (enabled_)
895 return;
896
897 LOG(LS_INFO) << "Channel enabled";
898 enabled_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200899 ChangeState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000900}
901
902void BaseChannel::DisableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000903 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000904 if (!enabled_)
905 return;
906
907 LOG(LS_INFO) << "Channel disabled";
908 enabled_ = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200909 ChangeState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000910}
911
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200912void BaseChannel::UpdateWritableState_n() {
deadbeefcbecd352015-09-23 11:50:27 -0700913 if (transport_channel_ && transport_channel_->writable() &&
914 (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200915 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700916 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200917 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700918 }
919}
920
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200921void BaseChannel::ChannelWritable_n() {
922 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800923 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000924 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800925 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926
deadbeefcbecd352015-09-23 11:50:27 -0700927 LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000928 << (was_ever_writable_ ? "" : " for the first time");
929
930 std::vector<ConnectionInfo> infos;
931 transport_channel_->GetStats(&infos);
932 for (std::vector<ConnectionInfo>::const_iterator it = infos.begin();
933 it != infos.end(); ++it) {
934 if (it->best_connection) {
935 LOG(LS_INFO) << "Using " << it->local_candidate.ToSensitiveString()
936 << "->" << it->remote_candidate.ToSensitiveString();
937 break;
938 }
939 }
940
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000941 was_ever_writable_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200942 MaybeSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000943 writable_ = true;
944 ChangeState();
945}
946
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200947void BaseChannel::SignalDtlsSetupFailure_n(bool rtcp) {
948 RTC_DCHECK(network_thread_->IsCurrent());
949 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700950 RTC_FROM_HERE, signaling_thread(),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200951 Bind(&BaseChannel::SignalDtlsSetupFailure_s, this, rtcp));
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000952}
953
954void BaseChannel::SignalDtlsSetupFailure_s(bool rtcp) {
955 ASSERT(signaling_thread() == rtc::Thread::Current());
956 SignalDtlsSetupFailure(this, rtcp);
957}
958
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200959bool BaseChannel::SetDtlsSrtpCryptoSuites_n(TransportChannel* tc, bool rtcp) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800960 std::vector<int> crypto_suites;
961 // We always use the default SRTP crypto suites for RTCP, but we may use
962 // different crypto suites for RTP depending on the media type.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000963 if (!rtcp) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200964 GetSrtpCryptoSuites_n(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000965 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800966 GetDefaultSrtpCryptoSuites(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000967 }
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800968 return tc->SetSrtpCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000969}
970
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200971bool BaseChannel::ShouldSetupDtlsSrtp_n() const {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800972 // Since DTLS is applied to all channels, checking RTP should be enough.
973 return transport_channel_ && transport_channel_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000974}
975
976// This function returns true if either DTLS-SRTP is not in use
977// *or* DTLS-SRTP is successfully set up.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200978bool BaseChannel::SetupDtlsSrtp_n(bool rtcp_channel) {
979 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000980 bool ret = false;
981
deadbeefcbecd352015-09-23 11:50:27 -0700982 TransportChannel* channel =
983 rtcp_channel ? rtcp_transport_channel_ : transport_channel_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000984
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800985 RTC_DCHECK(channel->IsDtlsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800987 int selected_crypto_suite;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000988
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800989 if (!channel->GetSrtpCryptoSuite(&selected_crypto_suite)) {
990 LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000991 return false;
992 }
993
994 LOG(LS_INFO) << "Installing keys from DTLS-SRTP on "
995 << content_name() << " "
996 << PacketType(rtcp_channel);
997
998 // OK, we're now doing DTLS (RFC 5764)
999 std::vector<unsigned char> dtls_buffer(SRTP_MASTER_KEY_KEY_LEN * 2 +
1000 SRTP_MASTER_KEY_SALT_LEN * 2);
1001
1002 // RFC 5705 exporter using the RFC 5764 parameters
1003 if (!channel->ExportKeyingMaterial(
1004 kDtlsSrtpExporterLabel,
1005 NULL, 0, false,
1006 &dtls_buffer[0], dtls_buffer.size())) {
1007 LOG(LS_WARNING) << "DTLS-SRTP key export failed";
1008 ASSERT(false); // This should never happen
1009 return false;
1010 }
1011
1012 // Sync up the keys with the DTLS-SRTP interface
1013 std::vector<unsigned char> client_write_key(SRTP_MASTER_KEY_KEY_LEN +
1014 SRTP_MASTER_KEY_SALT_LEN);
1015 std::vector<unsigned char> server_write_key(SRTP_MASTER_KEY_KEY_LEN +
1016 SRTP_MASTER_KEY_SALT_LEN);
1017 size_t offset = 0;
1018 memcpy(&client_write_key[0], &dtls_buffer[offset],
1019 SRTP_MASTER_KEY_KEY_LEN);
1020 offset += SRTP_MASTER_KEY_KEY_LEN;
1021 memcpy(&server_write_key[0], &dtls_buffer[offset],
1022 SRTP_MASTER_KEY_KEY_LEN);
1023 offset += SRTP_MASTER_KEY_KEY_LEN;
1024 memcpy(&client_write_key[SRTP_MASTER_KEY_KEY_LEN],
1025 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
1026 offset += SRTP_MASTER_KEY_SALT_LEN;
1027 memcpy(&server_write_key[SRTP_MASTER_KEY_KEY_LEN],
1028 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
1029
1030 std::vector<unsigned char> *send_key, *recv_key;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001031 rtc::SSLRole role;
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00001032 if (!channel->GetSslRole(&role)) {
1033 LOG(LS_WARNING) << "GetSslRole failed";
1034 return false;
1035 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001036
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001037 if (role == rtc::SSL_SERVER) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001038 send_key = &server_write_key;
1039 recv_key = &client_write_key;
1040 } else {
1041 send_key = &client_write_key;
1042 recv_key = &server_write_key;
1043 }
1044
1045 if (rtcp_channel) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001046 ret = srtp_filter_.SetRtcpParams(selected_crypto_suite, &(*send_key)[0],
1047 static_cast<int>(send_key->size()),
1048 selected_crypto_suite, &(*recv_key)[0],
1049 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001050 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001051 ret = srtp_filter_.SetRtpParams(selected_crypto_suite, &(*send_key)[0],
1052 static_cast<int>(send_key->size()),
1053 selected_crypto_suite, &(*recv_key)[0],
1054 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001055 }
1056
1057 if (!ret)
1058 LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
1059 else
1060 dtls_keyed_ = true;
1061
1062 return ret;
1063}
1064
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001065void BaseChannel::MaybeSetupDtlsSrtp_n() {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001066 if (srtp_filter_.IsActive()) {
1067 return;
1068 }
1069
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001070 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001071 return;
1072 }
1073
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001074 if (!SetupDtlsSrtp_n(false)) {
1075 SignalDtlsSetupFailure_n(false);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001076 return;
1077 }
1078
1079 if (rtcp_transport_channel_) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001080 if (!SetupDtlsSrtp_n(true)) {
1081 SignalDtlsSetupFailure_n(true);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001082 return;
1083 }
1084 }
1085}
1086
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001087void BaseChannel::ChannelNotWritable_n() {
1088 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001089 if (!writable_)
1090 return;
1091
deadbeefcbecd352015-09-23 11:50:27 -07001092 LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001093 writable_ = false;
1094 ChangeState();
1095}
1096
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001097bool BaseChannel::SetRtpTransportParameters(
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001098 const MediaContentDescription* content,
1099 ContentAction action,
1100 ContentSource src,
1101 std::string* error_desc) {
1102 if (action == CA_UPDATE) {
1103 // These parameters never get changed by a CA_UDPATE.
1104 return true;
1105 }
1106
1107 // Cache secure_required_ for belt and suspenders check on SendPacket
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001108 return network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001109 RTC_FROM_HERE, Bind(&BaseChannel::SetRtpTransportParameters_n, this,
1110 content, action, src, error_desc));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001111}
1112
1113bool BaseChannel::SetRtpTransportParameters_n(
1114 const MediaContentDescription* content,
1115 ContentAction action,
1116 ContentSource src,
1117 std::string* error_desc) {
1118 RTC_DCHECK(network_thread_->IsCurrent());
1119
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001120 if (src == CS_LOCAL) {
1121 set_secure_required(content->crypto_required() != CT_NONE);
1122 }
1123
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001124 if (!SetSrtp_n(content->cryptos(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001125 return false;
1126 }
1127
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001128 if (!SetRtcpMux_n(content->rtcp_mux(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001129 return false;
1130 }
1131
1132 return true;
1133}
1134
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001135// |dtls| will be set to true if DTLS is active for transport channel and
1136// crypto is empty.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001137bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
1138 bool* dtls,
1139 std::string* error_desc) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001140 *dtls = transport_channel_->IsDtlsActive();
1141 if (*dtls && !cryptos.empty()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001142 SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001143 return false;
1144 }
1145 return true;
1146}
1147
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001148bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001149 ContentAction action,
1150 ContentSource src,
1151 std::string* error_desc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001152 TRACE_EVENT0("webrtc", "BaseChannel::SetSrtp_w");
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001153 if (action == CA_UPDATE) {
1154 // no crypto params.
1155 return true;
1156 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001157 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001158 bool dtls = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001159 ret = CheckSrtpConfig_n(cryptos, &dtls, error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001160 if (!ret) {
1161 return false;
1162 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001163 switch (action) {
1164 case CA_OFFER:
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001165 // If DTLS is already active on the channel, we could be renegotiating
1166 // here. We don't update the srtp filter.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001167 if (!dtls) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001168 ret = srtp_filter_.SetOffer(cryptos, src);
1169 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001170 break;
1171 case CA_PRANSWER:
1172 // If we're doing DTLS-SRTP, we don't want to update the filter
1173 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001174 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001175 ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
1176 }
1177 break;
1178 case CA_ANSWER:
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_.SetAnswer(cryptos, src);
1183 }
1184 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001185 default:
1186 break;
1187 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001188 if (!ret) {
1189 SafeSetError("Failed to setup SRTP filter.", error_desc);
1190 return false;
1191 }
1192 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001193}
1194
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001195void BaseChannel::ActivateRtcpMux() {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001196 network_thread_->Invoke<void>(RTC_FROM_HERE,
1197 Bind(&BaseChannel::ActivateRtcpMux_n, this));
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001198}
1199
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001200void BaseChannel::ActivateRtcpMux_n() {
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001201 if (!rtcp_mux_filter_.IsActive()) {
1202 rtcp_mux_filter_.SetActive();
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001203 SetRtcpTransportChannel_n(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001204 rtcp_transport_enabled_ = false;
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001205 }
1206}
1207
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001208bool BaseChannel::SetRtcpMux_n(bool enable,
1209 ContentAction action,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001210 ContentSource src,
1211 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001212 bool ret = false;
1213 switch (action) {
1214 case CA_OFFER:
1215 ret = rtcp_mux_filter_.SetOffer(enable, src);
1216 break;
1217 case CA_PRANSWER:
1218 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
1219 break;
1220 case CA_ANSWER:
1221 ret = rtcp_mux_filter_.SetAnswer(enable, src);
1222 if (ret && rtcp_mux_filter_.IsActive()) {
1223 // We activated RTCP mux, close down the RTCP transport.
deadbeefcbecd352015-09-23 11:50:27 -07001224 LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
1225 << " by destroying RTCP transport channel for "
1226 << transport_name();
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001227 SetRtcpTransportChannel_n(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001228 rtcp_transport_enabled_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001229 }
1230 break;
1231 case CA_UPDATE:
1232 // No RTCP mux info.
1233 ret = true;
Henrik Kjellander7c027b62015-04-22 13:21:30 +02001234 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001235 default:
1236 break;
1237 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001238 if (!ret) {
1239 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
1240 return false;
1241 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001242 // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
1243 // CA_ANSWER, but we only want to tear down the RTCP transport channel if we
1244 // received a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001245 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001246 // If the RTP transport is already writable, then so are we.
1247 if (transport_channel_->writable()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001248 ChannelWritable_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001249 }
1250 }
1251
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001252 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001253}
1254
1255bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001256 ASSERT(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -08001257 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001258}
1259
Peter Boström0c4e06b2015-10-07 12:23:21 +02001260bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001261 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001262 return media_channel()->RemoveRecvStream(ssrc);
1263}
1264
1265bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001266 ContentAction action,
1267 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001268 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1269 action == CA_PRANSWER || action == CA_UPDATE))
1270 return false;
1271
1272 // If this is an update, streams only contain streams that have changed.
1273 if (action == CA_UPDATE) {
1274 for (StreamParamsVec::const_iterator it = streams.begin();
1275 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001276 const StreamParams* existing_stream =
1277 GetStreamByIds(local_streams_, it->groupid, it->id);
1278 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001279 if (media_channel()->AddSendStream(*it)) {
1280 local_streams_.push_back(*it);
1281 LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
1282 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001283 std::ostringstream desc;
1284 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1285 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001286 return false;
1287 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001288 } else if (existing_stream && !it->has_ssrcs()) {
1289 if (!media_channel()->RemoveSendStream(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001290 std::ostringstream desc;
1291 desc << "Failed to remove send stream with ssrc "
1292 << it->first_ssrc() << ".";
1293 SafeSetError(desc.str(), error_desc);
1294 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001295 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001296 RemoveStreamBySsrc(&local_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001297 } else {
1298 LOG(LS_WARNING) << "Ignore unsupported stream update";
1299 }
1300 }
1301 return true;
1302 }
1303 // Else streams are all the streams we want to send.
1304
1305 // Check for streams that have been removed.
1306 bool ret = true;
1307 for (StreamParamsVec::const_iterator it = local_streams_.begin();
1308 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001309 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001310 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001311 std::ostringstream desc;
1312 desc << "Failed to remove send stream with ssrc "
1313 << it->first_ssrc() << ".";
1314 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001315 ret = false;
1316 }
1317 }
1318 }
1319 // Check for new streams.
1320 for (StreamParamsVec::const_iterator it = streams.begin();
1321 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001322 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001323 if (media_channel()->AddSendStream(*it)) {
stefanc1aeaf02015-10-15 07:26:07 -07001324 LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001325 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001326 std::ostringstream desc;
1327 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1328 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001329 ret = false;
1330 }
1331 }
1332 }
1333 local_streams_ = streams;
1334 return ret;
1335}
1336
1337bool BaseChannel::UpdateRemoteStreams_w(
1338 const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001339 ContentAction action,
1340 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001341 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1342 action == CA_PRANSWER || action == CA_UPDATE))
1343 return false;
1344
1345 // If this is an update, streams only contain streams that have changed.
1346 if (action == CA_UPDATE) {
1347 for (StreamParamsVec::const_iterator it = streams.begin();
1348 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001349 const StreamParams* existing_stream =
1350 GetStreamByIds(remote_streams_, it->groupid, it->id);
1351 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001352 if (AddRecvStream_w(*it)) {
1353 remote_streams_.push_back(*it);
1354 LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
1355 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001356 std::ostringstream desc;
1357 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1358 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001359 return false;
1360 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001361 } else if (existing_stream && !it->has_ssrcs()) {
1362 if (!RemoveRecvStream_w(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001363 std::ostringstream desc;
1364 desc << "Failed to remove remote stream with ssrc "
1365 << it->first_ssrc() << ".";
1366 SafeSetError(desc.str(), error_desc);
1367 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001368 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001369 RemoveStreamBySsrc(&remote_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001370 } else {
1371 LOG(LS_WARNING) << "Ignore unsupported stream update."
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001372 << " Stream exists? " << (existing_stream != nullptr)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001373 << " new stream = " << it->ToString();
1374 }
1375 }
1376 return true;
1377 }
1378 // Else streams are all the streams we want to receive.
1379
1380 // Check for streams that have been removed.
1381 bool ret = true;
1382 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
1383 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001384 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001385 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001386 std::ostringstream desc;
1387 desc << "Failed to remove remote stream with ssrc "
1388 << it->first_ssrc() << ".";
1389 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001390 ret = false;
1391 }
1392 }
1393 }
1394 // Check for new streams.
1395 for (StreamParamsVec::const_iterator it = streams.begin();
1396 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001397 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001398 if (AddRecvStream_w(*it)) {
1399 LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
1400 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001401 std::ostringstream desc;
1402 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1403 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001404 ret = false;
1405 }
1406 }
1407 }
1408 remote_streams_ = streams;
1409 return ret;
1410}
1411
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001412void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w(
isheriff6f8d6862016-05-26 11:24:55 -07001413 const std::vector<webrtc::RtpExtension>& extensions) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001414// Absolute Send Time extension id is used only with external auth,
1415// so do not bother searching for it and making asyncronious call to set
1416// something that is not used.
1417#if defined(ENABLE_EXTERNAL_AUTH)
isheriff6f8d6862016-05-26 11:24:55 -07001418 const webrtc::RtpExtension* send_time_extension =
1419 FindHeaderExtension(extensions, webrtc::RtpExtension::kAbsSendTimeUri);
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001420 int rtp_abs_sendtime_extn_id =
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001421 send_time_extension ? send_time_extension->id : -1;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001422 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001423 RTC_FROM_HERE, network_thread_,
1424 Bind(&BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n, this,
1425 rtp_abs_sendtime_extn_id));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001426#endif
1427}
1428
1429void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n(
1430 int rtp_abs_sendtime_extn_id) {
1431 rtp_abs_sendtime_extn_id_ = rtp_abs_sendtime_extn_id;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001432}
1433
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001434void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001435 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001436 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001437 case MSG_SEND_RTP_PACKET:
1438 case MSG_SEND_RTCP_PACKET: {
1439 RTC_DCHECK(network_thread_->IsCurrent());
1440 SendPacketMessageData* data =
1441 static_cast<SendPacketMessageData*>(pmsg->pdata);
1442 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
1443 SendPacket(rtcp, &data->packet, data->options);
1444 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001445 break;
1446 }
1447 case MSG_FIRSTPACKETRECEIVED: {
1448 SignalFirstPacketReceived(this);
1449 break;
1450 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001451 }
1452}
1453
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001454void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001455 // Flush all remaining RTCP messages. This should only be called in
1456 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001457 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001458 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001459 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
1460 for (const auto& message : rtcp_messages) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001461 network_thread_->Send(RTC_FROM_HERE, this, MSG_SEND_RTCP_PACKET,
1462 message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001463 }
1464}
1465
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001466void BaseChannel::SignalSentPacket_n(TransportChannel* /* channel */,
1467 const rtc::SentPacket& sent_packet) {
1468 RTC_DCHECK(network_thread_->IsCurrent());
1469 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001470 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001471 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
1472}
1473
1474void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
1475 RTC_DCHECK(worker_thread_->IsCurrent());
1476 SignalSentPacket(sent_packet);
1477}
1478
1479VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
1480 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001481 MediaEngineInterface* media_engine,
1482 VoiceMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001483 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001484 const std::string& content_name,
1485 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001486 : BaseChannel(worker_thread,
1487 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001488 media_channel,
1489 transport_controller,
1490 content_name,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001491 rtcp),
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001492 media_engine_(media_engine),
deadbeefcbecd352015-09-23 11:50:27 -07001493 received_media_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001494
1495VoiceChannel::~VoiceChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001496 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001497 StopAudioMonitor();
1498 StopMediaMonitor();
1499 // this can't be done in the base class, since it calls a virtual
1500 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001501 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001502}
1503
skvlad6c87a672016-05-17 17:49:52 -07001504bool VoiceChannel::Init_w(const std::string* bundle_transport_name) {
1505 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506 return false;
1507 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001508 return true;
1509}
1510
Peter Boström0c4e06b2015-10-07 12:23:21 +02001511bool VoiceChannel::SetAudioSend(uint32_t ssrc,
solenbergdfc8f4f2015-10-01 02:31:10 -07001512 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001513 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001514 AudioSource* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001515 return InvokeOnWorker(RTC_FROM_HERE,
1516 Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001517 ssrc, enable, options, source));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001518}
1519
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001520// TODO(juberti): Handle early media the right way. We should get an explicit
1521// ringing message telling us to start playing local ringback, which we cancel
1522// if any early media actually arrives. For now, we do the opposite, which is
1523// to wait 1 second for early media, and start playing local ringback if none
1524// arrives.
1525void VoiceChannel::SetEarlyMedia(bool enable) {
1526 if (enable) {
1527 // Start the early media timeout
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001528 worker_thread()->PostDelayed(RTC_FROM_HERE, kEarlyMediaTimeout, this,
1529 MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001530 } else {
1531 // Stop the timeout if currently going.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001532 worker_thread()->Clear(this, MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001533 }
1534}
1535
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001536bool VoiceChannel::CanInsertDtmf() {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001537 return InvokeOnWorker(
1538 RTC_FROM_HERE, Bind(&VoiceMediaChannel::CanInsertDtmf, media_channel()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539}
1540
Peter Boström0c4e06b2015-10-07 12:23:21 +02001541bool VoiceChannel::InsertDtmf(uint32_t ssrc,
1542 int event_code,
solenberg1d63dd02015-12-02 12:35:09 -08001543 int duration) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001544 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceChannel::InsertDtmf_w, this,
1545 ssrc, event_code, duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546}
1547
solenberg4bac9c52015-10-09 02:32:53 -07001548bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001549 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::SetOutputVolume,
1550 media_channel(), ssrc, volume));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001551}
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001552
Tommif888bb52015-12-12 01:37:01 +01001553void VoiceChannel::SetRawAudioSink(
1554 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -08001555 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
1556 // We need to work around Bind's lack of support for unique_ptr and ownership
deadbeef2d110be2016-01-13 12:00:26 -08001557 // passing. So we invoke to our own little routine that gets a pointer to
1558 // our local variable. This is OK since we're synchronously invoking.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001559 InvokeOnWorker(RTC_FROM_HERE,
1560 Bind(&SetRawAudioSink_w, media_channel(), ssrc, &sink));
Tommif888bb52015-12-12 01:37:01 +01001561}
1562
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001563webrtc::RtpParameters VoiceChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001564 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001565 RTC_FROM_HERE, Bind(&VoiceChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001566}
1567
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001568webrtc::RtpParameters VoiceChannel::GetRtpSendParameters_w(
1569 uint32_t ssrc) const {
1570 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001571}
1572
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001573bool VoiceChannel::SetRtpSendParameters(
1574 uint32_t ssrc,
1575 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001576 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001577 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001578 Bind(&VoiceChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001579}
1580
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001581bool VoiceChannel::SetRtpSendParameters_w(uint32_t ssrc,
1582 webrtc::RtpParameters parameters) {
1583 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1584}
1585
1586webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters(
1587 uint32_t ssrc) const {
1588 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001589 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001590 Bind(&VoiceChannel::GetRtpReceiveParameters_w, this, ssrc));
1591}
1592
1593webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters_w(
1594 uint32_t ssrc) const {
1595 return media_channel()->GetRtpReceiveParameters(ssrc);
1596}
1597
1598bool VoiceChannel::SetRtpReceiveParameters(
1599 uint32_t ssrc,
1600 const webrtc::RtpParameters& parameters) {
1601 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001602 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001603 Bind(&VoiceChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1604}
1605
1606bool VoiceChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1607 webrtc::RtpParameters parameters) {
1608 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001609}
1610
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001611bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001612 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::GetStats,
1613 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001614}
1615
1616void VoiceChannel::StartMediaMonitor(int cms) {
1617 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001618 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001619 media_monitor_->SignalUpdate.connect(
1620 this, &VoiceChannel::OnMediaMonitorUpdate);
1621 media_monitor_->Start(cms);
1622}
1623
1624void VoiceChannel::StopMediaMonitor() {
1625 if (media_monitor_) {
1626 media_monitor_->Stop();
1627 media_monitor_->SignalUpdate.disconnect(this);
1628 media_monitor_.reset();
1629 }
1630}
1631
1632void VoiceChannel::StartAudioMonitor(int cms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001633 audio_monitor_.reset(new AudioMonitor(this, rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001634 audio_monitor_
1635 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1636 audio_monitor_->Start(cms);
1637}
1638
1639void VoiceChannel::StopAudioMonitor() {
1640 if (audio_monitor_) {
1641 audio_monitor_->Stop();
1642 audio_monitor_.reset();
1643 }
1644}
1645
1646bool VoiceChannel::IsAudioMonitorRunning() const {
1647 return (audio_monitor_.get() != NULL);
1648}
1649
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001650int VoiceChannel::GetInputLevel_w() {
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001651 return media_engine_->GetInputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001652}
1653
1654int VoiceChannel::GetOutputLevel_w() {
1655 return media_channel()->GetOutputLevel();
1656}
1657
1658void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1659 media_channel()->GetActiveStreams(actives);
1660}
1661
1662void VoiceChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001663 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001664 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001665 int flags) {
1666 BaseChannel::OnChannelRead(channel, data, len, packet_time, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001667
1668 // Set a flag when we've received an RTP packet. If we're waiting for early
1669 // media, this will disable the timeout.
1670 if (!received_media_ && !PacketIsRtcp(channel, data, len)) {
1671 received_media_ = true;
1672 }
1673}
1674
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001675void BaseChannel::ChangeState() {
1676 RTC_DCHECK(network_thread_->IsCurrent());
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001677 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001678 Bind(&BaseChannel::ChangeState_w, this));
1679}
1680
1681void VoiceChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001682 // Render incoming data if we're the active call, and we have the local
1683 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001684 bool recv = IsReadyToReceive_w();
solenberg5b14b422015-10-01 04:10:31 -07001685 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001686
1687 // Send outgoing data if we're the active call, we have the remote content,
1688 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001689 bool send = IsReadyToSend_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001690 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001691
1692 LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
1693}
1694
1695const ContentInfo* VoiceChannel::GetFirstContent(
1696 const SessionDescription* sdesc) {
1697 return GetFirstAudioContent(sdesc);
1698}
1699
1700bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001701 ContentAction action,
1702 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001703 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001704 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001705 LOG(LS_INFO) << "Setting local voice description";
1706
1707 const AudioContentDescription* audio =
1708 static_cast<const AudioContentDescription*>(content);
1709 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001710 if (!audio) {
1711 SafeSetError("Can't find audio content in local description.", error_desc);
1712 return false;
1713 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001714
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001715 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001716 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001717 }
1718
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001719 AudioRecvParameters recv_params = last_recv_params_;
1720 RtpParametersFromMediaDescription(audio, &recv_params);
1721 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001722 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001723 error_desc);
1724 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001725 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001726 for (const AudioCodec& codec : audio->codecs()) {
1727 bundle_filter()->AddPayloadType(codec.id);
1728 }
1729 last_recv_params_ = recv_params;
1730
1731 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1732 // only give it to the media channel once we have a remote
1733 // description too (without a remote description, we won't be able
1734 // to send them anyway).
1735 if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) {
1736 SafeSetError("Failed to set local audio description streams.", error_desc);
1737 return false;
1738 }
1739
1740 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001741 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001742 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001743}
1744
1745bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001746 ContentAction action,
1747 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001748 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001749 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001750 LOG(LS_INFO) << "Setting remote voice description";
1751
1752 const AudioContentDescription* audio =
1753 static_cast<const AudioContentDescription*>(content);
1754 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001755 if (!audio) {
1756 SafeSetError("Can't find audio content in remote description.", error_desc);
1757 return false;
1758 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001759
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001760 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001761 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001762 }
1763
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001764 AudioSendParameters send_params = last_send_params_;
1765 RtpSendParametersFromMediaDescription(audio, &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001766 if (audio->agc_minus_10db()) {
Karl Wibergbe579832015-11-10 22:34:18 +01001767 send_params.options.adjust_agc_delta = rtc::Optional<int>(kAgcMinus10db);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001768 }
skvladdc1c62c2016-03-16 19:07:43 -07001769
1770 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1771 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001772 SafeSetError("Failed to set remote audio description send parameters.",
1773 error_desc);
1774 return false;
1775 }
1776 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001777
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001778 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1779 // and only give it to the media channel once we have a local
1780 // description too (without a local description, we won't be able to
1781 // recv them anyway).
1782 if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) {
1783 SafeSetError("Failed to set remote audio description streams.", error_desc);
1784 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001785 }
1786
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001787 if (audio->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001788 MaybeCacheRtpAbsSendTimeHeaderExtension_w(audio->rtp_header_extensions());
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001789 }
1790
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001791 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001792 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001793 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001794}
1795
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001796void VoiceChannel::HandleEarlyMediaTimeout() {
1797 // This occurs on the main thread, not the worker thread.
1798 if (!received_media_) {
1799 LOG(LS_INFO) << "No early media received before timeout";
1800 SignalEarlyMediaTimeout(this);
1801 }
1802}
1803
Peter Boström0c4e06b2015-10-07 12:23:21 +02001804bool VoiceChannel::InsertDtmf_w(uint32_t ssrc,
1805 int event,
solenberg1d63dd02015-12-02 12:35:09 -08001806 int duration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001807 if (!enabled()) {
1808 return false;
1809 }
solenberg1d63dd02015-12-02 12:35:09 -08001810 return media_channel()->InsertDtmf(ssrc, event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001811}
1812
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001813void VoiceChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001814 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001815 case MSG_EARLYMEDIATIMEOUT:
1816 HandleEarlyMediaTimeout();
1817 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001818 case MSG_CHANNEL_ERROR: {
1819 VoiceChannelErrorMessageData* data =
1820 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001821 delete data;
1822 break;
1823 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001824 default:
1825 BaseChannel::OnMessage(pmsg);
1826 break;
1827 }
1828}
1829
1830void VoiceChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001831 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001832 SignalConnectionMonitor(this, infos);
1833}
1834
1835void VoiceChannel::OnMediaMonitorUpdate(
1836 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
1837 ASSERT(media_channel == this->media_channel());
1838 SignalMediaMonitor(this, info);
1839}
1840
1841void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1842 const AudioInfo& info) {
1843 SignalAudioMonitor(this, info);
1844}
1845
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001846void VoiceChannel::GetSrtpCryptoSuites_n(
1847 std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001848 GetSupportedAudioCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001849}
1850
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001851VideoChannel::VideoChannel(rtc::Thread* worker_thread,
1852 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001853 VideoMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001854 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001855 const std::string& content_name,
Fredrik Solenberg7fb711f2015-04-22 15:30:51 +02001856 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001857 : BaseChannel(worker_thread,
1858 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001859 media_channel,
1860 transport_controller,
1861 content_name,
perkjc11b1842016-03-07 17:34:13 -08001862 rtcp) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001863
skvlad6c87a672016-05-17 17:49:52 -07001864bool VideoChannel::Init_w(const std::string* bundle_transport_name) {
1865 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001866 return false;
1867 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001868 return true;
1869}
1870
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001871VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001872 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001873 StopMediaMonitor();
1874 // this can't be done in the base class, since it calls a virtual
1875 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001876
1877 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001878}
1879
nisse08582ff2016-02-04 01:24:52 -08001880bool VideoChannel::SetSink(uint32_t ssrc,
1881 rtc::VideoSinkInterface<VideoFrame>* sink) {
1882 worker_thread()->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001883 RTC_FROM_HERE,
nisse08582ff2016-02-04 01:24:52 -08001884 Bind(&VideoMediaChannel::SetSink, media_channel(), ssrc, sink));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001885 return true;
1886}
1887
deadbeef5a4a75a2016-06-02 16:23:38 -07001888bool VideoChannel::SetVideoSend(
nisse2ded9b12016-04-08 02:23:55 -07001889 uint32_t ssrc,
deadbeef5a4a75a2016-06-02 16:23:38 -07001890 bool mute,
1891 const VideoOptions* options,
nisse2ded9b12016-04-08 02:23:55 -07001892 rtc::VideoSourceInterface<cricket::VideoFrame>* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001893 return InvokeOnWorker(RTC_FROM_HERE,
1894 Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
deadbeef5a4a75a2016-06-02 16:23:38 -07001895 ssrc, mute, options, source));
solenberg1dd98f32015-09-10 01:57:14 -07001896}
1897
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001898webrtc::RtpParameters VideoChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001899 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001900 RTC_FROM_HERE, Bind(&VideoChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001901}
1902
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001903webrtc::RtpParameters VideoChannel::GetRtpSendParameters_w(
1904 uint32_t ssrc) const {
1905 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001906}
1907
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001908bool VideoChannel::SetRtpSendParameters(
1909 uint32_t ssrc,
1910 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001911 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001912 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001913 Bind(&VideoChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001914}
1915
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001916bool VideoChannel::SetRtpSendParameters_w(uint32_t ssrc,
1917 webrtc::RtpParameters parameters) {
1918 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1919}
1920
1921webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters(
1922 uint32_t ssrc) const {
1923 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001924 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001925 Bind(&VideoChannel::GetRtpReceiveParameters_w, this, ssrc));
1926}
1927
1928webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters_w(
1929 uint32_t ssrc) const {
1930 return media_channel()->GetRtpReceiveParameters(ssrc);
1931}
1932
1933bool VideoChannel::SetRtpReceiveParameters(
1934 uint32_t ssrc,
1935 const webrtc::RtpParameters& parameters) {
1936 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001937 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001938 Bind(&VideoChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1939}
1940
1941bool VideoChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1942 webrtc::RtpParameters parameters) {
1943 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001944}
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001945
1946void VideoChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001947 // Send outgoing data if we're the active call, we have the remote content,
1948 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001949 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001950 if (!media_channel()->SetSend(send)) {
1951 LOG(LS_ERROR) << "Failed to SetSend on video channel";
1952 // TODO(gangji): Report error back to server.
1953 }
1954
Peter Boström34fbfff2015-09-24 19:20:30 +02001955 LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001956}
1957
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00001958bool VideoChannel::GetStats(VideoMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001959 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VideoMediaChannel::GetStats,
1960 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001961}
1962
1963void VideoChannel::StartMediaMonitor(int cms) {
1964 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001965 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001966 media_monitor_->SignalUpdate.connect(
1967 this, &VideoChannel::OnMediaMonitorUpdate);
1968 media_monitor_->Start(cms);
1969}
1970
1971void VideoChannel::StopMediaMonitor() {
1972 if (media_monitor_) {
1973 media_monitor_->Stop();
1974 media_monitor_.reset();
1975 }
1976}
1977
1978const ContentInfo* VideoChannel::GetFirstContent(
1979 const SessionDescription* sdesc) {
1980 return GetFirstVideoContent(sdesc);
1981}
1982
1983bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001984 ContentAction action,
1985 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001986 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001987 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001988 LOG(LS_INFO) << "Setting local video description";
1989
1990 const VideoContentDescription* video =
1991 static_cast<const VideoContentDescription*>(content);
1992 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001993 if (!video) {
1994 SafeSetError("Can't find video content in local description.", error_desc);
1995 return false;
1996 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001997
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001998 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001999 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002000 }
2001
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002002 VideoRecvParameters recv_params = last_recv_params_;
2003 RtpParametersFromMediaDescription(video, &recv_params);
2004 if (!media_channel()->SetRecvParameters(recv_params)) {
2005 SafeSetError("Failed to set local video description recv parameters.",
2006 error_desc);
2007 return false;
2008 }
2009 for (const VideoCodec& codec : video->codecs()) {
2010 bundle_filter()->AddPayloadType(codec.id);
2011 }
2012 last_recv_params_ = recv_params;
2013
2014 // TODO(pthatcher): Move local streams into VideoSendParameters, and
2015 // only give it to the media channel once we have a remote
2016 // description too (without a remote description, we won't be able
2017 // to send them anyway).
2018 if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) {
2019 SafeSetError("Failed to set local video description streams.", error_desc);
2020 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002021 }
2022
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002023 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002024 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002025 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002026}
2027
2028bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002029 ContentAction action,
2030 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002031 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002032 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002033 LOG(LS_INFO) << "Setting remote video description";
2034
2035 const VideoContentDescription* video =
2036 static_cast<const VideoContentDescription*>(content);
2037 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002038 if (!video) {
2039 SafeSetError("Can't find video content in remote description.", error_desc);
2040 return false;
2041 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002042
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002043 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002044 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002045 }
2046
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002047 VideoSendParameters send_params = last_send_params_;
2048 RtpSendParametersFromMediaDescription(video, &send_params);
2049 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08002050 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002051 }
skvladdc1c62c2016-03-16 19:07:43 -07002052
2053 bool parameters_applied = media_channel()->SetSendParameters(send_params);
2054
2055 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002056 SafeSetError("Failed to set remote video description send parameters.",
2057 error_desc);
2058 return false;
2059 }
2060 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002061
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002062 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
2063 // and only give it to the media channel once we have a local
2064 // description too (without a local description, we won't be able to
2065 // recv them anyway).
2066 if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) {
2067 SafeSetError("Failed to set remote video description streams.", error_desc);
2068 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002069 }
2070
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002071 if (video->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002072 MaybeCacheRtpAbsSendTimeHeaderExtension_w(video->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002073 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002074
2075 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002076 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002077 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002078}
2079
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002080void VideoChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002081 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002082 case MSG_CHANNEL_ERROR: {
2083 const VideoChannelErrorMessageData* data =
2084 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002085 delete data;
2086 break;
2087 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002088 default:
2089 BaseChannel::OnMessage(pmsg);
2090 break;
2091 }
2092}
2093
2094void VideoChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002095 ConnectionMonitor* monitor, const std::vector<ConnectionInfo> &infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002096 SignalConnectionMonitor(this, infos);
2097}
2098
2099// TODO(pthatcher): Look into removing duplicate code between
2100// audio, video, and data, perhaps by using templates.
2101void VideoChannel::OnMediaMonitorUpdate(
2102 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
2103 ASSERT(media_channel == this->media_channel());
2104 SignalMediaMonitor(this, info);
2105}
2106
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002107void VideoChannel::GetSrtpCryptoSuites_n(
2108 std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002109 GetSupportedVideoCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002110}
2111
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002112DataChannel::DataChannel(rtc::Thread* worker_thread,
2113 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002114 DataMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07002115 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002116 const std::string& content_name,
2117 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002118 : BaseChannel(worker_thread,
2119 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07002120 media_channel,
2121 transport_controller,
2122 content_name,
2123 rtcp),
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002124 data_channel_type_(cricket::DCT_NONE),
deadbeefcbecd352015-09-23 11:50:27 -07002125 ready_to_send_data_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002126
2127DataChannel::~DataChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08002128 TRACE_EVENT0("webrtc", "DataChannel::~DataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002129 StopMediaMonitor();
2130 // this can't be done in the base class, since it calls a virtual
2131 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00002132
2133 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002134}
2135
skvlad6c87a672016-05-17 17:49:52 -07002136bool DataChannel::Init_w(const std::string* bundle_transport_name) {
2137 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002138 return false;
2139 }
2140 media_channel()->SignalDataReceived.connect(
2141 this, &DataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002142 media_channel()->SignalReadyToSend.connect(
2143 this, &DataChannel::OnDataChannelReadyToSend);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002144 media_channel()->SignalStreamClosedRemotely.connect(
2145 this, &DataChannel::OnStreamClosedRemotely);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002146 return true;
2147}
2148
2149bool DataChannel::SendData(const SendDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -07002150 const rtc::CopyOnWriteBuffer& payload,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002151 SendDataResult* result) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002152 return InvokeOnWorker(
2153 RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params,
2154 payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002155}
2156
2157const ContentInfo* DataChannel::GetFirstContent(
2158 const SessionDescription* sdesc) {
2159 return GetFirstDataContent(sdesc);
2160}
2161
jbaucheec21bd2016-03-20 06:15:43 -07002162bool DataChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002163 if (data_channel_type_ == DCT_SCTP) {
2164 // TODO(pthatcher): Do this in a more robust way by checking for
2165 // SCTP or DTLS.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +00002166 return !IsRtpPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002167 } else if (data_channel_type_ == DCT_RTP) {
2168 return BaseChannel::WantsPacket(rtcp, packet);
2169 }
2170 return false;
2171}
2172
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002173bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
2174 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002175 // It hasn't been set before, so set it now.
2176 if (data_channel_type_ == DCT_NONE) {
2177 data_channel_type_ = new_data_channel_type;
2178 return true;
2179 }
2180
2181 // It's been set before, but doesn't match. That's bad.
2182 if (data_channel_type_ != new_data_channel_type) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002183 std::ostringstream desc;
2184 desc << "Data channel type mismatch."
2185 << " Expected " << data_channel_type_
2186 << " Got " << new_data_channel_type;
2187 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002188 return false;
2189 }
2190
2191 // It's hasn't changed. Nothing to do.
2192 return true;
2193}
2194
2195bool DataChannel::SetDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002196 const DataContentDescription* content,
2197 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002198 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
2199 (content->protocol() == kMediaProtocolDtlsSctp));
2200 DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002201 return SetDataChannelType(data_channel_type, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002202}
2203
2204bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002205 ContentAction action,
2206 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002207 TRACE_EVENT0("webrtc", "DataChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002208 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002209 LOG(LS_INFO) << "Setting local data description";
2210
2211 const DataContentDescription* data =
2212 static_cast<const DataContentDescription*>(content);
2213 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002214 if (!data) {
2215 SafeSetError("Can't find data content in local description.", error_desc);
2216 return false;
2217 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002218
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002219 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002220 return false;
2221 }
2222
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002223 if (data_channel_type_ == DCT_RTP) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002224 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002225 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002226 }
2227 }
2228
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002229 // FYI: We send the SCTP port number (not to be confused with the
2230 // underlying UDP port number) as a codec parameter. So even SCTP
2231 // data channels need codecs.
2232 DataRecvParameters recv_params = last_recv_params_;
2233 RtpParametersFromMediaDescription(data, &recv_params);
2234 if (!media_channel()->SetRecvParameters(recv_params)) {
2235 SafeSetError("Failed to set remote data description recv parameters.",
2236 error_desc);
2237 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002238 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002239 if (data_channel_type_ == DCT_RTP) {
2240 for (const DataCodec& codec : data->codecs()) {
2241 bundle_filter()->AddPayloadType(codec.id);
2242 }
2243 }
2244 last_recv_params_ = recv_params;
2245
2246 // TODO(pthatcher): Move local streams into DataSendParameters, and
2247 // only give it to the media channel once we have a remote
2248 // description too (without a remote description, we won't be able
2249 // to send them anyway).
2250 if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) {
2251 SafeSetError("Failed to set local data description streams.", error_desc);
2252 return false;
2253 }
2254
2255 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002256 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002257 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002258}
2259
2260bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002261 ContentAction action,
2262 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002263 TRACE_EVENT0("webrtc", "DataChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002264 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002265
2266 const DataContentDescription* data =
2267 static_cast<const DataContentDescription*>(content);
2268 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002269 if (!data) {
2270 SafeSetError("Can't find data content in remote description.", error_desc);
2271 return false;
2272 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002273
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002274 // If the remote data doesn't have codecs and isn't an update, it
2275 // must be empty, so ignore it.
2276 if (!data->has_codecs() && action != CA_UPDATE) {
2277 return true;
2278 }
2279
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002280 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002281 return false;
2282 }
2283
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002284 LOG(LS_INFO) << "Setting remote data description";
2285 if (data_channel_type_ == DCT_RTP &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002286 !SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002287 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002288 }
2289
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002290
2291 DataSendParameters send_params = last_send_params_;
2292 RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params);
2293 if (!media_channel()->SetSendParameters(send_params)) {
2294 SafeSetError("Failed to set remote data description send parameters.",
2295 error_desc);
2296 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002297 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002298 last_send_params_ = send_params;
2299
2300 // TODO(pthatcher): Move remote streams into DataRecvParameters,
2301 // and only give it to the media channel once we have a local
2302 // description too (without a local description, we won't be able to
2303 // recv them anyway).
2304 if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) {
2305 SafeSetError("Failed to set remote data description streams.",
2306 error_desc);
2307 return false;
2308 }
2309
2310 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002311 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002312 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002313}
2314
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002315void DataChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002316 // Render incoming data if we're the active call, and we have the local
2317 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002318 bool recv = IsReadyToReceive_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002319 if (!media_channel()->SetReceive(recv)) {
2320 LOG(LS_ERROR) << "Failed to SetReceive on data channel";
2321 }
2322
2323 // Send outgoing data if we're the active call, we have the remote content,
2324 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002325 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002326 if (!media_channel()->SetSend(send)) {
2327 LOG(LS_ERROR) << "Failed to SetSend on data channel";
2328 }
2329
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002330 // Trigger SignalReadyToSendData asynchronously.
2331 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002332
2333 LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
2334}
2335
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002336void DataChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002337 switch (pmsg->message_id) {
2338 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002339 DataChannelReadyToSendMessageData* data =
2340 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002341 ready_to_send_data_ = data->data();
2342 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002343 delete data;
2344 break;
2345 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002346 case MSG_DATARECEIVED: {
2347 DataReceivedMessageData* data =
2348 static_cast<DataReceivedMessageData*>(pmsg->pdata);
2349 SignalDataReceived(this, data->params, data->payload);
2350 delete data;
2351 break;
2352 }
2353 case MSG_CHANNEL_ERROR: {
2354 const DataChannelErrorMessageData* data =
2355 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002356 delete data;
2357 break;
2358 }
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002359 case MSG_STREAMCLOSEDREMOTELY: {
Peter Boström0c4e06b2015-10-07 12:23:21 +02002360 rtc::TypedMessageData<uint32_t>* data =
2361 static_cast<rtc::TypedMessageData<uint32_t>*>(pmsg->pdata);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002362 SignalStreamClosedRemotely(data->data());
2363 delete data;
2364 break;
2365 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002366 default:
2367 BaseChannel::OnMessage(pmsg);
2368 break;
2369 }
2370}
2371
2372void DataChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002373 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002374 SignalConnectionMonitor(this, infos);
2375}
2376
2377void DataChannel::StartMediaMonitor(int cms) {
2378 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002379 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002380 media_monitor_->SignalUpdate.connect(
2381 this, &DataChannel::OnMediaMonitorUpdate);
2382 media_monitor_->Start(cms);
2383}
2384
2385void DataChannel::StopMediaMonitor() {
2386 if (media_monitor_) {
2387 media_monitor_->Stop();
2388 media_monitor_->SignalUpdate.disconnect(this);
2389 media_monitor_.reset();
2390 }
2391}
2392
2393void DataChannel::OnMediaMonitorUpdate(
2394 DataMediaChannel* media_channel, const DataMediaInfo& info) {
2395 ASSERT(media_channel == this->media_channel());
2396 SignalMediaMonitor(this, info);
2397}
2398
2399void DataChannel::OnDataReceived(
2400 const ReceiveDataParams& params, const char* data, size_t len) {
2401 DataReceivedMessageData* msg = new DataReceivedMessageData(
2402 params, data, len);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002403 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002404}
2405
Peter Boström0c4e06b2015-10-07 12:23:21 +02002406void DataChannel::OnDataChannelError(uint32_t ssrc,
2407 DataMediaChannel::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002408 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2409 ssrc, err);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002410 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_CHANNEL_ERROR, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002411}
2412
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002413void DataChannel::OnDataChannelReadyToSend(bool writable) {
2414 // This is usded for congestion control to indicate that the stream is ready
2415 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2416 // that the transport channel is ready.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002417 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002418 new DataChannelReadyToSendMessageData(writable));
2419}
2420
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002421void DataChannel::GetSrtpCryptoSuites_n(std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002422 GetSupportedDataCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002423}
2424
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002425bool DataChannel::ShouldSetupDtlsSrtp_n() const {
2426 return data_channel_type_ == DCT_RTP && BaseChannel::ShouldSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002427}
2428
Peter Boström0c4e06b2015-10-07 12:23:21 +02002429void DataChannel::OnStreamClosedRemotely(uint32_t sid) {
2430 rtc::TypedMessageData<uint32_t>* message =
2431 new rtc::TypedMessageData<uint32_t>(sid);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002432 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_STREAMCLOSEDREMOTELY,
2433 message);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002434}
2435
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002436} // namespace cricket