blob: 67c16ec64aa1a47cb177e4ef6f3b4c7e5d8abec4 [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
skvladdc1c62c2016-03-16 19:07:43 -07001536webrtc::RtpParameters VoiceChannel::GetRtpParameters(uint32_t ssrc) const {
1537 return worker_thread()->Invoke<webrtc::RtpParameters>(
1538 Bind(&VoiceChannel::GetRtpParameters_w, this, ssrc));
1539}
1540
1541webrtc::RtpParameters VoiceChannel::GetRtpParameters_w(uint32_t ssrc) const {
skvlade0d46372016-04-07 22:59:22 -07001542 return media_channel()->GetRtpParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001543}
1544
1545bool VoiceChannel::SetRtpParameters(uint32_t ssrc,
1546 const webrtc::RtpParameters& parameters) {
1547 return InvokeOnWorker(
1548 Bind(&VoiceChannel::SetRtpParameters_w, this, ssrc, parameters));
1549}
1550
1551bool VoiceChannel::SetRtpParameters_w(uint32_t ssrc,
1552 webrtc::RtpParameters parameters) {
skvlade0d46372016-04-07 22:59:22 -07001553 return media_channel()->SetRtpParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001554}
1555
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001556bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001557 return InvokeOnWorker(Bind(&VoiceMediaChannel::GetStats,
1558 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001559}
1560
1561void VoiceChannel::StartMediaMonitor(int cms) {
1562 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001563 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001564 media_monitor_->SignalUpdate.connect(
1565 this, &VoiceChannel::OnMediaMonitorUpdate);
1566 media_monitor_->Start(cms);
1567}
1568
1569void VoiceChannel::StopMediaMonitor() {
1570 if (media_monitor_) {
1571 media_monitor_->Stop();
1572 media_monitor_->SignalUpdate.disconnect(this);
1573 media_monitor_.reset();
1574 }
1575}
1576
1577void VoiceChannel::StartAudioMonitor(int cms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001578 audio_monitor_.reset(new AudioMonitor(this, rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001579 audio_monitor_
1580 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1581 audio_monitor_->Start(cms);
1582}
1583
1584void VoiceChannel::StopAudioMonitor() {
1585 if (audio_monitor_) {
1586 audio_monitor_->Stop();
1587 audio_monitor_.reset();
1588 }
1589}
1590
1591bool VoiceChannel::IsAudioMonitorRunning() const {
1592 return (audio_monitor_.get() != NULL);
1593}
1594
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001595int VoiceChannel::GetInputLevel_w() {
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001596 return media_engine_->GetInputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001597}
1598
1599int VoiceChannel::GetOutputLevel_w() {
1600 return media_channel()->GetOutputLevel();
1601}
1602
1603void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1604 media_channel()->GetActiveStreams(actives);
1605}
1606
1607void VoiceChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001608 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001609 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001610 int flags) {
1611 BaseChannel::OnChannelRead(channel, data, len, packet_time, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001612
1613 // Set a flag when we've received an RTP packet. If we're waiting for early
1614 // media, this will disable the timeout.
1615 if (!received_media_ && !PacketIsRtcp(channel, data, len)) {
1616 received_media_ = true;
1617 }
1618}
1619
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001620void BaseChannel::ChangeState() {
1621 RTC_DCHECK(network_thread_->IsCurrent());
1622 invoker_.AsyncInvoke<void>(worker_thread_,
1623 Bind(&BaseChannel::ChangeState_w, this));
1624}
1625
1626void VoiceChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001627 // Render incoming data if we're the active call, and we have the local
1628 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001629 bool recv = IsReadyToReceive_w();
solenberg5b14b422015-10-01 04:10:31 -07001630 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001631
1632 // Send outgoing data if we're the active call, we have the remote content,
1633 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001634 bool send = IsReadyToSend_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001635 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001636
1637 LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
1638}
1639
1640const ContentInfo* VoiceChannel::GetFirstContent(
1641 const SessionDescription* sdesc) {
1642 return GetFirstAudioContent(sdesc);
1643}
1644
1645bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001646 ContentAction action,
1647 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001648 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001649 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001650 LOG(LS_INFO) << "Setting local voice description";
1651
1652 const AudioContentDescription* audio =
1653 static_cast<const AudioContentDescription*>(content);
1654 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001655 if (!audio) {
1656 SafeSetError("Can't find audio content in local description.", error_desc);
1657 return false;
1658 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001659
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001660 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001661 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001662 }
1663
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001664 AudioRecvParameters recv_params = last_recv_params_;
1665 RtpParametersFromMediaDescription(audio, &recv_params);
1666 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001667 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001668 error_desc);
1669 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001670 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001671 for (const AudioCodec& codec : audio->codecs()) {
1672 bundle_filter()->AddPayloadType(codec.id);
1673 }
1674 last_recv_params_ = recv_params;
1675
1676 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1677 // only give it to the media channel once we have a remote
1678 // description too (without a remote description, we won't be able
1679 // to send them anyway).
1680 if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) {
1681 SafeSetError("Failed to set local audio description streams.", error_desc);
1682 return false;
1683 }
1684
1685 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001686 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001687 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001688}
1689
1690bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001691 ContentAction action,
1692 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001693 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001694 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001695 LOG(LS_INFO) << "Setting remote voice description";
1696
1697 const AudioContentDescription* audio =
1698 static_cast<const AudioContentDescription*>(content);
1699 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001700 if (!audio) {
1701 SafeSetError("Can't find audio content in remote description.", error_desc);
1702 return false;
1703 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001704
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001705 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001706 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001707 }
1708
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001709 AudioSendParameters send_params = last_send_params_;
1710 RtpSendParametersFromMediaDescription(audio, &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001711 if (audio->agc_minus_10db()) {
Karl Wibergbe579832015-11-10 22:34:18 +01001712 send_params.options.adjust_agc_delta = rtc::Optional<int>(kAgcMinus10db);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001713 }
skvladdc1c62c2016-03-16 19:07:43 -07001714
1715 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1716 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001717 SafeSetError("Failed to set remote audio description send parameters.",
1718 error_desc);
1719 return false;
1720 }
1721 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001722
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001723 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1724 // and only give it to the media channel once we have a local
1725 // description too (without a local description, we won't be able to
1726 // recv them anyway).
1727 if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) {
1728 SafeSetError("Failed to set remote audio description streams.", error_desc);
1729 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001730 }
1731
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001732 if (audio->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001733 MaybeCacheRtpAbsSendTimeHeaderExtension_w(audio->rtp_header_extensions());
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001734 }
1735
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001736 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001737 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001738 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001739}
1740
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001741void VoiceChannel::HandleEarlyMediaTimeout() {
1742 // This occurs on the main thread, not the worker thread.
1743 if (!received_media_) {
1744 LOG(LS_INFO) << "No early media received before timeout";
1745 SignalEarlyMediaTimeout(this);
1746 }
1747}
1748
Peter Boström0c4e06b2015-10-07 12:23:21 +02001749bool VoiceChannel::InsertDtmf_w(uint32_t ssrc,
1750 int event,
solenberg1d63dd02015-12-02 12:35:09 -08001751 int duration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001752 if (!enabled()) {
1753 return false;
1754 }
solenberg1d63dd02015-12-02 12:35:09 -08001755 return media_channel()->InsertDtmf(ssrc, event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001756}
1757
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001758void VoiceChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001759 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001760 case MSG_EARLYMEDIATIMEOUT:
1761 HandleEarlyMediaTimeout();
1762 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001763 case MSG_CHANNEL_ERROR: {
1764 VoiceChannelErrorMessageData* data =
1765 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001766 delete data;
1767 break;
1768 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001769 default:
1770 BaseChannel::OnMessage(pmsg);
1771 break;
1772 }
1773}
1774
1775void VoiceChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001776 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001777 SignalConnectionMonitor(this, infos);
1778}
1779
1780void VoiceChannel::OnMediaMonitorUpdate(
1781 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
1782 ASSERT(media_channel == this->media_channel());
1783 SignalMediaMonitor(this, info);
1784}
1785
1786void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1787 const AudioInfo& info) {
1788 SignalAudioMonitor(this, info);
1789}
1790
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001791void VoiceChannel::GetSrtpCryptoSuites_n(
1792 std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001793 GetSupportedAudioCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001794}
1795
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001796VideoChannel::VideoChannel(rtc::Thread* worker_thread,
1797 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001798 VideoMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001799 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001800 const std::string& content_name,
Fredrik Solenberg7fb711f2015-04-22 15:30:51 +02001801 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001802 : BaseChannel(worker_thread,
1803 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001804 media_channel,
1805 transport_controller,
1806 content_name,
perkjc11b1842016-03-07 17:34:13 -08001807 rtcp) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001808
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001809bool VideoChannel::Init_w() {
1810 if (!BaseChannel::Init_w()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001811 return false;
1812 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001813 return true;
1814}
1815
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001816VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001817 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001818 StopMediaMonitor();
1819 // this can't be done in the base class, since it calls a virtual
1820 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001821
1822 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001823}
1824
nisse08582ff2016-02-04 01:24:52 -08001825bool VideoChannel::SetSink(uint32_t ssrc,
1826 rtc::VideoSinkInterface<VideoFrame>* sink) {
1827 worker_thread()->Invoke<void>(
1828 Bind(&VideoMediaChannel::SetSink, media_channel(), ssrc, sink));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001829 return true;
1830}
1831
nisse2ded9b12016-04-08 02:23:55 -07001832void VideoChannel::SetSource(
1833 uint32_t ssrc,
1834 rtc::VideoSourceInterface<cricket::VideoFrame>* source) {
1835 worker_thread()->Invoke<void>(
1836 Bind(&VideoMediaChannel::SetSource, media_channel(), ssrc, source));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001837}
1838
Peter Boström0c4e06b2015-10-07 12:23:21 +02001839bool VideoChannel::SetVideoSend(uint32_t ssrc,
deadbeefcbecd352015-09-23 11:50:27 -07001840 bool mute,
solenberg1dd98f32015-09-10 01:57:14 -07001841 const VideoOptions* options) {
deadbeefcbecd352015-09-23 11:50:27 -07001842 return InvokeOnWorker(Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
1843 ssrc, mute, options));
solenberg1dd98f32015-09-10 01:57:14 -07001844}
1845
skvladdc1c62c2016-03-16 19:07:43 -07001846webrtc::RtpParameters VideoChannel::GetRtpParameters(uint32_t ssrc) const {
1847 return worker_thread()->Invoke<webrtc::RtpParameters>(
1848 Bind(&VideoChannel::GetRtpParameters_w, this, ssrc));
1849}
1850
1851webrtc::RtpParameters VideoChannel::GetRtpParameters_w(uint32_t ssrc) const {
1852 return media_channel()->GetRtpParameters(ssrc);
1853}
1854
1855bool VideoChannel::SetRtpParameters(uint32_t ssrc,
1856 const webrtc::RtpParameters& parameters) {
1857 return InvokeOnWorker(
1858 Bind(&VideoChannel::SetRtpParameters_w, this, ssrc, parameters));
1859}
1860
1861bool VideoChannel::SetRtpParameters_w(uint32_t ssrc,
1862 webrtc::RtpParameters parameters) {
1863 return media_channel()->SetRtpParameters(ssrc, parameters);
1864}
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001865
1866void VideoChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001867 // Send outgoing data if we're the active call, we have the remote content,
1868 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001869 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001870 if (!media_channel()->SetSend(send)) {
1871 LOG(LS_ERROR) << "Failed to SetSend on video channel";
1872 // TODO(gangji): Report error back to server.
1873 }
1874
Peter Boström34fbfff2015-09-24 19:20:30 +02001875 LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001876}
1877
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00001878bool VideoChannel::GetStats(VideoMediaInfo* stats) {
1879 return InvokeOnWorker(
1880 Bind(&VideoMediaChannel::GetStats, media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001881}
1882
1883void VideoChannel::StartMediaMonitor(int cms) {
1884 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001885 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001886 media_monitor_->SignalUpdate.connect(
1887 this, &VideoChannel::OnMediaMonitorUpdate);
1888 media_monitor_->Start(cms);
1889}
1890
1891void VideoChannel::StopMediaMonitor() {
1892 if (media_monitor_) {
1893 media_monitor_->Stop();
1894 media_monitor_.reset();
1895 }
1896}
1897
1898const ContentInfo* VideoChannel::GetFirstContent(
1899 const SessionDescription* sdesc) {
1900 return GetFirstVideoContent(sdesc);
1901}
1902
1903bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001904 ContentAction action,
1905 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001906 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001907 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001908 LOG(LS_INFO) << "Setting local video description";
1909
1910 const VideoContentDescription* video =
1911 static_cast<const VideoContentDescription*>(content);
1912 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001913 if (!video) {
1914 SafeSetError("Can't find video content in local description.", error_desc);
1915 return false;
1916 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001917
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001918 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001919 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001920 }
1921
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001922 VideoRecvParameters recv_params = last_recv_params_;
1923 RtpParametersFromMediaDescription(video, &recv_params);
1924 if (!media_channel()->SetRecvParameters(recv_params)) {
1925 SafeSetError("Failed to set local video description recv parameters.",
1926 error_desc);
1927 return false;
1928 }
1929 for (const VideoCodec& codec : video->codecs()) {
1930 bundle_filter()->AddPayloadType(codec.id);
1931 }
1932 last_recv_params_ = recv_params;
1933
1934 // TODO(pthatcher): Move local streams into VideoSendParameters, and
1935 // only give it to the media channel once we have a remote
1936 // description too (without a remote description, we won't be able
1937 // to send them anyway).
1938 if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) {
1939 SafeSetError("Failed to set local video description streams.", error_desc);
1940 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001941 }
1942
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001943 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001944 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001945 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001946}
1947
1948bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001949 ContentAction action,
1950 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001951 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001952 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001953 LOG(LS_INFO) << "Setting remote video description";
1954
1955 const VideoContentDescription* video =
1956 static_cast<const VideoContentDescription*>(content);
1957 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001958 if (!video) {
1959 SafeSetError("Can't find video content in remote description.", error_desc);
1960 return false;
1961 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001962
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001963 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001964 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001965 }
1966
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001967 VideoSendParameters send_params = last_send_params_;
1968 RtpSendParametersFromMediaDescription(video, &send_params);
1969 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08001970 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001971 }
skvladdc1c62c2016-03-16 19:07:43 -07001972
1973 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1974
1975 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001976 SafeSetError("Failed to set remote video description send parameters.",
1977 error_desc);
1978 return false;
1979 }
1980 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001981
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001982 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
1983 // and only give it to the media channel once we have a local
1984 // description too (without a local description, we won't be able to
1985 // recv them anyway).
1986 if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) {
1987 SafeSetError("Failed to set remote video description streams.", error_desc);
1988 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001989 }
1990
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001991 if (video->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001992 MaybeCacheRtpAbsSendTimeHeaderExtension_w(video->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001993 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001994
1995 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001996 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001997 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001998}
1999
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002000void VideoChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002001 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002002 case MSG_CHANNEL_ERROR: {
2003 const VideoChannelErrorMessageData* data =
2004 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002005 delete data;
2006 break;
2007 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002008 default:
2009 BaseChannel::OnMessage(pmsg);
2010 break;
2011 }
2012}
2013
2014void VideoChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002015 ConnectionMonitor* monitor, const std::vector<ConnectionInfo> &infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002016 SignalConnectionMonitor(this, infos);
2017}
2018
2019// TODO(pthatcher): Look into removing duplicate code between
2020// audio, video, and data, perhaps by using templates.
2021void VideoChannel::OnMediaMonitorUpdate(
2022 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
2023 ASSERT(media_channel == this->media_channel());
2024 SignalMediaMonitor(this, info);
2025}
2026
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002027void VideoChannel::GetSrtpCryptoSuites_n(
2028 std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002029 GetSupportedVideoCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002030}
2031
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002032DataChannel::DataChannel(rtc::Thread* worker_thread,
2033 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002034 DataMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07002035 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002036 const std::string& content_name,
2037 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002038 : BaseChannel(worker_thread,
2039 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07002040 media_channel,
2041 transport_controller,
2042 content_name,
2043 rtcp),
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002044 data_channel_type_(cricket::DCT_NONE),
deadbeefcbecd352015-09-23 11:50:27 -07002045 ready_to_send_data_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002046
2047DataChannel::~DataChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08002048 TRACE_EVENT0("webrtc", "DataChannel::~DataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002049 StopMediaMonitor();
2050 // this can't be done in the base class, since it calls a virtual
2051 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00002052
2053 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002054}
2055
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002056bool DataChannel::Init_w() {
2057 if (!BaseChannel::Init_w()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002058 return false;
2059 }
2060 media_channel()->SignalDataReceived.connect(
2061 this, &DataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002062 media_channel()->SignalReadyToSend.connect(
2063 this, &DataChannel::OnDataChannelReadyToSend);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002064 media_channel()->SignalStreamClosedRemotely.connect(
2065 this, &DataChannel::OnStreamClosedRemotely);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002066 return true;
2067}
2068
2069bool DataChannel::SendData(const SendDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -07002070 const rtc::CopyOnWriteBuffer& payload,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002071 SendDataResult* result) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002072 return InvokeOnWorker(Bind(&DataMediaChannel::SendData,
2073 media_channel(), params, payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002074}
2075
2076const ContentInfo* DataChannel::GetFirstContent(
2077 const SessionDescription* sdesc) {
2078 return GetFirstDataContent(sdesc);
2079}
2080
jbaucheec21bd2016-03-20 06:15:43 -07002081bool DataChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002082 if (data_channel_type_ == DCT_SCTP) {
2083 // TODO(pthatcher): Do this in a more robust way by checking for
2084 // SCTP or DTLS.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +00002085 return !IsRtpPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002086 } else if (data_channel_type_ == DCT_RTP) {
2087 return BaseChannel::WantsPacket(rtcp, packet);
2088 }
2089 return false;
2090}
2091
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002092bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
2093 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002094 // It hasn't been set before, so set it now.
2095 if (data_channel_type_ == DCT_NONE) {
2096 data_channel_type_ = new_data_channel_type;
2097 return true;
2098 }
2099
2100 // It's been set before, but doesn't match. That's bad.
2101 if (data_channel_type_ != new_data_channel_type) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002102 std::ostringstream desc;
2103 desc << "Data channel type mismatch."
2104 << " Expected " << data_channel_type_
2105 << " Got " << new_data_channel_type;
2106 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002107 return false;
2108 }
2109
2110 // It's hasn't changed. Nothing to do.
2111 return true;
2112}
2113
2114bool DataChannel::SetDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002115 const DataContentDescription* content,
2116 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002117 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
2118 (content->protocol() == kMediaProtocolDtlsSctp));
2119 DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002120 return SetDataChannelType(data_channel_type, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002121}
2122
2123bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002124 ContentAction action,
2125 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002126 TRACE_EVENT0("webrtc", "DataChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002127 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002128 LOG(LS_INFO) << "Setting local data description";
2129
2130 const DataContentDescription* data =
2131 static_cast<const DataContentDescription*>(content);
2132 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002133 if (!data) {
2134 SafeSetError("Can't find data content in local description.", error_desc);
2135 return false;
2136 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002137
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002138 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002139 return false;
2140 }
2141
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002142 if (data_channel_type_ == DCT_RTP) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002143 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002144 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002145 }
2146 }
2147
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002148 // FYI: We send the SCTP port number (not to be confused with the
2149 // underlying UDP port number) as a codec parameter. So even SCTP
2150 // data channels need codecs.
2151 DataRecvParameters recv_params = last_recv_params_;
2152 RtpParametersFromMediaDescription(data, &recv_params);
2153 if (!media_channel()->SetRecvParameters(recv_params)) {
2154 SafeSetError("Failed to set remote data description recv parameters.",
2155 error_desc);
2156 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002157 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002158 if (data_channel_type_ == DCT_RTP) {
2159 for (const DataCodec& codec : data->codecs()) {
2160 bundle_filter()->AddPayloadType(codec.id);
2161 }
2162 }
2163 last_recv_params_ = recv_params;
2164
2165 // TODO(pthatcher): Move local streams into DataSendParameters, and
2166 // only give it to the media channel once we have a remote
2167 // description too (without a remote description, we won't be able
2168 // to send them anyway).
2169 if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) {
2170 SafeSetError("Failed to set local data description streams.", error_desc);
2171 return false;
2172 }
2173
2174 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002175 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002176 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002177}
2178
2179bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002180 ContentAction action,
2181 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002182 TRACE_EVENT0("webrtc", "DataChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002183 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002184
2185 const DataContentDescription* data =
2186 static_cast<const DataContentDescription*>(content);
2187 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002188 if (!data) {
2189 SafeSetError("Can't find data content in remote description.", error_desc);
2190 return false;
2191 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002192
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002193 // If the remote data doesn't have codecs and isn't an update, it
2194 // must be empty, so ignore it.
2195 if (!data->has_codecs() && action != CA_UPDATE) {
2196 return true;
2197 }
2198
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002199 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002200 return false;
2201 }
2202
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002203 LOG(LS_INFO) << "Setting remote data description";
2204 if (data_channel_type_ == DCT_RTP &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002205 !SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002206 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002207 }
2208
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002209
2210 DataSendParameters send_params = last_send_params_;
2211 RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params);
2212 if (!media_channel()->SetSendParameters(send_params)) {
2213 SafeSetError("Failed to set remote data description send parameters.",
2214 error_desc);
2215 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002216 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002217 last_send_params_ = send_params;
2218
2219 // TODO(pthatcher): Move remote streams into DataRecvParameters,
2220 // and only give it to the media channel once we have a local
2221 // description too (without a local description, we won't be able to
2222 // recv them anyway).
2223 if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) {
2224 SafeSetError("Failed to set remote data description streams.",
2225 error_desc);
2226 return false;
2227 }
2228
2229 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002230 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002231 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002232}
2233
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002234void DataChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002235 // Render incoming data if we're the active call, and we have the local
2236 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002237 bool recv = IsReadyToReceive_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002238 if (!media_channel()->SetReceive(recv)) {
2239 LOG(LS_ERROR) << "Failed to SetReceive on data channel";
2240 }
2241
2242 // Send outgoing data if we're the active call, we have the remote content,
2243 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002244 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002245 if (!media_channel()->SetSend(send)) {
2246 LOG(LS_ERROR) << "Failed to SetSend on data channel";
2247 }
2248
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002249 // Trigger SignalReadyToSendData asynchronously.
2250 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002251
2252 LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
2253}
2254
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002255void DataChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002256 switch (pmsg->message_id) {
2257 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002258 DataChannelReadyToSendMessageData* data =
2259 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002260 ready_to_send_data_ = data->data();
2261 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002262 delete data;
2263 break;
2264 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002265 case MSG_DATARECEIVED: {
2266 DataReceivedMessageData* data =
2267 static_cast<DataReceivedMessageData*>(pmsg->pdata);
2268 SignalDataReceived(this, data->params, data->payload);
2269 delete data;
2270 break;
2271 }
2272 case MSG_CHANNEL_ERROR: {
2273 const DataChannelErrorMessageData* data =
2274 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002275 delete data;
2276 break;
2277 }
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002278 case MSG_STREAMCLOSEDREMOTELY: {
Peter Boström0c4e06b2015-10-07 12:23:21 +02002279 rtc::TypedMessageData<uint32_t>* data =
2280 static_cast<rtc::TypedMessageData<uint32_t>*>(pmsg->pdata);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002281 SignalStreamClosedRemotely(data->data());
2282 delete data;
2283 break;
2284 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002285 default:
2286 BaseChannel::OnMessage(pmsg);
2287 break;
2288 }
2289}
2290
2291void DataChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002292 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002293 SignalConnectionMonitor(this, infos);
2294}
2295
2296void DataChannel::StartMediaMonitor(int cms) {
2297 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002298 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002299 media_monitor_->SignalUpdate.connect(
2300 this, &DataChannel::OnMediaMonitorUpdate);
2301 media_monitor_->Start(cms);
2302}
2303
2304void DataChannel::StopMediaMonitor() {
2305 if (media_monitor_) {
2306 media_monitor_->Stop();
2307 media_monitor_->SignalUpdate.disconnect(this);
2308 media_monitor_.reset();
2309 }
2310}
2311
2312void DataChannel::OnMediaMonitorUpdate(
2313 DataMediaChannel* media_channel, const DataMediaInfo& info) {
2314 ASSERT(media_channel == this->media_channel());
2315 SignalMediaMonitor(this, info);
2316}
2317
2318void DataChannel::OnDataReceived(
2319 const ReceiveDataParams& params, const char* data, size_t len) {
2320 DataReceivedMessageData* msg = new DataReceivedMessageData(
2321 params, data, len);
2322 signaling_thread()->Post(this, MSG_DATARECEIVED, msg);
2323}
2324
Peter Boström0c4e06b2015-10-07 12:23:21 +02002325void DataChannel::OnDataChannelError(uint32_t ssrc,
2326 DataMediaChannel::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002327 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2328 ssrc, err);
2329 signaling_thread()->Post(this, MSG_CHANNEL_ERROR, data);
2330}
2331
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002332void DataChannel::OnDataChannelReadyToSend(bool writable) {
2333 // This is usded for congestion control to indicate that the stream is ready
2334 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2335 // that the transport channel is ready.
2336 signaling_thread()->Post(this, MSG_READYTOSENDDATA,
2337 new DataChannelReadyToSendMessageData(writable));
2338}
2339
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002340void DataChannel::GetSrtpCryptoSuites_n(std::vector<int>* crypto_suites) const {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002341 GetSupportedDataCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002342}
2343
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002344bool DataChannel::ShouldSetupDtlsSrtp_n() const {
2345 return data_channel_type_ == DCT_RTP && BaseChannel::ShouldSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002346}
2347
Peter Boström0c4e06b2015-10-07 12:23:21 +02002348void DataChannel::OnStreamClosedRemotely(uint32_t sid) {
2349 rtc::TypedMessageData<uint32_t>* message =
2350 new rtc::TypedMessageData<uint32_t>(sid);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002351 signaling_thread()->Post(this, MSG_STREAMCLOSEDREMOTELY, message);
2352}
2353
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002354} // namespace cricket