blob: 7a0d1efaff7da13bcc8d5119a63a201fedf70af1 [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
deadbeef2d110be2016-01-13 12:00:26 -080046} // namespace
47
henrike@webrtc.org28e20752013-07-10 00:45:36 +000048enum {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000049 MSG_EARLYMEDIATIMEOUT = 1,
Danil Chapovalov33b01f22016-05-11 19:55:27 +020050 MSG_SEND_RTP_PACKET,
51 MSG_SEND_RTCP_PACKET,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000052 MSG_CHANNEL_ERROR,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000053 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000054 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000055 MSG_FIRSTPACKETRECEIVED,
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +000056 MSG_STREAMCLOSEDREMOTELY,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000057};
58
59// Value specified in RFC 5764.
60static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
61
62static const int kAgcMinus10db = -10;
63
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000064static void SafeSetError(const std::string& message, std::string* error_desc) {
65 if (error_desc) {
66 *error_desc = message;
67 }
68}
69
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000070struct VoiceChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020071 VoiceChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000072 VoiceMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020073 : ssrc(in_ssrc), error(in_error) {}
74 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075 VoiceMediaChannel::Error error;
76};
77
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000078struct VideoChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020079 VideoChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000080 VideoMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020081 : ssrc(in_ssrc), error(in_error) {}
82 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000083 VideoMediaChannel::Error error;
84};
85
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000086struct DataChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020087 DataChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000088 DataMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020089 : ssrc(in_ssrc), error(in_error) {}
90 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000091 DataMediaChannel::Error error;
92};
93
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094static const char* PacketType(bool rtcp) {
95 return (!rtcp) ? "RTP" : "RTCP";
96}
97
jbaucheec21bd2016-03-20 06:15:43 -070098static bool ValidPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099 // Check the packet size. We could check the header too if needed.
100 return (packet &&
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000101 packet->size() >= (!rtcp ? kMinRtpPacketLen : kMinRtcpPacketLen) &&
102 packet->size() <= kMaxRtpPacketLen);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103}
104
105static bool IsReceiveContentDirection(MediaContentDirection direction) {
106 return direction == MD_SENDRECV || direction == MD_RECVONLY;
107}
108
109static bool IsSendContentDirection(MediaContentDirection direction) {
110 return direction == MD_SENDRECV || direction == MD_SENDONLY;
111}
112
113static const MediaContentDescription* GetContentDescription(
114 const ContentInfo* cinfo) {
115 if (cinfo == NULL)
116 return NULL;
117 return static_cast<const MediaContentDescription*>(cinfo->description);
118}
119
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700120template <class Codec>
121void RtpParametersFromMediaDescription(
122 const MediaContentDescriptionImpl<Codec>* desc,
123 RtpParameters<Codec>* params) {
124 // TODO(pthatcher): Remove this once we're sure no one will give us
125 // a description without codecs (currently a CA_UPDATE with just
126 // streams can).
127 if (desc->has_codecs()) {
128 params->codecs = desc->codecs();
129 }
130 // TODO(pthatcher): See if we really need
131 // rtp_header_extensions_set() and remove it if we don't.
132 if (desc->rtp_header_extensions_set()) {
133 params->extensions = desc->rtp_header_extensions();
134 }
deadbeef13871492015-12-09 12:37:51 -0800135 params->rtcp.reduced_size = desc->rtcp_reduced_size();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700136}
137
nisse05103312016-03-16 02:22:50 -0700138template <class Codec>
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700139void RtpSendParametersFromMediaDescription(
140 const MediaContentDescriptionImpl<Codec>* desc,
nisse05103312016-03-16 02:22:50 -0700141 RtpSendParameters<Codec>* send_params) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700142 RtpParametersFromMediaDescription(desc, send_params);
143 send_params->max_bandwidth_bps = desc->bandwidth();
144}
145
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200146BaseChannel::BaseChannel(rtc::Thread* worker_thread,
147 rtc::Thread* network_thread,
deadbeefcbecd352015-09-23 11:50:27 -0700148 MediaChannel* media_channel,
149 TransportController* transport_controller,
150 const std::string& content_name,
151 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200152 : worker_thread_(worker_thread),
153 network_thread_(network_thread),
154
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155 content_name_(content_name),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200156
157 transport_controller_(transport_controller),
deadbeefcbecd352015-09-23 11:50:27 -0700158 rtcp_transport_enabled_(rtcp),
159 transport_channel_(nullptr),
160 rtcp_transport_channel_(nullptr),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161 rtp_ready_to_send_(false),
162 rtcp_ready_to_send_(false),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200163 writable_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000164 was_ever_writable_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000165 has_received_packet_(false),
166 dtls_keyed_(false),
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000167 secure_required_(false),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200168 rtp_abs_sendtime_extn_id_(-1),
169
170 media_channel_(media_channel),
171 enabled_(false),
172 local_content_direction_(MD_INACTIVE),
173 remote_content_direction_(MD_INACTIVE) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000174 ASSERT(worker_thread_ == rtc::Thread::Current());
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200175 if (transport_controller) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200176 RTC_DCHECK_EQ(network_thread, transport_controller->network_thread());
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200177 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000178 LOG(LS_INFO) << "Created channel for " << content_name;
179}
180
181BaseChannel::~BaseChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800182 TRACE_EVENT0("webrtc", "BaseChannel::~BaseChannel");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000183 ASSERT(worker_thread_ == rtc::Thread::Current());
wu@webrtc.org78187522013-10-07 23:32:02 +0000184 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000185 StopConnectionMonitor();
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200186 // Eats any outstanding messages or packets.
187 worker_thread_->Clear(&invoker_);
188 worker_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000189 // We must destroy the media channel before the transport channel, otherwise
190 // the media channel may try to send on the dead transport channel. NULLing
191 // is not an effective strategy since the sends will come on another thread.
192 delete media_channel_;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200193 // Note that we don't just call SetTransportChannel_n(nullptr) because that
deadbeefcbecd352015-09-23 11:50:27 -0700194 // would call a pure virtual method which we can't do from a destructor.
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200195 network_thread_->Invoke<void>(
196 Bind(&BaseChannel::DestroyTransportChannels_n, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200197 LOG(LS_INFO) << "Destroyed channel";
198}
199
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200200void BaseChannel::DisconnectTransportChannels_n() {
201 // Send any outstanding RTCP packets.
202 FlushRtcpMessages_n();
203
204 // Stop signals from transport channels, but keep them alive because
205 // media_channel may use them from a different thread.
deadbeefcbecd352015-09-23 11:50:27 -0700206 if (transport_channel_) {
207 DisconnectFromTransportChannel(transport_channel_);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200208 }
209 if (rtcp_transport_channel_) {
210 DisconnectFromTransportChannel(rtcp_transport_channel_);
211 }
212
213 // Clear pending read packets/messages.
214 network_thread_->Clear(&invoker_);
215 network_thread_->Clear(this);
216}
217
218void BaseChannel::DestroyTransportChannels_n() {
219 if (transport_channel_) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200220 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700221 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
222 }
223 if (rtcp_transport_channel_) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200224 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700225 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
226 }
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200227 // Clear pending send packets/messages.
228 network_thread_->Clear(&invoker_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200229 network_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000230}
231
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200232bool BaseChannel::Init_w() {
233 if (!network_thread_->Invoke<bool>(Bind(&BaseChannel::InitNetwork_n, this))) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000234 return false;
235 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000236
wu@webrtc.orgde305012013-10-31 15:40:38 +0000237 // Both RTP and RTCP channels are set, we can call SetInterface on
238 // media channel and it can set network options.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200239 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.orgde305012013-10-31 15:40:38 +0000240 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000241 return true;
242}
243
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200244bool BaseChannel::InitNetwork_n() {
245 RTC_DCHECK(network_thread_->IsCurrent());
246 if (!SetTransport_n(content_name())) {
247 return false;
248 }
249
250 if (!SetDtlsSrtpCryptoSuites_n(transport_channel_, false)) {
251 return false;
252 }
253 if (rtcp_transport_enabled() &&
254 !SetDtlsSrtpCryptoSuites_n(rtcp_transport_channel_, true)) {
255 return false;
256 }
257 return true;
258}
259
wu@webrtc.org78187522013-10-07 23:32:02 +0000260void BaseChannel::Deinit() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200261 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.org78187522013-10-07 23:32:02 +0000262 media_channel_->SetInterface(NULL);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200263 // Packets arrive on the network thread, processing packets calls virtual
264 // functions, so need to stop this process in Deinit that is called in
265 // derived classes destructor.
266 network_thread_->Invoke<void>(
267 Bind(&BaseChannel::DisconnectTransportChannels_n, this));
wu@webrtc.org78187522013-10-07 23:32:02 +0000268}
269
deadbeefcbecd352015-09-23 11:50:27 -0700270bool BaseChannel::SetTransport(const std::string& transport_name) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200271 return network_thread_->Invoke<bool>(
272 Bind(&BaseChannel::SetTransport_n, this, transport_name));
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000273}
274
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200275bool BaseChannel::SetTransport_n(const std::string& transport_name) {
276 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000277
deadbeefcbecd352015-09-23 11:50:27 -0700278 if (transport_name == transport_name_) {
279 // Nothing to do if transport name isn't changing
280 return true;
281 }
282
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800283 // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport
284 // changes and wait until the DTLS handshake is complete to set the newly
285 // negotiated parameters.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200286 if (ShouldSetupDtlsSrtp_n()) {
guoweis46383312015-12-17 16:45:59 -0800287 // Set |writable_| to false such that UpdateWritableState_w can set up
288 // DTLS-SRTP when the writable_ becomes true again.
289 writable_ = false;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800290 srtp_filter_.ResetParams();
291 }
292
guoweis46383312015-12-17 16:45:59 -0800293 // TODO(guoweis): Remove this grossness when we remove non-muxed RTCP.
deadbeefcbecd352015-09-23 11:50:27 -0700294 if (rtcp_transport_enabled()) {
295 LOG(LS_INFO) << "Create RTCP TransportChannel for " << content_name()
296 << " on " << transport_name << " transport ";
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200297 SetRtcpTransportChannel_n(
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200298 transport_controller_->CreateTransportChannel_n(
guoweis46383312015-12-17 16:45:59 -0800299 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP),
300 false /* update_writablity */);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200301 if (!rtcp_transport_channel_) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000302 return false;
303 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000304 }
305
guoweis46383312015-12-17 16:45:59 -0800306 // We're not updating the writablity during the transition state.
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200307 SetTransportChannel_n(transport_controller_->CreateTransportChannel_n(
guoweis46383312015-12-17 16:45:59 -0800308 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200309 if (!transport_channel_) {
guoweis46383312015-12-17 16:45:59 -0800310 return false;
311 }
312
313 // TODO(guoweis): Remove this grossness when we remove non-muxed RTCP.
314 if (rtcp_transport_enabled()) {
315 // We can only update the RTCP ready to send after set_transport_channel has
316 // handled channel writability.
317 SetReadyToSend(
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200318 true, rtcp_transport_channel_ && rtcp_transport_channel_->writable());
guoweis46383312015-12-17 16:45:59 -0800319 }
deadbeefcbecd352015-09-23 11:50:27 -0700320 transport_name_ = transport_name;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000321 return true;
322}
323
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200324void BaseChannel::SetTransportChannel_n(TransportChannel* new_tc) {
325 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000326
327 TransportChannel* old_tc = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700328 if (!old_tc && !new_tc) {
329 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000330 return;
331 }
deadbeefcbecd352015-09-23 11:50:27 -0700332 ASSERT(old_tc != new_tc);
333
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000334 if (old_tc) {
335 DisconnectFromTransportChannel(old_tc);
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200336 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700337 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000338 }
339
340 transport_channel_ = new_tc;
341
342 if (new_tc) {
343 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700344 for (const auto& pair : socket_options_) {
345 new_tc->SetOption(pair.first, pair.second);
346 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000347 }
deadbeefcbecd352015-09-23 11:50:27 -0700348
349 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
350 // setting new channel
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200351 UpdateWritableState_n();
deadbeefcbecd352015-09-23 11:50:27 -0700352 SetReadyToSend(false, new_tc && new_tc->writable());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000353}
354
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200355void BaseChannel::SetRtcpTransportChannel_n(TransportChannel* new_tc,
356 bool update_writablity) {
357 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000358
359 TransportChannel* old_tc = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700360 if (!old_tc && !new_tc) {
361 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000362 return;
363 }
deadbeefcbecd352015-09-23 11:50:27 -0700364 ASSERT(old_tc != new_tc);
365
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000366 if (old_tc) {
367 DisconnectFromTransportChannel(old_tc);
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200368 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700369 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000370 }
371
372 rtcp_transport_channel_ = new_tc;
373
374 if (new_tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200375 RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_filter_.IsActive()))
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800376 << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
377 << "should never happen.";
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000378 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700379 for (const auto& pair : rtcp_socket_options_) {
380 new_tc->SetOption(pair.first, pair.second);
381 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000382 }
deadbeefcbecd352015-09-23 11:50:27 -0700383
guoweis46383312015-12-17 16:45:59 -0800384 if (update_writablity) {
385 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
386 // setting new channel
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200387 UpdateWritableState_n();
guoweis46383312015-12-17 16:45:59 -0800388 SetReadyToSend(true, new_tc && new_tc->writable());
389 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000390}
391
392void BaseChannel::ConnectToTransportChannel(TransportChannel* tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200393 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000394
395 tc->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
396 tc->SignalReadPacket.connect(this, &BaseChannel::OnChannelRead);
397 tc->SignalReadyToSend.connect(this, &BaseChannel::OnReadyToSend);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800398 tc->SignalDtlsState.connect(this, &BaseChannel::OnDtlsState);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700399 tc->SignalSelectedCandidatePairChanged.connect(
400 this, &BaseChannel::OnSelectedCandidatePairChanged);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200401 tc->SignalSentPacket.connect(this, &BaseChannel::SignalSentPacket_n);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000402}
403
404void BaseChannel::DisconnectFromTransportChannel(TransportChannel* tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200405 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000406
407 tc->SignalWritableState.disconnect(this);
408 tc->SignalReadPacket.disconnect(this);
409 tc->SignalReadyToSend.disconnect(this);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800410 tc->SignalDtlsState.disconnect(this);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200411 tc->SignalSelectedCandidatePairChanged.disconnect(this);
412 tc->SignalSentPacket.disconnect(this);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000413}
414
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000415bool BaseChannel::Enable(bool enable) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000416 worker_thread_->Invoke<void>(Bind(
417 enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
418 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000419 return true;
420}
421
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000422bool BaseChannel::AddRecvStream(const StreamParams& sp) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000423 return InvokeOnWorker(Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000424}
425
Peter Boström0c4e06b2015-10-07 12:23:21 +0200426bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000427 return InvokeOnWorker(Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000428}
429
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000430bool BaseChannel::AddSendStream(const StreamParams& sp) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000431 return InvokeOnWorker(
432 Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000433}
434
Peter Boström0c4e06b2015-10-07 12:23:21 +0200435bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000436 return InvokeOnWorker(
437 Bind(&MediaChannel::RemoveSendStream, media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000438}
439
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000441 ContentAction action,
442 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100443 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000444 return InvokeOnWorker(Bind(&BaseChannel::SetLocalContent_w,
445 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000446}
447
448bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000449 ContentAction action,
450 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100451 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000452 return InvokeOnWorker(Bind(&BaseChannel::SetRemoteContent_w,
453 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000454}
455
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000456void BaseChannel::StartConnectionMonitor(int cms) {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000457 // We pass in the BaseChannel instead of the transport_channel_
458 // because if the transport_channel_ changes, the ConnectionMonitor
459 // would be pointing to the wrong TransportChannel.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200460 // We pass in the network thread because on that thread connection monitor
461 // will call BaseChannel::GetConnectionStats which must be called on the
462 // network thread.
463 connection_monitor_.reset(
464 new ConnectionMonitor(this, network_thread(), rtc::Thread::Current()));
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000465 connection_monitor_->SignalUpdate.connect(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000466 this, &BaseChannel::OnConnectionMonitorUpdate);
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000467 connection_monitor_->Start(cms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000468}
469
470void BaseChannel::StopConnectionMonitor() {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000471 if (connection_monitor_) {
472 connection_monitor_->Stop();
473 connection_monitor_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000474 }
475}
476
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000477bool BaseChannel::GetConnectionStats(ConnectionInfos* infos) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200478 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000479 return transport_channel_->GetStats(infos);
480}
481
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200482bool BaseChannel::IsReadyToReceive_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000483 // Receive data if we are enabled and have local content,
484 return enabled() && IsReceiveContentDirection(local_content_direction_);
485}
486
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200487bool BaseChannel::IsReadyToSend_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488 // Send outgoing data if we are enabled, have local and remote content,
489 // and we have had some form of connectivity.
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800490 return enabled() && IsReceiveContentDirection(remote_content_direction_) &&
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000491 IsSendContentDirection(local_content_direction_) &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200492 network_thread_->Invoke<bool>(
493 Bind(&BaseChannel::IsTransportReadyToSend_n, this));
494}
495
496bool BaseChannel::IsTransportReadyToSend_n() const {
497 return was_ever_writable() &&
498 (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp_n());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000499}
500
jbaucheec21bd2016-03-20 06:15:43 -0700501bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700502 const rtc::PacketOptions& options) {
503 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000504}
505
jbaucheec21bd2016-03-20 06:15:43 -0700506bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700507 const rtc::PacketOptions& options) {
508 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000509}
510
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000511int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000512 int value) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200513 return network_thread_->Invoke<int>(
514 Bind(&BaseChannel::SetOption_n, this, type, opt, value));
515}
516
517int BaseChannel::SetOption_n(SocketType type,
518 rtc::Socket::Option opt,
519 int value) {
520 RTC_DCHECK(network_thread_->IsCurrent());
521 TransportChannel* channel = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000522 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000523 case ST_RTP:
524 channel = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700525 socket_options_.push_back(
526 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000527 break;
528 case ST_RTCP:
529 channel = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700530 rtcp_socket_options_.push_back(
531 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000532 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000533 }
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000534 return channel ? channel->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000535}
536
537void BaseChannel::OnWritableState(TransportChannel* channel) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200538 RTC_DCHECK(channel == transport_channel_ ||
539 channel == rtcp_transport_channel_);
540 RTC_DCHECK(network_thread_->IsCurrent());
541 UpdateWritableState_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000542}
543
544void BaseChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000545 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000546 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000547 int flags) {
Peter Boström6f28cf02015-12-07 23:17:15 +0100548 TRACE_EVENT0("webrtc", "BaseChannel::OnChannelRead");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000549 // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200550 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000551
552 // When using RTCP multiplexing we might get RTCP packets on the RTP
553 // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
554 bool rtcp = PacketIsRtcp(channel, data, len);
jbaucheec21bd2016-03-20 06:15:43 -0700555 rtc::CopyOnWriteBuffer packet(data, len);
wu@webrtc.orga9890802013-12-13 00:21:03 +0000556 HandlePacket(rtcp, &packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000557}
558
559void BaseChannel::OnReadyToSend(TransportChannel* channel) {
deadbeefcbecd352015-09-23 11:50:27 -0700560 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
561 SetReadyToSend(channel == rtcp_transport_channel_, true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000562}
563
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800564void BaseChannel::OnDtlsState(TransportChannel* channel,
565 DtlsTransportState state) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200566 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800567 return;
568 }
569
570 // Reset the srtp filter if it's not the CONNECTED state. For the CONNECTED
571 // state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to
572 // cover other scenarios like the whole channel is writable (not just this
573 // TransportChannel) or when TransportChannel is attached after DTLS is
574 // negotiated.
575 if (state != DTLS_TRANSPORT_CONNECTED) {
576 srtp_filter_.ResetParams();
577 }
578}
579
Honghai Zhangcc411c02016-03-29 17:27:21 -0700580void BaseChannel::OnSelectedCandidatePairChanged(
581 TransportChannel* channel,
Honghai Zhang52dce732016-03-31 12:37:31 -0700582 CandidatePairInterface* selected_candidate_pair,
583 int last_sent_packet_id) {
Honghai Zhangcc411c02016-03-29 17:27:21 -0700584 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200585 RTC_DCHECK(network_thread_->IsCurrent());
586 std::string transport_name = channel->transport_name();
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700587 rtc::NetworkRoute network_route;
Honghai Zhangcc411c02016-03-29 17:27:21 -0700588 if (selected_candidate_pair) {
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700589 network_route = rtc::NetworkRoute(
590 selected_candidate_pair->local_candidate().network_id(),
591 selected_candidate_pair->remote_candidate().network_id(),
592 last_sent_packet_id);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700593 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200594 invoker_.AsyncInvoke<void>(
595 worker_thread_, Bind(&MediaChannel::OnNetworkRouteChanged, media_channel_,
596 transport_name, network_route));
Honghai Zhangcc411c02016-03-29 17:27:21 -0700597}
598
deadbeefcbecd352015-09-23 11:50:27 -0700599void BaseChannel::SetReadyToSend(bool rtcp, bool ready) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200600 RTC_DCHECK(network_thread_->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -0700601 if (rtcp) {
602 rtcp_ready_to_send_ = ready;
603 } else {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000604 rtp_ready_to_send_ = ready;
605 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000606
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200607 bool ready_to_send =
608 (rtp_ready_to_send_ &&
609 // In the case of rtcp mux |rtcp_transport_channel_| will be null.
610 (rtcp_ready_to_send_ || !rtcp_transport_channel_));
611
612 invoker_.AsyncInvoke<void>(
613 worker_thread_,
614 Bind(&MediaChannel::OnReadyToSend, media_channel_, ready_to_send));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000615}
616
617bool BaseChannel::PacketIsRtcp(const TransportChannel* channel,
618 const char* data, size_t len) {
619 return (channel == rtcp_transport_channel_ ||
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000620 rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000621}
622
stefanc1aeaf02015-10-15 07:26:07 -0700623bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700624 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700625 const rtc::PacketOptions& options) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200626 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
627 // If the thread is not our network thread, we will post to our network
628 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000629 // synchronize access to all the pieces of the send path, including
630 // SRTP and the inner workings of the transport channels.
631 // The only downside is that we can't return a proper failure code if
632 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200633 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000634 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200635 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
636 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800637 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700638 data->options = options;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200639 network_thread_->Post(this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000640 return true;
641 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200642 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000643
644 // Now that we are on the correct thread, ensure we have a place to send this
645 // packet before doing anything. (We might get RTCP packets that we don't
646 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
647 // transport.
648 TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
649 transport_channel_ : rtcp_transport_channel_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000650 if (!channel || !channel->writable()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000651 return false;
652 }
653
654 // Protect ourselves against crazy data.
655 if (!ValidPacket(rtcp, packet)) {
656 LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000657 << PacketType(rtcp)
658 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000659 return false;
660 }
661
stefanc1aeaf02015-10-15 07:26:07 -0700662 rtc::PacketOptions updated_options;
663 updated_options = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000664 // Protect if needed.
665 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200666 TRACE_EVENT0("webrtc", "SRTP Encode");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000667 bool res;
Karl Wibergc56ac1e2015-05-04 14:54:55 +0200668 uint8_t* data = packet->data();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000669 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000670 if (!rtcp) {
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000671 // If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
672 // inside libsrtp for a RTP packet. A external HMAC module will be writing
673 // a fake HMAC value. This is ONLY done for a RTP packet.
674 // Socket layer will update rtp sendtime extension header if present in
675 // packet with current time before updating the HMAC.
676#if !defined(ENABLE_EXTERNAL_AUTH)
677 res = srtp_filter_.ProtectRtp(
678 data, len, static_cast<int>(packet->capacity()), &len);
679#else
stefanc1aeaf02015-10-15 07:26:07 -0700680 updated_options.packet_time_params.rtp_sendtime_extension_id =
henrike@webrtc.org05376342014-03-10 15:53:12 +0000681 rtp_abs_sendtime_extn_id_;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000682 res = srtp_filter_.ProtectRtp(
683 data, len, static_cast<int>(packet->capacity()), &len,
stefanc1aeaf02015-10-15 07:26:07 -0700684 &updated_options.packet_time_params.srtp_packet_index);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000685 // If protection succeeds, let's get auth params from srtp.
686 if (res) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200687 uint8_t* auth_key = NULL;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000688 int key_len;
689 res = srtp_filter_.GetRtpAuthParams(
stefanc1aeaf02015-10-15 07:26:07 -0700690 &auth_key, &key_len,
691 &updated_options.packet_time_params.srtp_auth_tag_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000692 if (res) {
stefanc1aeaf02015-10-15 07:26:07 -0700693 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
694 updated_options.packet_time_params.srtp_auth_key.assign(
695 auth_key, auth_key + key_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000696 }
697 }
698#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000699 if (!res) {
700 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200701 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000702 GetRtpSeqNum(data, len, &seq_num);
703 GetRtpSsrc(data, len, &ssrc);
704 LOG(LS_ERROR) << "Failed to protect " << content_name_
705 << " RTP packet: size=" << len
706 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
707 return false;
708 }
709 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000710 res = srtp_filter_.ProtectRtcp(data, len,
711 static_cast<int>(packet->capacity()),
712 &len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000713 if (!res) {
714 int type = -1;
715 GetRtcpType(data, len, &type);
716 LOG(LS_ERROR) << "Failed to protect " << content_name_
717 << " RTCP packet: size=" << len << ", type=" << type;
718 return false;
719 }
720 }
721
722 // Update the length of the packet now that we've added the auth tag.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000723 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000724 } else if (secure_required_) {
725 // This is a double check for something that supposedly can't happen.
726 LOG(LS_ERROR) << "Can't send outgoing " << PacketType(rtcp)
727 << " packet when SRTP is inactive and crypto is required";
728
729 ASSERT(false);
730 return false;
731 }
732
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000733 // Bon voyage.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200734 int flags = (secure() && secure_dtls()) ? PF_SRTP_BYPASS : PF_NORMAL;
735 int ret = channel->SendPacket(packet->data<char>(), packet->size(),
736 updated_options, flags);
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000737 if (ret != static_cast<int>(packet->size())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000738 if (channel->GetError() == EWOULDBLOCK) {
739 LOG(LS_WARNING) << "Got EWOULDBLOCK from socket.";
deadbeefcbecd352015-09-23 11:50:27 -0700740 SetReadyToSend(rtcp, false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000741 }
742 return false;
743 }
744 return true;
745}
746
jbaucheec21bd2016-03-20 06:15:43 -0700747bool BaseChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000748 // Protect ourselves against crazy data.
749 if (!ValidPacket(rtcp, packet)) {
750 LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000751 << PacketType(rtcp)
752 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000753 return false;
754 }
pbos482b12e2015-11-16 10:19:58 -0800755 if (rtcp) {
756 // Permit all (seemingly valid) RTCP packets.
757 return true;
758 }
759 // Check whether we handle this payload.
jbaucheec21bd2016-03-20 06:15:43 -0700760 return bundle_filter_.DemuxPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000761}
762
jbaucheec21bd2016-03-20 06:15:43 -0700763void BaseChannel::HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000764 const rtc::PacketTime& packet_time) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200765 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000766 if (!WantsPacket(rtcp, packet)) {
767 return;
768 }
769
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000770 // We are only interested in the first rtp packet because that
771 // indicates the media has started flowing.
772 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000773 has_received_packet_ = true;
774 signaling_thread()->Post(this, MSG_FIRSTPACKETRECEIVED);
775 }
776
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000777 // Unprotect the packet, if needed.
778 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200779 TRACE_EVENT0("webrtc", "SRTP Decode");
Karl Wiberg94784372015-04-20 14:03:07 +0200780 char* data = packet->data<char>();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000781 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000782 bool res;
783 if (!rtcp) {
784 res = srtp_filter_.UnprotectRtp(data, len, &len);
785 if (!res) {
786 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200787 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000788 GetRtpSeqNum(data, len, &seq_num);
789 GetRtpSsrc(data, len, &ssrc);
790 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
791 << " RTP packet: size=" << len
792 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
793 return;
794 }
795 } else {
796 res = srtp_filter_.UnprotectRtcp(data, len, &len);
797 if (!res) {
798 int type = -1;
799 GetRtcpType(data, len, &type);
800 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
801 << " RTCP packet: size=" << len << ", type=" << type;
802 return;
803 }
804 }
805
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000806 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000807 } else if (secure_required_) {
808 // Our session description indicates that SRTP is required, but we got a
809 // packet before our SRTP filter is active. This means either that
810 // a) we got SRTP packets before we received the SDES keys, in which case
811 // we can't decrypt it anyway, or
812 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
813 // channels, so we haven't yet extracted keys, even if DTLS did complete
814 // on the channel that the packets are being sent on. It's really good
815 // practice to wait for both RTP and RTCP to be good to go before sending
816 // media, to prevent weird failure modes, so it's fine for us to just eat
817 // packets here. This is all sidestepped if RTCP mux is used anyway.
818 LOG(LS_WARNING) << "Can't process incoming " << PacketType(rtcp)
819 << " packet when SRTP is inactive and crypto is required";
820 return;
821 }
822
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200823 invoker_.AsyncInvoke<void>(
824 worker_thread_,
825 Bind(&BaseChannel::OnPacketReceived, this, rtcp, *packet, packet_time));
826}
827
828void BaseChannel::OnPacketReceived(bool rtcp,
829 const rtc::CopyOnWriteBuffer& packet,
830 const rtc::PacketTime& packet_time) {
831 RTC_DCHECK(worker_thread_->IsCurrent());
832 // Need to copy variable because OnRtcpReceived/OnPacketReceived
833 // requires non-const pointer to buffer. This doesn't memcpy the actual data.
834 rtc::CopyOnWriteBuffer data(packet);
835 if (rtcp) {
836 media_channel_->OnRtcpReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000837 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200838 media_channel_->OnPacketReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000839 }
840}
841
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000842bool BaseChannel::PushdownLocalDescription(
843 const SessionDescription* local_desc, ContentAction action,
844 std::string* error_desc) {
845 const ContentInfo* content_info = GetFirstContent(local_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000846 const MediaContentDescription* content_desc =
847 GetContentDescription(content_info);
848 if (content_desc && content_info && !content_info->rejected &&
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000849 !SetLocalContent(content_desc, action, error_desc)) {
850 LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
851 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000852 }
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000853 return true;
854}
855
856bool BaseChannel::PushdownRemoteDescription(
857 const SessionDescription* remote_desc, ContentAction action,
858 std::string* error_desc) {
859 const ContentInfo* content_info = GetFirstContent(remote_desc);
860 const MediaContentDescription* content_desc =
861 GetContentDescription(content_info);
862 if (content_desc && content_info && !content_info->rejected &&
863 !SetRemoteContent(content_desc, action, error_desc)) {
864 LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
865 return false;
866 }
867 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000868}
869
870void BaseChannel::EnableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000871 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000872 if (enabled_)
873 return;
874
875 LOG(LS_INFO) << "Channel enabled";
876 enabled_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200877 ChangeState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000878}
879
880void BaseChannel::DisableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000881 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000882 if (!enabled_)
883 return;
884
885 LOG(LS_INFO) << "Channel disabled";
886 enabled_ = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200887 ChangeState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000888}
889
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200890void BaseChannel::UpdateWritableState_n() {
deadbeefcbecd352015-09-23 11:50:27 -0700891 if (transport_channel_ && transport_channel_->writable() &&
892 (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200893 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700894 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200895 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700896 }
897}
898
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200899void BaseChannel::ChannelWritable_n() {
900 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800901 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000902 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800903 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000904
deadbeefcbecd352015-09-23 11:50:27 -0700905 LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000906 << (was_ever_writable_ ? "" : " for the first time");
907
908 std::vector<ConnectionInfo> infos;
909 transport_channel_->GetStats(&infos);
910 for (std::vector<ConnectionInfo>::const_iterator it = infos.begin();
911 it != infos.end(); ++it) {
912 if (it->best_connection) {
913 LOG(LS_INFO) << "Using " << it->local_candidate.ToSensitiveString()
914 << "->" << it->remote_candidate.ToSensitiveString();
915 break;
916 }
917 }
918
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000919 was_ever_writable_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200920 MaybeSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000921 writable_ = true;
922 ChangeState();
923}
924
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200925void BaseChannel::SignalDtlsSetupFailure_n(bool rtcp) {
926 RTC_DCHECK(network_thread_->IsCurrent());
927 invoker_.AsyncInvoke<void>(
928 signaling_thread(),
929 Bind(&BaseChannel::SignalDtlsSetupFailure_s, this, rtcp));
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000930}
931
932void BaseChannel::SignalDtlsSetupFailure_s(bool rtcp) {
933 ASSERT(signaling_thread() == rtc::Thread::Current());
934 SignalDtlsSetupFailure(this, rtcp);
935}
936
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200937bool BaseChannel::SetDtlsSrtpCryptoSuites_n(TransportChannel* tc, bool rtcp) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800938 std::vector<int> crypto_suites;
939 // We always use the default SRTP crypto suites for RTCP, but we may use
940 // different crypto suites for RTP depending on the media type.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000941 if (!rtcp) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200942 GetSrtpCryptoSuites_n(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000943 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800944 GetDefaultSrtpCryptoSuites(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000945 }
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800946 return tc->SetSrtpCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000947}
948
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200949bool BaseChannel::ShouldSetupDtlsSrtp_n() const {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800950 // Since DTLS is applied to all channels, checking RTP should be enough.
951 return transport_channel_ && transport_channel_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000952}
953
954// This function returns true if either DTLS-SRTP is not in use
955// *or* DTLS-SRTP is successfully set up.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200956bool BaseChannel::SetupDtlsSrtp_n(bool rtcp_channel) {
957 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000958 bool ret = false;
959
deadbeefcbecd352015-09-23 11:50:27 -0700960 TransportChannel* channel =
961 rtcp_channel ? rtcp_transport_channel_ : transport_channel_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000962
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800963 RTC_DCHECK(channel->IsDtlsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000964
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800965 int selected_crypto_suite;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000966
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800967 if (!channel->GetSrtpCryptoSuite(&selected_crypto_suite)) {
968 LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000969 return false;
970 }
971
972 LOG(LS_INFO) << "Installing keys from DTLS-SRTP on "
973 << content_name() << " "
974 << PacketType(rtcp_channel);
975
976 // OK, we're now doing DTLS (RFC 5764)
977 std::vector<unsigned char> dtls_buffer(SRTP_MASTER_KEY_KEY_LEN * 2 +
978 SRTP_MASTER_KEY_SALT_LEN * 2);
979
980 // RFC 5705 exporter using the RFC 5764 parameters
981 if (!channel->ExportKeyingMaterial(
982 kDtlsSrtpExporterLabel,
983 NULL, 0, false,
984 &dtls_buffer[0], dtls_buffer.size())) {
985 LOG(LS_WARNING) << "DTLS-SRTP key export failed";
986 ASSERT(false); // This should never happen
987 return false;
988 }
989
990 // Sync up the keys with the DTLS-SRTP interface
991 std::vector<unsigned char> client_write_key(SRTP_MASTER_KEY_KEY_LEN +
992 SRTP_MASTER_KEY_SALT_LEN);
993 std::vector<unsigned char> server_write_key(SRTP_MASTER_KEY_KEY_LEN +
994 SRTP_MASTER_KEY_SALT_LEN);
995 size_t offset = 0;
996 memcpy(&client_write_key[0], &dtls_buffer[offset],
997 SRTP_MASTER_KEY_KEY_LEN);
998 offset += SRTP_MASTER_KEY_KEY_LEN;
999 memcpy(&server_write_key[0], &dtls_buffer[offset],
1000 SRTP_MASTER_KEY_KEY_LEN);
1001 offset += SRTP_MASTER_KEY_KEY_LEN;
1002 memcpy(&client_write_key[SRTP_MASTER_KEY_KEY_LEN],
1003 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
1004 offset += SRTP_MASTER_KEY_SALT_LEN;
1005 memcpy(&server_write_key[SRTP_MASTER_KEY_KEY_LEN],
1006 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
1007
1008 std::vector<unsigned char> *send_key, *recv_key;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001009 rtc::SSLRole role;
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00001010 if (!channel->GetSslRole(&role)) {
1011 LOG(LS_WARNING) << "GetSslRole failed";
1012 return false;
1013 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001014
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001015 if (role == rtc::SSL_SERVER) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001016 send_key = &server_write_key;
1017 recv_key = &client_write_key;
1018 } else {
1019 send_key = &client_write_key;
1020 recv_key = &server_write_key;
1021 }
1022
1023 if (rtcp_channel) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001024 ret = srtp_filter_.SetRtcpParams(selected_crypto_suite, &(*send_key)[0],
1025 static_cast<int>(send_key->size()),
1026 selected_crypto_suite, &(*recv_key)[0],
1027 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001028 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001029 ret = srtp_filter_.SetRtpParams(selected_crypto_suite, &(*send_key)[0],
1030 static_cast<int>(send_key->size()),
1031 selected_crypto_suite, &(*recv_key)[0],
1032 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001033 }
1034
1035 if (!ret)
1036 LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
1037 else
1038 dtls_keyed_ = true;
1039
1040 return ret;
1041}
1042
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001043void BaseChannel::MaybeSetupDtlsSrtp_n() {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001044 if (srtp_filter_.IsActive()) {
1045 return;
1046 }
1047
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001048 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001049 return;
1050 }
1051
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001052 if (!SetupDtlsSrtp_n(false)) {
1053 SignalDtlsSetupFailure_n(false);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001054 return;
1055 }
1056
1057 if (rtcp_transport_channel_) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001058 if (!SetupDtlsSrtp_n(true)) {
1059 SignalDtlsSetupFailure_n(true);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001060 return;
1061 }
1062 }
1063}
1064
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001065void BaseChannel::ChannelNotWritable_n() {
1066 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001067 if (!writable_)
1068 return;
1069
deadbeefcbecd352015-09-23 11:50:27 -07001070 LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001071 writable_ = false;
1072 ChangeState();
1073}
1074
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001075bool BaseChannel::SetRtpTransportParameters(
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001076 const MediaContentDescription* content,
1077 ContentAction action,
1078 ContentSource src,
1079 std::string* error_desc) {
1080 if (action == CA_UPDATE) {
1081 // These parameters never get changed by a CA_UDPATE.
1082 return true;
1083 }
1084
1085 // Cache secure_required_ for belt and suspenders check on SendPacket
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001086 return network_thread_->Invoke<bool>(
1087 Bind(&BaseChannel::SetRtpTransportParameters_n, this, content, action,
1088 src, error_desc));
1089}
1090
1091bool BaseChannel::SetRtpTransportParameters_n(
1092 const MediaContentDescription* content,
1093 ContentAction action,
1094 ContentSource src,
1095 std::string* error_desc) {
1096 RTC_DCHECK(network_thread_->IsCurrent());
1097
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001098 if (src == CS_LOCAL) {
1099 set_secure_required(content->crypto_required() != CT_NONE);
1100 }
1101
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001102 if (!SetSrtp_n(content->cryptos(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001103 return false;
1104 }
1105
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001106 if (!SetRtcpMux_n(content->rtcp_mux(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001107 return false;
1108 }
1109
1110 return true;
1111}
1112
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001113// |dtls| will be set to true if DTLS is active for transport channel and
1114// crypto is empty.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001115bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
1116 bool* dtls,
1117 std::string* error_desc) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001118 *dtls = transport_channel_->IsDtlsActive();
1119 if (*dtls && !cryptos.empty()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001120 SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001121 return false;
1122 }
1123 return true;
1124}
1125
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001126bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001127 ContentAction action,
1128 ContentSource src,
1129 std::string* error_desc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001130 TRACE_EVENT0("webrtc", "BaseChannel::SetSrtp_w");
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001131 if (action == CA_UPDATE) {
1132 // no crypto params.
1133 return true;
1134 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001135 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001136 bool dtls = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001137 ret = CheckSrtpConfig_n(cryptos, &dtls, error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001138 if (!ret) {
1139 return false;
1140 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001141 switch (action) {
1142 case CA_OFFER:
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001143 // If DTLS is already active on the channel, we could be renegotiating
1144 // here. We don't update the srtp filter.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001145 if (!dtls) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001146 ret = srtp_filter_.SetOffer(cryptos, src);
1147 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001148 break;
1149 case CA_PRANSWER:
1150 // If we're doing DTLS-SRTP, we don't want to update the filter
1151 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001152 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001153 ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
1154 }
1155 break;
1156 case CA_ANSWER:
1157 // If we're doing DTLS-SRTP, we don't want to update the filter
1158 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001159 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001160 ret = srtp_filter_.SetAnswer(cryptos, src);
1161 }
1162 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001163 default:
1164 break;
1165 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001166 if (!ret) {
1167 SafeSetError("Failed to setup SRTP filter.", error_desc);
1168 return false;
1169 }
1170 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001171}
1172
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001173void BaseChannel::ActivateRtcpMux() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001174 network_thread_->Invoke<void>(Bind(&BaseChannel::ActivateRtcpMux_n, this));
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001175}
1176
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001177void BaseChannel::ActivateRtcpMux_n() {
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001178 if (!rtcp_mux_filter_.IsActive()) {
1179 rtcp_mux_filter_.SetActive();
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001180 SetRtcpTransportChannel_n(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001181 rtcp_transport_enabled_ = false;
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001182 }
1183}
1184
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001185bool BaseChannel::SetRtcpMux_n(bool enable,
1186 ContentAction action,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001187 ContentSource src,
1188 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001189 bool ret = false;
1190 switch (action) {
1191 case CA_OFFER:
1192 ret = rtcp_mux_filter_.SetOffer(enable, src);
1193 break;
1194 case CA_PRANSWER:
1195 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
1196 break;
1197 case CA_ANSWER:
1198 ret = rtcp_mux_filter_.SetAnswer(enable, src);
1199 if (ret && rtcp_mux_filter_.IsActive()) {
1200 // We activated RTCP mux, close down the RTCP transport.
deadbeefcbecd352015-09-23 11:50:27 -07001201 LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
1202 << " by destroying RTCP transport channel for "
1203 << transport_name();
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001204 SetRtcpTransportChannel_n(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001205 rtcp_transport_enabled_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001206 }
1207 break;
1208 case CA_UPDATE:
1209 // No RTCP mux info.
1210 ret = true;
Henrik Kjellander7c027b62015-04-22 13:21:30 +02001211 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001212 default:
1213 break;
1214 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001215 if (!ret) {
1216 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
1217 return false;
1218 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001219 // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
1220 // CA_ANSWER, but we only want to tear down the RTCP transport channel if we
1221 // received a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001222 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001223 // If the RTP transport is already writable, then so are we.
1224 if (transport_channel_->writable()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001225 ChannelWritable_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001226 }
1227 }
1228
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001229 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001230}
1231
1232bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001233 ASSERT(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -08001234 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001235}
1236
Peter Boström0c4e06b2015-10-07 12:23:21 +02001237bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001238 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001239 return media_channel()->RemoveRecvStream(ssrc);
1240}
1241
1242bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001243 ContentAction action,
1244 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001245 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1246 action == CA_PRANSWER || action == CA_UPDATE))
1247 return false;
1248
1249 // If this is an update, streams only contain streams that have changed.
1250 if (action == CA_UPDATE) {
1251 for (StreamParamsVec::const_iterator it = streams.begin();
1252 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001253 const StreamParams* existing_stream =
1254 GetStreamByIds(local_streams_, it->groupid, it->id);
1255 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001256 if (media_channel()->AddSendStream(*it)) {
1257 local_streams_.push_back(*it);
1258 LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
1259 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001260 std::ostringstream desc;
1261 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1262 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001263 return false;
1264 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001265 } else if (existing_stream && !it->has_ssrcs()) {
1266 if (!media_channel()->RemoveSendStream(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001267 std::ostringstream desc;
1268 desc << "Failed to remove send stream with ssrc "
1269 << it->first_ssrc() << ".";
1270 SafeSetError(desc.str(), error_desc);
1271 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001272 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001273 RemoveStreamBySsrc(&local_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001274 } else {
1275 LOG(LS_WARNING) << "Ignore unsupported stream update";
1276 }
1277 }
1278 return true;
1279 }
1280 // Else streams are all the streams we want to send.
1281
1282 // Check for streams that have been removed.
1283 bool ret = true;
1284 for (StreamParamsVec::const_iterator it = local_streams_.begin();
1285 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001286 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001287 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001288 std::ostringstream desc;
1289 desc << "Failed to remove send stream with ssrc "
1290 << it->first_ssrc() << ".";
1291 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001292 ret = false;
1293 }
1294 }
1295 }
1296 // Check for new streams.
1297 for (StreamParamsVec::const_iterator it = streams.begin();
1298 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001299 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001300 if (media_channel()->AddSendStream(*it)) {
stefanc1aeaf02015-10-15 07:26:07 -07001301 LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001302 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001303 std::ostringstream desc;
1304 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1305 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306 ret = false;
1307 }
1308 }
1309 }
1310 local_streams_ = streams;
1311 return ret;
1312}
1313
1314bool BaseChannel::UpdateRemoteStreams_w(
1315 const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001316 ContentAction action,
1317 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001318 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1319 action == CA_PRANSWER || action == CA_UPDATE))
1320 return false;
1321
1322 // If this is an update, streams only contain streams that have changed.
1323 if (action == CA_UPDATE) {
1324 for (StreamParamsVec::const_iterator it = streams.begin();
1325 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001326 const StreamParams* existing_stream =
1327 GetStreamByIds(remote_streams_, it->groupid, it->id);
1328 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001329 if (AddRecvStream_w(*it)) {
1330 remote_streams_.push_back(*it);
1331 LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
1332 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001333 std::ostringstream desc;
1334 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1335 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001336 return false;
1337 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001338 } else if (existing_stream && !it->has_ssrcs()) {
1339 if (!RemoveRecvStream_w(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001340 std::ostringstream desc;
1341 desc << "Failed to remove remote stream with ssrc "
1342 << it->first_ssrc() << ".";
1343 SafeSetError(desc.str(), error_desc);
1344 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001345 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001346 RemoveStreamBySsrc(&remote_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001347 } else {
1348 LOG(LS_WARNING) << "Ignore unsupported stream update."
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001349 << " Stream exists? " << (existing_stream != nullptr)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001350 << " new stream = " << it->ToString();
1351 }
1352 }
1353 return true;
1354 }
1355 // Else streams are all the streams we want to receive.
1356
1357 // Check for streams that have been removed.
1358 bool ret = true;
1359 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
1360 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001361 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001362 if (!RemoveRecvStream_w(it->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);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001367 ret = false;
1368 }
1369 }
1370 }
1371 // Check for new streams.
1372 for (StreamParamsVec::const_iterator it = streams.begin();
1373 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001374 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001375 if (AddRecvStream_w(*it)) {
1376 LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
1377 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001378 std::ostringstream desc;
1379 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1380 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001381 ret = false;
1382 }
1383 }
1384 }
1385 remote_streams_ = streams;
1386 return ret;
1387}
1388
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001389void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w(
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001390 const std::vector<RtpHeaderExtension>& extensions) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001391// Absolute Send Time extension id is used only with external auth,
1392// so do not bother searching for it and making asyncronious call to set
1393// something that is not used.
1394#if defined(ENABLE_EXTERNAL_AUTH)
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001395 const RtpHeaderExtension* send_time_extension =
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001396 FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001397 int rtp_abs_sendtime_extn_id =
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001398 send_time_extension ? send_time_extension->id : -1;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001399 invoker_.AsyncInvoke<void>(
1400 network_thread_, Bind(&BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n,
1401 this, rtp_abs_sendtime_extn_id));
1402#endif
1403}
1404
1405void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n(
1406 int rtp_abs_sendtime_extn_id) {
1407 rtp_abs_sendtime_extn_id_ = rtp_abs_sendtime_extn_id;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001408}
1409
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001410void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001411 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001412 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001413 case MSG_SEND_RTP_PACKET:
1414 case MSG_SEND_RTCP_PACKET: {
1415 RTC_DCHECK(network_thread_->IsCurrent());
1416 SendPacketMessageData* data =
1417 static_cast<SendPacketMessageData*>(pmsg->pdata);
1418 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
1419 SendPacket(rtcp, &data->packet, data->options);
1420 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001421 break;
1422 }
1423 case MSG_FIRSTPACKETRECEIVED: {
1424 SignalFirstPacketReceived(this);
1425 break;
1426 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001427 }
1428}
1429
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001430void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001431 // Flush all remaining RTCP messages. This should only be called in
1432 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001433 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001434 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001435 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
1436 for (const auto& message : rtcp_messages) {
1437 network_thread_->Send(this, MSG_SEND_RTCP_PACKET, message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001438 }
1439}
1440
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001441void BaseChannel::SignalSentPacket_n(TransportChannel* /* channel */,
1442 const rtc::SentPacket& sent_packet) {
1443 RTC_DCHECK(network_thread_->IsCurrent());
1444 invoker_.AsyncInvoke<void>(
1445 worker_thread_,
1446 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
1447}
1448
1449void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
1450 RTC_DCHECK(worker_thread_->IsCurrent());
1451 SignalSentPacket(sent_packet);
1452}
1453
1454VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
1455 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001456 MediaEngineInterface* media_engine,
1457 VoiceMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001458 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001459 const std::string& content_name,
1460 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001461 : BaseChannel(worker_thread,
1462 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001463 media_channel,
1464 transport_controller,
1465 content_name,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001466 rtcp),
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001467 media_engine_(media_engine),
deadbeefcbecd352015-09-23 11:50:27 -07001468 received_media_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001469
1470VoiceChannel::~VoiceChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001471 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001472 StopAudioMonitor();
1473 StopMediaMonitor();
1474 // this can't be done in the base class, since it calls a virtual
1475 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001476 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001477}
1478
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001479bool VoiceChannel::Init_w() {
1480 if (!BaseChannel::Init_w()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001481 return false;
1482 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001483 return true;
1484}
1485
Peter Boström0c4e06b2015-10-07 12:23:21 +02001486bool VoiceChannel::SetAudioSend(uint32_t ssrc,
solenbergdfc8f4f2015-10-01 02:31:10 -07001487 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001488 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001489 AudioSource* source) {
deadbeefcbecd352015-09-23 11:50:27 -07001490 return InvokeOnWorker(Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001491 ssrc, enable, options, source));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001492}
1493
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001494// TODO(juberti): Handle early media the right way. We should get an explicit
1495// ringing message telling us to start playing local ringback, which we cancel
1496// if any early media actually arrives. For now, we do the opposite, which is
1497// to wait 1 second for early media, and start playing local ringback if none
1498// arrives.
1499void VoiceChannel::SetEarlyMedia(bool enable) {
1500 if (enable) {
1501 // Start the early media timeout
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001502 worker_thread()->PostDelayed(kEarlyMediaTimeout, this,
1503 MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001504 } else {
1505 // Stop the timeout if currently going.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001506 worker_thread()->Clear(this, MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001507 }
1508}
1509
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001510bool VoiceChannel::CanInsertDtmf() {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001511 return InvokeOnWorker(Bind(&VoiceMediaChannel::CanInsertDtmf,
1512 media_channel()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001513}
1514
Peter Boström0c4e06b2015-10-07 12:23:21 +02001515bool VoiceChannel::InsertDtmf(uint32_t ssrc,
1516 int event_code,
solenberg1d63dd02015-12-02 12:35:09 -08001517 int duration) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001518 return InvokeOnWorker(Bind(&VoiceChannel::InsertDtmf_w, this,
solenberg1d63dd02015-12-02 12:35:09 -08001519 ssrc, event_code, duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001520}
1521
solenberg4bac9c52015-10-09 02:32:53 -07001522bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) {
1523 return InvokeOnWorker(Bind(&VoiceMediaChannel::SetOutputVolume,
1524 media_channel(), ssrc, volume));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001525}
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001526
Tommif888bb52015-12-12 01:37:01 +01001527void VoiceChannel::SetRawAudioSink(
1528 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -08001529 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
1530 // We need to work around Bind's lack of support for unique_ptr and ownership
deadbeef2d110be2016-01-13 12:00:26 -08001531 // passing. So we invoke to our own little routine that gets a pointer to
1532 // our local variable. This is OK since we're synchronously invoking.
1533 InvokeOnWorker(Bind(&SetRawAudioSink_w, media_channel(), ssrc, &sink));
Tommif888bb52015-12-12 01:37:01 +01001534}
1535
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001536webrtc::RtpParameters VoiceChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001537 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001538 Bind(&VoiceChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001539}
1540
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001541webrtc::RtpParameters VoiceChannel::GetRtpSendParameters_w(
1542 uint32_t ssrc) const {
1543 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001544}
1545
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001546bool VoiceChannel::SetRtpSendParameters(
1547 uint32_t ssrc,
1548 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001549 return InvokeOnWorker(
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001550 Bind(&VoiceChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001551}
1552
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001553bool VoiceChannel::SetRtpSendParameters_w(uint32_t ssrc,
1554 webrtc::RtpParameters parameters) {
1555 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1556}
1557
1558webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters(
1559 uint32_t ssrc) const {
1560 return worker_thread()->Invoke<webrtc::RtpParameters>(
1561 Bind(&VoiceChannel::GetRtpReceiveParameters_w, this, ssrc));
1562}
1563
1564webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters_w(
1565 uint32_t ssrc) const {
1566 return media_channel()->GetRtpReceiveParameters(ssrc);
1567}
1568
1569bool VoiceChannel::SetRtpReceiveParameters(
1570 uint32_t ssrc,
1571 const webrtc::RtpParameters& parameters) {
1572 return InvokeOnWorker(
1573 Bind(&VoiceChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1574}
1575
1576bool VoiceChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1577 webrtc::RtpParameters parameters) {
1578 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001579}
1580
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001581bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001582 return InvokeOnWorker(Bind(&VoiceMediaChannel::GetStats,
1583 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001584}
1585
1586void VoiceChannel::StartMediaMonitor(int cms) {
1587 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001588 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001589 media_monitor_->SignalUpdate.connect(
1590 this, &VoiceChannel::OnMediaMonitorUpdate);
1591 media_monitor_->Start(cms);
1592}
1593
1594void VoiceChannel::StopMediaMonitor() {
1595 if (media_monitor_) {
1596 media_monitor_->Stop();
1597 media_monitor_->SignalUpdate.disconnect(this);
1598 media_monitor_.reset();
1599 }
1600}
1601
1602void VoiceChannel::StartAudioMonitor(int cms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001603 audio_monitor_.reset(new AudioMonitor(this, rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001604 audio_monitor_
1605 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1606 audio_monitor_->Start(cms);
1607}
1608
1609void VoiceChannel::StopAudioMonitor() {
1610 if (audio_monitor_) {
1611 audio_monitor_->Stop();
1612 audio_monitor_.reset();
1613 }
1614}
1615
1616bool VoiceChannel::IsAudioMonitorRunning() const {
1617 return (audio_monitor_.get() != NULL);
1618}
1619
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001620int VoiceChannel::GetInputLevel_w() {
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001621 return media_engine_->GetInputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001622}
1623
1624int VoiceChannel::GetOutputLevel_w() {
1625 return media_channel()->GetOutputLevel();
1626}
1627
1628void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1629 media_channel()->GetActiveStreams(actives);
1630}
1631
1632void VoiceChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001633 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001634 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001635 int flags) {
1636 BaseChannel::OnChannelRead(channel, data, len, packet_time, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001637
1638 // Set a flag when we've received an RTP packet. If we're waiting for early
1639 // media, this will disable the timeout.
1640 if (!received_media_ && !PacketIsRtcp(channel, data, len)) {
1641 received_media_ = true;
1642 }
1643}
1644
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001645void BaseChannel::ChangeState() {
1646 RTC_DCHECK(network_thread_->IsCurrent());
1647 invoker_.AsyncInvoke<void>(worker_thread_,
1648 Bind(&BaseChannel::ChangeState_w, this));
1649}
1650
1651void VoiceChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001652 // Render incoming data if we're the active call, and we have the local
1653 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001654 bool recv = IsReadyToReceive_w();
solenberg5b14b422015-10-01 04:10:31 -07001655 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001656
1657 // Send outgoing data if we're the active call, we have the remote content,
1658 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001659 bool send = IsReadyToSend_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001660 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001661
1662 LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
1663}
1664
1665const ContentInfo* VoiceChannel::GetFirstContent(
1666 const SessionDescription* sdesc) {
1667 return GetFirstAudioContent(sdesc);
1668}
1669
1670bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001671 ContentAction action,
1672 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001673 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001674 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001675 LOG(LS_INFO) << "Setting local voice description";
1676
1677 const AudioContentDescription* audio =
1678 static_cast<const AudioContentDescription*>(content);
1679 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001680 if (!audio) {
1681 SafeSetError("Can't find audio content in local description.", error_desc);
1682 return false;
1683 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001684
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001685 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001686 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001687 }
1688
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001689 AudioRecvParameters recv_params = last_recv_params_;
1690 RtpParametersFromMediaDescription(audio, &recv_params);
1691 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001692 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001693 error_desc);
1694 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001695 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001696 for (const AudioCodec& codec : audio->codecs()) {
1697 bundle_filter()->AddPayloadType(codec.id);
1698 }
1699 last_recv_params_ = recv_params;
1700
1701 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1702 // only give it to the media channel once we have a remote
1703 // description too (without a remote description, we won't be able
1704 // to send them anyway).
1705 if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) {
1706 SafeSetError("Failed to set local audio description streams.", error_desc);
1707 return false;
1708 }
1709
1710 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001711 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001712 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001713}
1714
1715bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001716 ContentAction action,
1717 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001718 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001719 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001720 LOG(LS_INFO) << "Setting remote voice description";
1721
1722 const AudioContentDescription* audio =
1723 static_cast<const AudioContentDescription*>(content);
1724 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001725 if (!audio) {
1726 SafeSetError("Can't find audio content in remote description.", error_desc);
1727 return false;
1728 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001729
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001730 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001731 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001732 }
1733
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001734 AudioSendParameters send_params = last_send_params_;
1735 RtpSendParametersFromMediaDescription(audio, &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001736 if (audio->agc_minus_10db()) {
Karl Wibergbe579832015-11-10 22:34:18 +01001737 send_params.options.adjust_agc_delta = rtc::Optional<int>(kAgcMinus10db);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001738 }
skvladdc1c62c2016-03-16 19:07:43 -07001739
1740 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1741 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001742 SafeSetError("Failed to set remote audio description send parameters.",
1743 error_desc);
1744 return false;
1745 }
1746 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001747
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001748 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1749 // and only give it to the media channel once we have a local
1750 // description too (without a local description, we won't be able to
1751 // recv them anyway).
1752 if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) {
1753 SafeSetError("Failed to set remote audio description streams.", error_desc);
1754 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001755 }
1756
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001757 if (audio->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001758 MaybeCacheRtpAbsSendTimeHeaderExtension_w(audio->rtp_header_extensions());
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001759 }
1760
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001761 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001762 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001763 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001764}
1765
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001766void VoiceChannel::HandleEarlyMediaTimeout() {
1767 // This occurs on the main thread, not the worker thread.
1768 if (!received_media_) {
1769 LOG(LS_INFO) << "No early media received before timeout";
1770 SignalEarlyMediaTimeout(this);
1771 }
1772}
1773
Peter Boström0c4e06b2015-10-07 12:23:21 +02001774bool VoiceChannel::InsertDtmf_w(uint32_t ssrc,
1775 int event,
solenberg1d63dd02015-12-02 12:35:09 -08001776 int duration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001777 if (!enabled()) {
1778 return false;
1779 }
solenberg1d63dd02015-12-02 12:35:09 -08001780 return media_channel()->InsertDtmf(ssrc, event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001781}
1782
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001783void VoiceChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001784 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001785 case MSG_EARLYMEDIATIMEOUT:
1786 HandleEarlyMediaTimeout();
1787 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001788 case MSG_CHANNEL_ERROR: {
1789 VoiceChannelErrorMessageData* data =
1790 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001791 delete data;
1792 break;
1793 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001794 default:
1795 BaseChannel::OnMessage(pmsg);
1796 break;
1797 }
1798}
1799
1800void VoiceChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001801 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001802 SignalConnectionMonitor(this, infos);
1803}
1804
1805void VoiceChannel::OnMediaMonitorUpdate(
1806 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
1807 ASSERT(media_channel == this->media_channel());
1808 SignalMediaMonitor(this, info);
1809}
1810
1811void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1812 const AudioInfo& info) {
1813 SignalAudioMonitor(this, info);
1814}
1815
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001816void VoiceChannel::GetSrtpCryptoSuites_n(
1817 std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001818 GetSupportedAudioCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001819}
1820
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001821VideoChannel::VideoChannel(rtc::Thread* worker_thread,
1822 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001823 VideoMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001824 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001825 const std::string& content_name,
Fredrik Solenberg7fb711f2015-04-22 15:30:51 +02001826 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001827 : BaseChannel(worker_thread,
1828 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001829 media_channel,
1830 transport_controller,
1831 content_name,
perkjc11b1842016-03-07 17:34:13 -08001832 rtcp) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001833
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001834bool VideoChannel::Init_w() {
1835 if (!BaseChannel::Init_w()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001836 return false;
1837 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001838 return true;
1839}
1840
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001841VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001842 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001843 StopMediaMonitor();
1844 // this can't be done in the base class, since it calls a virtual
1845 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001846
1847 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001848}
1849
nisse08582ff2016-02-04 01:24:52 -08001850bool VideoChannel::SetSink(uint32_t ssrc,
1851 rtc::VideoSinkInterface<VideoFrame>* sink) {
1852 worker_thread()->Invoke<void>(
1853 Bind(&VideoMediaChannel::SetSink, media_channel(), ssrc, sink));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001854 return true;
1855}
1856
nisse2ded9b12016-04-08 02:23:55 -07001857void VideoChannel::SetSource(
1858 uint32_t ssrc,
1859 rtc::VideoSourceInterface<cricket::VideoFrame>* source) {
1860 worker_thread()->Invoke<void>(
1861 Bind(&VideoMediaChannel::SetSource, media_channel(), ssrc, source));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001862}
1863
Peter Boström0c4e06b2015-10-07 12:23:21 +02001864bool VideoChannel::SetVideoSend(uint32_t ssrc,
deadbeefcbecd352015-09-23 11:50:27 -07001865 bool mute,
solenberg1dd98f32015-09-10 01:57:14 -07001866 const VideoOptions* options) {
deadbeefcbecd352015-09-23 11:50:27 -07001867 return InvokeOnWorker(Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
1868 ssrc, mute, options));
solenberg1dd98f32015-09-10 01:57:14 -07001869}
1870
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001871webrtc::RtpParameters VideoChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001872 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001873 Bind(&VideoChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001874}
1875
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001876webrtc::RtpParameters VideoChannel::GetRtpSendParameters_w(
1877 uint32_t ssrc) const {
1878 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001879}
1880
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001881bool VideoChannel::SetRtpSendParameters(
1882 uint32_t ssrc,
1883 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001884 return InvokeOnWorker(
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001885 Bind(&VideoChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001886}
1887
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001888bool VideoChannel::SetRtpSendParameters_w(uint32_t ssrc,
1889 webrtc::RtpParameters parameters) {
1890 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1891}
1892
1893webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters(
1894 uint32_t ssrc) const {
1895 return worker_thread()->Invoke<webrtc::RtpParameters>(
1896 Bind(&VideoChannel::GetRtpReceiveParameters_w, this, ssrc));
1897}
1898
1899webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters_w(
1900 uint32_t ssrc) const {
1901 return media_channel()->GetRtpReceiveParameters(ssrc);
1902}
1903
1904bool VideoChannel::SetRtpReceiveParameters(
1905 uint32_t ssrc,
1906 const webrtc::RtpParameters& parameters) {
1907 return InvokeOnWorker(
1908 Bind(&VideoChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1909}
1910
1911bool VideoChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1912 webrtc::RtpParameters parameters) {
1913 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001914}
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001915
1916void VideoChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001917 // Send outgoing data if we're the active call, we have the remote content,
1918 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001919 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001920 if (!media_channel()->SetSend(send)) {
1921 LOG(LS_ERROR) << "Failed to SetSend on video channel";
1922 // TODO(gangji): Report error back to server.
1923 }
1924
Peter Boström34fbfff2015-09-24 19:20:30 +02001925 LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001926}
1927
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00001928bool VideoChannel::GetStats(VideoMediaInfo* stats) {
1929 return InvokeOnWorker(
1930 Bind(&VideoMediaChannel::GetStats, media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001931}
1932
1933void VideoChannel::StartMediaMonitor(int cms) {
1934 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001935 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001936 media_monitor_->SignalUpdate.connect(
1937 this, &VideoChannel::OnMediaMonitorUpdate);
1938 media_monitor_->Start(cms);
1939}
1940
1941void VideoChannel::StopMediaMonitor() {
1942 if (media_monitor_) {
1943 media_monitor_->Stop();
1944 media_monitor_.reset();
1945 }
1946}
1947
1948const ContentInfo* VideoChannel::GetFirstContent(
1949 const SessionDescription* sdesc) {
1950 return GetFirstVideoContent(sdesc);
1951}
1952
1953bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001954 ContentAction action,
1955 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001956 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001957 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001958 LOG(LS_INFO) << "Setting local video description";
1959
1960 const VideoContentDescription* video =
1961 static_cast<const VideoContentDescription*>(content);
1962 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001963 if (!video) {
1964 SafeSetError("Can't find video content in local description.", error_desc);
1965 return false;
1966 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001967
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001968 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001969 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001970 }
1971
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001972 VideoRecvParameters recv_params = last_recv_params_;
1973 RtpParametersFromMediaDescription(video, &recv_params);
1974 if (!media_channel()->SetRecvParameters(recv_params)) {
1975 SafeSetError("Failed to set local video description recv parameters.",
1976 error_desc);
1977 return false;
1978 }
1979 for (const VideoCodec& codec : video->codecs()) {
1980 bundle_filter()->AddPayloadType(codec.id);
1981 }
1982 last_recv_params_ = recv_params;
1983
1984 // TODO(pthatcher): Move local streams into VideoSendParameters, and
1985 // only give it to the media channel once we have a remote
1986 // description too (without a remote description, we won't be able
1987 // to send them anyway).
1988 if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) {
1989 SafeSetError("Failed to set local video description streams.", error_desc);
1990 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001991 }
1992
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001993 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001994 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001995 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001996}
1997
1998bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001999 ContentAction action,
2000 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002001 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002002 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002003 LOG(LS_INFO) << "Setting remote video description";
2004
2005 const VideoContentDescription* video =
2006 static_cast<const VideoContentDescription*>(content);
2007 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002008 if (!video) {
2009 SafeSetError("Can't find video content in remote description.", error_desc);
2010 return false;
2011 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002012
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002013 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002014 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002015 }
2016
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002017 VideoSendParameters send_params = last_send_params_;
2018 RtpSendParametersFromMediaDescription(video, &send_params);
2019 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08002020 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002021 }
skvladdc1c62c2016-03-16 19:07:43 -07002022
2023 bool parameters_applied = media_channel()->SetSendParameters(send_params);
2024
2025 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002026 SafeSetError("Failed to set remote video description send parameters.",
2027 error_desc);
2028 return false;
2029 }
2030 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002031
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002032 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
2033 // and only give it to the media channel once we have a local
2034 // description too (without a local description, we won't be able to
2035 // recv them anyway).
2036 if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) {
2037 SafeSetError("Failed to set remote video description streams.", error_desc);
2038 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002039 }
2040
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002041 if (video->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002042 MaybeCacheRtpAbsSendTimeHeaderExtension_w(video->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002043 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002044
2045 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002046 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002047 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002048}
2049
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002050void VideoChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002051 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002052 case MSG_CHANNEL_ERROR: {
2053 const VideoChannelErrorMessageData* data =
2054 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002055 delete data;
2056 break;
2057 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002058 default:
2059 BaseChannel::OnMessage(pmsg);
2060 break;
2061 }
2062}
2063
2064void VideoChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002065 ConnectionMonitor* monitor, const std::vector<ConnectionInfo> &infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002066 SignalConnectionMonitor(this, infos);
2067}
2068
2069// TODO(pthatcher): Look into removing duplicate code between
2070// audio, video, and data, perhaps by using templates.
2071void VideoChannel::OnMediaMonitorUpdate(
2072 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
2073 ASSERT(media_channel == this->media_channel());
2074 SignalMediaMonitor(this, info);
2075}
2076
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002077void VideoChannel::GetSrtpCryptoSuites_n(
2078 std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002079 GetSupportedVideoCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002080}
2081
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002082DataChannel::DataChannel(rtc::Thread* worker_thread,
2083 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002084 DataMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07002085 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002086 const std::string& content_name,
2087 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002088 : BaseChannel(worker_thread,
2089 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07002090 media_channel,
2091 transport_controller,
2092 content_name,
2093 rtcp),
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002094 data_channel_type_(cricket::DCT_NONE),
deadbeefcbecd352015-09-23 11:50:27 -07002095 ready_to_send_data_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002096
2097DataChannel::~DataChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08002098 TRACE_EVENT0("webrtc", "DataChannel::~DataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002099 StopMediaMonitor();
2100 // this can't be done in the base class, since it calls a virtual
2101 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00002102
2103 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002104}
2105
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002106bool DataChannel::Init_w() {
2107 if (!BaseChannel::Init_w()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002108 return false;
2109 }
2110 media_channel()->SignalDataReceived.connect(
2111 this, &DataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002112 media_channel()->SignalReadyToSend.connect(
2113 this, &DataChannel::OnDataChannelReadyToSend);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002114 media_channel()->SignalStreamClosedRemotely.connect(
2115 this, &DataChannel::OnStreamClosedRemotely);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002116 return true;
2117}
2118
2119bool DataChannel::SendData(const SendDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -07002120 const rtc::CopyOnWriteBuffer& payload,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002121 SendDataResult* result) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002122 return InvokeOnWorker(Bind(&DataMediaChannel::SendData,
2123 media_channel(), params, payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002124}
2125
2126const ContentInfo* DataChannel::GetFirstContent(
2127 const SessionDescription* sdesc) {
2128 return GetFirstDataContent(sdesc);
2129}
2130
jbaucheec21bd2016-03-20 06:15:43 -07002131bool DataChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002132 if (data_channel_type_ == DCT_SCTP) {
2133 // TODO(pthatcher): Do this in a more robust way by checking for
2134 // SCTP or DTLS.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +00002135 return !IsRtpPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002136 } else if (data_channel_type_ == DCT_RTP) {
2137 return BaseChannel::WantsPacket(rtcp, packet);
2138 }
2139 return false;
2140}
2141
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002142bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
2143 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002144 // It hasn't been set before, so set it now.
2145 if (data_channel_type_ == DCT_NONE) {
2146 data_channel_type_ = new_data_channel_type;
2147 return true;
2148 }
2149
2150 // It's been set before, but doesn't match. That's bad.
2151 if (data_channel_type_ != new_data_channel_type) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002152 std::ostringstream desc;
2153 desc << "Data channel type mismatch."
2154 << " Expected " << data_channel_type_
2155 << " Got " << new_data_channel_type;
2156 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002157 return false;
2158 }
2159
2160 // It's hasn't changed. Nothing to do.
2161 return true;
2162}
2163
2164bool DataChannel::SetDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002165 const DataContentDescription* content,
2166 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002167 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
2168 (content->protocol() == kMediaProtocolDtlsSctp));
2169 DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002170 return SetDataChannelType(data_channel_type, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002171}
2172
2173bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002174 ContentAction action,
2175 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002176 TRACE_EVENT0("webrtc", "DataChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002177 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002178 LOG(LS_INFO) << "Setting local data description";
2179
2180 const DataContentDescription* data =
2181 static_cast<const DataContentDescription*>(content);
2182 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002183 if (!data) {
2184 SafeSetError("Can't find data content in local description.", error_desc);
2185 return false;
2186 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002187
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002188 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002189 return false;
2190 }
2191
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002192 if (data_channel_type_ == DCT_RTP) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002193 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002194 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002195 }
2196 }
2197
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002198 // FYI: We send the SCTP port number (not to be confused with the
2199 // underlying UDP port number) as a codec parameter. So even SCTP
2200 // data channels need codecs.
2201 DataRecvParameters recv_params = last_recv_params_;
2202 RtpParametersFromMediaDescription(data, &recv_params);
2203 if (!media_channel()->SetRecvParameters(recv_params)) {
2204 SafeSetError("Failed to set remote data description recv parameters.",
2205 error_desc);
2206 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002207 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002208 if (data_channel_type_ == DCT_RTP) {
2209 for (const DataCodec& codec : data->codecs()) {
2210 bundle_filter()->AddPayloadType(codec.id);
2211 }
2212 }
2213 last_recv_params_ = recv_params;
2214
2215 // TODO(pthatcher): Move local streams into DataSendParameters, and
2216 // only give it to the media channel once we have a remote
2217 // description too (without a remote description, we won't be able
2218 // to send them anyway).
2219 if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) {
2220 SafeSetError("Failed to set local data description streams.", error_desc);
2221 return false;
2222 }
2223
2224 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002225 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002226 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002227}
2228
2229bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002230 ContentAction action,
2231 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002232 TRACE_EVENT0("webrtc", "DataChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002233 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002234
2235 const DataContentDescription* data =
2236 static_cast<const DataContentDescription*>(content);
2237 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002238 if (!data) {
2239 SafeSetError("Can't find data content in remote description.", error_desc);
2240 return false;
2241 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002242
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002243 // If the remote data doesn't have codecs and isn't an update, it
2244 // must be empty, so ignore it.
2245 if (!data->has_codecs() && action != CA_UPDATE) {
2246 return true;
2247 }
2248
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002249 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250 return false;
2251 }
2252
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002253 LOG(LS_INFO) << "Setting remote data description";
2254 if (data_channel_type_ == DCT_RTP &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002255 !SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002256 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002257 }
2258
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002259
2260 DataSendParameters send_params = last_send_params_;
2261 RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params);
2262 if (!media_channel()->SetSendParameters(send_params)) {
2263 SafeSetError("Failed to set remote data description send parameters.",
2264 error_desc);
2265 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002266 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002267 last_send_params_ = send_params;
2268
2269 // TODO(pthatcher): Move remote streams into DataRecvParameters,
2270 // and only give it to the media channel once we have a local
2271 // description too (without a local description, we won't be able to
2272 // recv them anyway).
2273 if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) {
2274 SafeSetError("Failed to set remote data description streams.",
2275 error_desc);
2276 return false;
2277 }
2278
2279 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002280 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002281 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002282}
2283
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002284void DataChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002285 // Render incoming data if we're the active call, and we have the local
2286 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002287 bool recv = IsReadyToReceive_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002288 if (!media_channel()->SetReceive(recv)) {
2289 LOG(LS_ERROR) << "Failed to SetReceive on data channel";
2290 }
2291
2292 // Send outgoing data if we're the active call, we have the remote content,
2293 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002294 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002295 if (!media_channel()->SetSend(send)) {
2296 LOG(LS_ERROR) << "Failed to SetSend on data channel";
2297 }
2298
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002299 // Trigger SignalReadyToSendData asynchronously.
2300 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002301
2302 LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
2303}
2304
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002305void DataChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002306 switch (pmsg->message_id) {
2307 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002308 DataChannelReadyToSendMessageData* data =
2309 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002310 ready_to_send_data_ = data->data();
2311 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002312 delete data;
2313 break;
2314 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002315 case MSG_DATARECEIVED: {
2316 DataReceivedMessageData* data =
2317 static_cast<DataReceivedMessageData*>(pmsg->pdata);
2318 SignalDataReceived(this, data->params, data->payload);
2319 delete data;
2320 break;
2321 }
2322 case MSG_CHANNEL_ERROR: {
2323 const DataChannelErrorMessageData* data =
2324 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002325 delete data;
2326 break;
2327 }
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002328 case MSG_STREAMCLOSEDREMOTELY: {
Peter Boström0c4e06b2015-10-07 12:23:21 +02002329 rtc::TypedMessageData<uint32_t>* data =
2330 static_cast<rtc::TypedMessageData<uint32_t>*>(pmsg->pdata);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002331 SignalStreamClosedRemotely(data->data());
2332 delete data;
2333 break;
2334 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002335 default:
2336 BaseChannel::OnMessage(pmsg);
2337 break;
2338 }
2339}
2340
2341void DataChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002342 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002343 SignalConnectionMonitor(this, infos);
2344}
2345
2346void DataChannel::StartMediaMonitor(int cms) {
2347 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002348 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002349 media_monitor_->SignalUpdate.connect(
2350 this, &DataChannel::OnMediaMonitorUpdate);
2351 media_monitor_->Start(cms);
2352}
2353
2354void DataChannel::StopMediaMonitor() {
2355 if (media_monitor_) {
2356 media_monitor_->Stop();
2357 media_monitor_->SignalUpdate.disconnect(this);
2358 media_monitor_.reset();
2359 }
2360}
2361
2362void DataChannel::OnMediaMonitorUpdate(
2363 DataMediaChannel* media_channel, const DataMediaInfo& info) {
2364 ASSERT(media_channel == this->media_channel());
2365 SignalMediaMonitor(this, info);
2366}
2367
2368void DataChannel::OnDataReceived(
2369 const ReceiveDataParams& params, const char* data, size_t len) {
2370 DataReceivedMessageData* msg = new DataReceivedMessageData(
2371 params, data, len);
2372 signaling_thread()->Post(this, MSG_DATARECEIVED, msg);
2373}
2374
Peter Boström0c4e06b2015-10-07 12:23:21 +02002375void DataChannel::OnDataChannelError(uint32_t ssrc,
2376 DataMediaChannel::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002377 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2378 ssrc, err);
2379 signaling_thread()->Post(this, MSG_CHANNEL_ERROR, data);
2380}
2381
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002382void DataChannel::OnDataChannelReadyToSend(bool writable) {
2383 // This is usded for congestion control to indicate that the stream is ready
2384 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2385 // that the transport channel is ready.
2386 signaling_thread()->Post(this, MSG_READYTOSENDDATA,
2387 new DataChannelReadyToSendMessageData(writable));
2388}
2389
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002390void DataChannel::GetSrtpCryptoSuites_n(std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002391 GetSupportedDataCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002392}
2393
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002394bool DataChannel::ShouldSetupDtlsSrtp_n() const {
2395 return data_channel_type_ == DCT_RTP && BaseChannel::ShouldSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002396}
2397
Peter Boström0c4e06b2015-10-07 12:23:21 +02002398void DataChannel::OnStreamClosedRemotely(uint32_t sid) {
2399 rtc::TypedMessageData<uint32_t>* message =
2400 new rtc::TypedMessageData<uint32_t>(sid);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002401 signaling_thread()->Post(this, MSG_STREAMCLOSEDREMOTELY, message);
2402}
2403
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002404} // namespace cricket