blob: 1312d63b37e02865ff42defb4b14217605f6a555 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander65c7f672016-02-12 00:05:01 -08002 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander65c7f672016-02-12 00:05:01 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
kwiberg0eb15ed2015-12-17 03:04:15 -080011#include <utility>
12
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010013#include "webrtc/pc/channel.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014
kjellander@webrtc.org7ffeab52016-02-26 22:46:09 +010015#include "webrtc/audio_sink.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000016#include "webrtc/base/bind.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000017#include "webrtc/base/byteorder.h"
18#include "webrtc/base/common.h"
jbaucheec21bd2016-03-20 06:15:43 -070019#include "webrtc/base/copyonwritebuffer.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000020#include "webrtc/base/dscp.h"
21#include "webrtc/base/logging.h"
Honghai Zhangcc411c02016-03-29 17:27:21 -070022#include "webrtc/base/networkroute.h"
Peter Boström6f28cf02015-12-07 23:17:15 +010023#include "webrtc/base/trace_event.h"
kjellanderf4752772016-03-02 05:42:30 -080024#include "webrtc/media/base/mediaconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080025#include "webrtc/media/base/rtputils.h"
Peter Boström6f28cf02015-12-07 23:17:15 +010026#include "webrtc/p2p/base/transportchannel.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010027#include "webrtc/pc/channelmanager.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000028
29namespace cricket {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000030using rtc::Bind;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000031
deadbeef2d110be2016-01-13 12:00:26 -080032namespace {
kwiberg31022942016-03-11 14:18:21 -080033// See comment below for why we need to use a pointer to a unique_ptr.
deadbeef2d110be2016-01-13 12:00:26 -080034bool SetRawAudioSink_w(VoiceMediaChannel* channel,
35 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -080036 std::unique_ptr<webrtc::AudioSinkInterface>* sink) {
37 channel->SetRawAudioSink(ssrc, std::move(*sink));
deadbeef2d110be2016-01-13 12:00:26 -080038 return true;
39}
Danil Chapovalov33b01f22016-05-11 19:55:27 +020040
41struct SendPacketMessageData : public rtc::MessageData {
42 rtc::CopyOnWriteBuffer packet;
43 rtc::PacketOptions options;
44};
45
isheriff6f8d6862016-05-26 11:24:55 -070046#if defined(ENABLE_EXTERNAL_AUTH)
47// Returns the named header extension if found among all extensions,
48// nullptr otherwise.
49const webrtc::RtpExtension* FindHeaderExtension(
50 const std::vector<webrtc::RtpExtension>& extensions,
51 const std::string& uri) {
52 for (const auto& extension : extensions) {
53 if (extension.uri == uri)
54 return &extension;
55 }
56 return nullptr;
57}
58#endif
59
deadbeef2d110be2016-01-13 12:00:26 -080060} // namespace
61
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062enum {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000063 MSG_EARLYMEDIATIMEOUT = 1,
Danil Chapovalov33b01f22016-05-11 19:55:27 +020064 MSG_SEND_RTP_PACKET,
65 MSG_SEND_RTCP_PACKET,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066 MSG_CHANNEL_ERROR,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000069 MSG_FIRSTPACKETRECEIVED,
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +000070 MSG_STREAMCLOSEDREMOTELY,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000071};
72
73// Value specified in RFC 5764.
74static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
75
76static const int kAgcMinus10db = -10;
77
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000078static void SafeSetError(const std::string& message, std::string* error_desc) {
79 if (error_desc) {
80 *error_desc = message;
81 }
82}
83
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000084struct VoiceChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020085 VoiceChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086 VoiceMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020087 : ssrc(in_ssrc), error(in_error) {}
88 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089 VoiceMediaChannel::Error error;
90};
91
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000092struct VideoChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020093 VideoChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094 VideoMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020095 : ssrc(in_ssrc), error(in_error) {}
96 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097 VideoMediaChannel::Error error;
98};
99
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000100struct DataChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200101 DataChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102 DataMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +0200103 : ssrc(in_ssrc), error(in_error) {}
104 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000105 DataMediaChannel::Error error;
106};
107
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108static const char* PacketType(bool rtcp) {
109 return (!rtcp) ? "RTP" : "RTCP";
110}
111
jbaucheec21bd2016-03-20 06:15:43 -0700112static bool ValidPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113 // Check the packet size. We could check the header too if needed.
114 return (packet &&
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000115 packet->size() >= (!rtcp ? kMinRtpPacketLen : kMinRtcpPacketLen) &&
116 packet->size() <= kMaxRtpPacketLen);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000117}
118
119static bool IsReceiveContentDirection(MediaContentDirection direction) {
120 return direction == MD_SENDRECV || direction == MD_RECVONLY;
121}
122
123static bool IsSendContentDirection(MediaContentDirection direction) {
124 return direction == MD_SENDRECV || direction == MD_SENDONLY;
125}
126
127static const MediaContentDescription* GetContentDescription(
128 const ContentInfo* cinfo) {
129 if (cinfo == NULL)
130 return NULL;
131 return static_cast<const MediaContentDescription*>(cinfo->description);
132}
133
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700134template <class Codec>
135void RtpParametersFromMediaDescription(
136 const MediaContentDescriptionImpl<Codec>* desc,
137 RtpParameters<Codec>* params) {
138 // TODO(pthatcher): Remove this once we're sure no one will give us
139 // a description without codecs (currently a CA_UPDATE with just
140 // streams can).
141 if (desc->has_codecs()) {
142 params->codecs = desc->codecs();
143 }
144 // TODO(pthatcher): See if we really need
145 // rtp_header_extensions_set() and remove it if we don't.
146 if (desc->rtp_header_extensions_set()) {
147 params->extensions = desc->rtp_header_extensions();
148 }
deadbeef13871492015-12-09 12:37:51 -0800149 params->rtcp.reduced_size = desc->rtcp_reduced_size();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700150}
151
nisse05103312016-03-16 02:22:50 -0700152template <class Codec>
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700153void RtpSendParametersFromMediaDescription(
154 const MediaContentDescriptionImpl<Codec>* desc,
nisse05103312016-03-16 02:22:50 -0700155 RtpSendParameters<Codec>* send_params) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700156 RtpParametersFromMediaDescription(desc, send_params);
157 send_params->max_bandwidth_bps = desc->bandwidth();
158}
159
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200160BaseChannel::BaseChannel(rtc::Thread* worker_thread,
161 rtc::Thread* network_thread,
deadbeefcbecd352015-09-23 11:50:27 -0700162 MediaChannel* media_channel,
163 TransportController* transport_controller,
164 const std::string& content_name,
165 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200166 : worker_thread_(worker_thread),
167 network_thread_(network_thread),
168
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000169 content_name_(content_name),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200170
171 transport_controller_(transport_controller),
deadbeef23d947d2016-08-22 16:00:30 -0700172 rtcp_enabled_(rtcp),
173 media_channel_(media_channel) {
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>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700196 RTC_FROM_HERE, 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
skvlad6c87a672016-05-17 17:49:52 -0700232bool BaseChannel::Init_w(const std::string* bundle_transport_name) {
233 if (!network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700234 RTC_FROM_HERE,
skvlad6c87a672016-05-17 17:49:52 -0700235 Bind(&BaseChannel::InitNetwork_n, this, bundle_transport_name))) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000236 return false;
237 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000238
wu@webrtc.orgde305012013-10-31 15:40:38 +0000239 // Both RTP and RTCP channels are set, we can call SetInterface on
240 // media channel and it can set network options.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200241 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.orgde305012013-10-31 15:40:38 +0000242 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000243 return true;
244}
245
skvlad6c87a672016-05-17 17:49:52 -0700246bool BaseChannel::InitNetwork_n(const std::string* bundle_transport_name) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200247 RTC_DCHECK(network_thread_->IsCurrent());
skvlad6c87a672016-05-17 17:49:52 -0700248 const std::string& transport_name =
249 (bundle_transport_name ? *bundle_transport_name : content_name());
250 if (!SetTransport_n(transport_name)) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200251 return false;
252 }
253
254 if (!SetDtlsSrtpCryptoSuites_n(transport_channel_, false)) {
255 return false;
256 }
deadbeef23d947d2016-08-22 16:00:30 -0700257 if (rtcp_transport_channel_ &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200258 !SetDtlsSrtpCryptoSuites_n(rtcp_transport_channel_, true)) {
259 return false;
260 }
261 return true;
262}
263
wu@webrtc.org78187522013-10-07 23:32:02 +0000264void BaseChannel::Deinit() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200265 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.org78187522013-10-07 23:32:02 +0000266 media_channel_->SetInterface(NULL);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200267 // Packets arrive on the network thread, processing packets calls virtual
268 // functions, so need to stop this process in Deinit that is called in
269 // derived classes destructor.
270 network_thread_->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700271 RTC_FROM_HERE, Bind(&BaseChannel::DisconnectTransportChannels_n, this));
wu@webrtc.org78187522013-10-07 23:32:02 +0000272}
273
deadbeefcbecd352015-09-23 11:50:27 -0700274bool BaseChannel::SetTransport(const std::string& transport_name) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200275 return network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700276 RTC_FROM_HERE, Bind(&BaseChannel::SetTransport_n, this, transport_name));
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000277}
278
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200279bool BaseChannel::SetTransport_n(const std::string& transport_name) {
280 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000281
deadbeefcbecd352015-09-23 11:50:27 -0700282 if (transport_name == transport_name_) {
283 // Nothing to do if transport name isn't changing
284 return true;
285 }
286
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800287 // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport
288 // changes and wait until the DTLS handshake is complete to set the newly
289 // negotiated parameters.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200290 if (ShouldSetupDtlsSrtp_n()) {
guoweis46383312015-12-17 16:45:59 -0800291 // Set |writable_| to false such that UpdateWritableState_w can set up
292 // DTLS-SRTP when the writable_ becomes true again.
293 writable_ = false;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800294 srtp_filter_.ResetParams();
295 }
296
deadbeef23d947d2016-08-22 16:00:30 -0700297 // If this BaseChannel uses RTCP and we haven't fully negotiated RTCP mux,
298 // we need an RTCP channel.
299 if (rtcp_enabled_ && !rtcp_mux_filter_.IsFullyActive()) {
deadbeefcbecd352015-09-23 11:50:27 -0700300 LOG(LS_INFO) << "Create RTCP TransportChannel for " << content_name()
301 << " on " << transport_name << " transport ";
deadbeef23d947d2016-08-22 16:00:30 -0700302 // TODO(deadbeef): Remove this grossness when we remove non-muxed RTCP.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200303 SetRtcpTransportChannel_n(
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200304 transport_controller_->CreateTransportChannel_n(
guoweis46383312015-12-17 16:45:59 -0800305 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP),
306 false /* update_writablity */);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200307 if (!rtcp_transport_channel_) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000308 return false;
309 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000310 }
311
guoweis46383312015-12-17 16:45:59 -0800312 // We're not updating the writablity during the transition state.
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200313 SetTransportChannel_n(transport_controller_->CreateTransportChannel_n(
guoweis46383312015-12-17 16:45:59 -0800314 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200315 if (!transport_channel_) {
guoweis46383312015-12-17 16:45:59 -0800316 return false;
317 }
318
deadbeef23d947d2016-08-22 16:00:30 -0700319 // TODO(deadbeef): Remove this grossness when we remove non-muxed RTCP.
320 if (rtcp_transport_channel_) {
guoweis46383312015-12-17 16:45:59 -0800321 // We can only update the RTCP ready to send after set_transport_channel has
322 // handled channel writability.
deadbeef23d947d2016-08-22 16:00:30 -0700323 SetReadyToSend(true, rtcp_transport_channel_->writable());
guoweis46383312015-12-17 16:45:59 -0800324 }
deadbeefcbecd352015-09-23 11:50:27 -0700325 transport_name_ = transport_name;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000326 return true;
327}
328
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200329void BaseChannel::SetTransportChannel_n(TransportChannel* new_tc) {
330 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000331
332 TransportChannel* old_tc = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700333 if (!old_tc && !new_tc) {
334 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000335 return;
336 }
deadbeefcbecd352015-09-23 11:50:27 -0700337 ASSERT(old_tc != new_tc);
338
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000339 if (old_tc) {
340 DisconnectFromTransportChannel(old_tc);
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200341 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700342 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000343 }
344
345 transport_channel_ = new_tc;
346
347 if (new_tc) {
348 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700349 for (const auto& pair : socket_options_) {
350 new_tc->SetOption(pair.first, pair.second);
351 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000352 }
deadbeefcbecd352015-09-23 11:50:27 -0700353
354 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
355 // setting new channel
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200356 UpdateWritableState_n();
deadbeefcbecd352015-09-23 11:50:27 -0700357 SetReadyToSend(false, new_tc && new_tc->writable());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000358}
359
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200360void BaseChannel::SetRtcpTransportChannel_n(TransportChannel* new_tc,
361 bool update_writablity) {
362 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000363
364 TransportChannel* old_tc = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700365 if (!old_tc && !new_tc) {
366 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000367 return;
368 }
deadbeefcbecd352015-09-23 11:50:27 -0700369 ASSERT(old_tc != new_tc);
370
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000371 if (old_tc) {
372 DisconnectFromTransportChannel(old_tc);
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200373 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700374 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000375 }
376
377 rtcp_transport_channel_ = new_tc;
378
379 if (new_tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200380 RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_filter_.IsActive()))
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800381 << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
382 << "should never happen.";
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000383 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700384 for (const auto& pair : rtcp_socket_options_) {
385 new_tc->SetOption(pair.first, pair.second);
386 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000387 }
deadbeefcbecd352015-09-23 11:50:27 -0700388
guoweis46383312015-12-17 16:45:59 -0800389 if (update_writablity) {
390 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
391 // setting new channel
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200392 UpdateWritableState_n();
guoweis46383312015-12-17 16:45:59 -0800393 SetReadyToSend(true, new_tc && new_tc->writable());
394 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000395}
396
397void BaseChannel::ConnectToTransportChannel(TransportChannel* tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200398 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000399
400 tc->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
401 tc->SignalReadPacket.connect(this, &BaseChannel::OnChannelRead);
402 tc->SignalReadyToSend.connect(this, &BaseChannel::OnReadyToSend);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800403 tc->SignalDtlsState.connect(this, &BaseChannel::OnDtlsState);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700404 tc->SignalSelectedCandidatePairChanged.connect(
405 this, &BaseChannel::OnSelectedCandidatePairChanged);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200406 tc->SignalSentPacket.connect(this, &BaseChannel::SignalSentPacket_n);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000407}
408
409void BaseChannel::DisconnectFromTransportChannel(TransportChannel* tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200410 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000411
412 tc->SignalWritableState.disconnect(this);
413 tc->SignalReadPacket.disconnect(this);
414 tc->SignalReadyToSend.disconnect(this);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800415 tc->SignalDtlsState.disconnect(this);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200416 tc->SignalSelectedCandidatePairChanged.disconnect(this);
417 tc->SignalSentPacket.disconnect(this);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000418}
419
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000420bool BaseChannel::Enable(bool enable) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700421 worker_thread_->Invoke<void>(
422 RTC_FROM_HERE,
423 Bind(enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
424 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000425 return true;
426}
427
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000428bool BaseChannel::AddRecvStream(const StreamParams& sp) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700429 return InvokeOnWorker(RTC_FROM_HERE,
430 Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000431}
432
Peter Boström0c4e06b2015-10-07 12:23:21 +0200433bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700434 return InvokeOnWorker(RTC_FROM_HERE,
435 Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000436}
437
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000438bool BaseChannel::AddSendStream(const StreamParams& sp) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000439 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700440 RTC_FROM_HERE, Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000441}
442
Peter Boström0c4e06b2015-10-07 12:23:21 +0200443bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700444 return InvokeOnWorker(RTC_FROM_HERE, Bind(&MediaChannel::RemoveSendStream,
445 media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000446}
447
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000448bool BaseChannel::SetLocalContent(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::SetLocalContent");
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700452 return InvokeOnWorker(RTC_FROM_HERE, Bind(&BaseChannel::SetLocalContent_w,
453 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000454}
455
456bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000457 ContentAction action,
458 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100459 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700460 return InvokeOnWorker(RTC_FROM_HERE, Bind(&BaseChannel::SetRemoteContent_w,
461 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000462}
463
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000464void BaseChannel::StartConnectionMonitor(int cms) {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000465 // We pass in the BaseChannel instead of the transport_channel_
466 // because if the transport_channel_ changes, the ConnectionMonitor
467 // would be pointing to the wrong TransportChannel.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200468 // We pass in the network thread because on that thread connection monitor
469 // will call BaseChannel::GetConnectionStats which must be called on the
470 // network thread.
471 connection_monitor_.reset(
472 new ConnectionMonitor(this, network_thread(), rtc::Thread::Current()));
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000473 connection_monitor_->SignalUpdate.connect(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000474 this, &BaseChannel::OnConnectionMonitorUpdate);
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000475 connection_monitor_->Start(cms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000476}
477
478void BaseChannel::StopConnectionMonitor() {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000479 if (connection_monitor_) {
480 connection_monitor_->Stop();
481 connection_monitor_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000482 }
483}
484
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000485bool BaseChannel::GetConnectionStats(ConnectionInfos* infos) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200486 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000487 return transport_channel_->GetStats(infos);
488}
489
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200490bool BaseChannel::IsReadyToReceive_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000491 // Receive data if we are enabled and have local content,
492 return enabled() && IsReceiveContentDirection(local_content_direction_);
493}
494
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200495bool BaseChannel::IsReadyToSend_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000496 // Send outgoing data if we are enabled, have local and remote content,
497 // and we have had some form of connectivity.
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800498 return enabled() && IsReceiveContentDirection(remote_content_direction_) &&
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000499 IsSendContentDirection(local_content_direction_) &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200500 network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700501 RTC_FROM_HERE, Bind(&BaseChannel::IsTransportReadyToSend_n, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200502}
503
504bool BaseChannel::IsTransportReadyToSend_n() const {
505 return was_ever_writable() &&
506 (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp_n());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000507}
508
jbaucheec21bd2016-03-20 06:15:43 -0700509bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700510 const rtc::PacketOptions& options) {
511 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000512}
513
jbaucheec21bd2016-03-20 06:15:43 -0700514bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700515 const rtc::PacketOptions& options) {
516 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000517}
518
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000519int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000520 int value) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200521 return network_thread_->Invoke<int>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700522 RTC_FROM_HERE, Bind(&BaseChannel::SetOption_n, this, type, opt, value));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200523}
524
525int BaseChannel::SetOption_n(SocketType type,
526 rtc::Socket::Option opt,
527 int value) {
528 RTC_DCHECK(network_thread_->IsCurrent());
529 TransportChannel* channel = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000531 case ST_RTP:
532 channel = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700533 socket_options_.push_back(
534 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000535 break;
536 case ST_RTCP:
537 channel = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700538 rtcp_socket_options_.push_back(
539 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000540 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000541 }
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000542 return channel ? channel->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000543}
544
jbauchcb560652016-08-04 05:20:32 -0700545bool BaseChannel::SetCryptoOptions(const rtc::CryptoOptions& crypto_options) {
546 crypto_options_ = crypto_options;
547 return true;
548}
549
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000550void BaseChannel::OnWritableState(TransportChannel* channel) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200551 RTC_DCHECK(channel == transport_channel_ ||
552 channel == rtcp_transport_channel_);
553 RTC_DCHECK(network_thread_->IsCurrent());
554 UpdateWritableState_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000555}
556
557void BaseChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000558 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000559 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000560 int flags) {
Peter Boström6f28cf02015-12-07 23:17:15 +0100561 TRACE_EVENT0("webrtc", "BaseChannel::OnChannelRead");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000562 // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200563 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000564
565 // When using RTCP multiplexing we might get RTCP packets on the RTP
566 // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
567 bool rtcp = PacketIsRtcp(channel, data, len);
jbaucheec21bd2016-03-20 06:15:43 -0700568 rtc::CopyOnWriteBuffer packet(data, len);
wu@webrtc.orga9890802013-12-13 00:21:03 +0000569 HandlePacket(rtcp, &packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000570}
571
572void BaseChannel::OnReadyToSend(TransportChannel* channel) {
deadbeefcbecd352015-09-23 11:50:27 -0700573 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
574 SetReadyToSend(channel == rtcp_transport_channel_, true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000575}
576
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800577void BaseChannel::OnDtlsState(TransportChannel* channel,
578 DtlsTransportState state) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200579 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800580 return;
581 }
582
583 // Reset the srtp filter if it's not the CONNECTED state. For the CONNECTED
584 // state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to
585 // cover other scenarios like the whole channel is writable (not just this
586 // TransportChannel) or when TransportChannel is attached after DTLS is
587 // negotiated.
588 if (state != DTLS_TRANSPORT_CONNECTED) {
589 srtp_filter_.ResetParams();
590 }
591}
592
Honghai Zhangcc411c02016-03-29 17:27:21 -0700593void BaseChannel::OnSelectedCandidatePairChanged(
594 TransportChannel* channel,
Honghai Zhang52dce732016-03-31 12:37:31 -0700595 CandidatePairInterface* selected_candidate_pair,
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -0700596 int last_sent_packet_id,
597 bool ready_to_send) {
Honghai Zhangcc411c02016-03-29 17:27:21 -0700598 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200599 RTC_DCHECK(network_thread_->IsCurrent());
600 std::string transport_name = channel->transport_name();
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700601 rtc::NetworkRoute network_route;
Honghai Zhangcc411c02016-03-29 17:27:21 -0700602 if (selected_candidate_pair) {
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700603 network_route = rtc::NetworkRoute(
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -0700604 ready_to_send, selected_candidate_pair->local_candidate().network_id(),
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700605 selected_candidate_pair->remote_candidate().network_id(),
606 last_sent_packet_id);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700607 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200608 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700609 RTC_FROM_HERE, worker_thread_,
610 Bind(&MediaChannel::OnNetworkRouteChanged, media_channel_, transport_name,
611 network_route));
Honghai Zhangcc411c02016-03-29 17:27:21 -0700612}
613
deadbeefcbecd352015-09-23 11:50:27 -0700614void BaseChannel::SetReadyToSend(bool rtcp, bool ready) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200615 RTC_DCHECK(network_thread_->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -0700616 if (rtcp) {
617 rtcp_ready_to_send_ = ready;
618 } else {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000619 rtp_ready_to_send_ = ready;
620 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000621
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200622 bool ready_to_send =
623 (rtp_ready_to_send_ &&
624 // In the case of rtcp mux |rtcp_transport_channel_| will be null.
625 (rtcp_ready_to_send_ || !rtcp_transport_channel_));
626
627 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700628 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200629 Bind(&MediaChannel::OnReadyToSend, media_channel_, ready_to_send));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000630}
631
632bool BaseChannel::PacketIsRtcp(const TransportChannel* channel,
633 const char* data, size_t len) {
634 return (channel == rtcp_transport_channel_ ||
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000635 rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000636}
637
stefanc1aeaf02015-10-15 07:26:07 -0700638bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700639 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700640 const rtc::PacketOptions& options) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200641 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
642 // If the thread is not our network thread, we will post to our network
643 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000644 // synchronize access to all the pieces of the send path, including
645 // SRTP and the inner workings of the transport channels.
646 // The only downside is that we can't return a proper failure code if
647 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200648 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000649 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200650 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
651 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800652 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700653 data->options = options;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700654 network_thread_->Post(RTC_FROM_HERE, this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000655 return true;
656 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200657 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000658
659 // Now that we are on the correct thread, ensure we have a place to send this
660 // packet before doing anything. (We might get RTCP packets that we don't
661 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
662 // transport.
663 TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
664 transport_channel_ : rtcp_transport_channel_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000665 if (!channel || !channel->writable()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666 return false;
667 }
668
669 // Protect ourselves against crazy data.
670 if (!ValidPacket(rtcp, packet)) {
671 LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000672 << PacketType(rtcp)
673 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000674 return false;
675 }
676
stefanc1aeaf02015-10-15 07:26:07 -0700677 rtc::PacketOptions updated_options;
678 updated_options = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 // Protect if needed.
680 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200681 TRACE_EVENT0("webrtc", "SRTP Encode");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000682 bool res;
Karl Wibergc56ac1e2015-05-04 14:54:55 +0200683 uint8_t* data = packet->data();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000684 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000685 if (!rtcp) {
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000686 // If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
687 // inside libsrtp for a RTP packet. A external HMAC module will be writing
688 // a fake HMAC value. This is ONLY done for a RTP packet.
689 // Socket layer will update rtp sendtime extension header if present in
690 // packet with current time before updating the HMAC.
691#if !defined(ENABLE_EXTERNAL_AUTH)
692 res = srtp_filter_.ProtectRtp(
693 data, len, static_cast<int>(packet->capacity()), &len);
694#else
stefanc1aeaf02015-10-15 07:26:07 -0700695 updated_options.packet_time_params.rtp_sendtime_extension_id =
henrike@webrtc.org05376342014-03-10 15:53:12 +0000696 rtp_abs_sendtime_extn_id_;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000697 res = srtp_filter_.ProtectRtp(
698 data, len, static_cast<int>(packet->capacity()), &len,
stefanc1aeaf02015-10-15 07:26:07 -0700699 &updated_options.packet_time_params.srtp_packet_index);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000700 // If protection succeeds, let's get auth params from srtp.
701 if (res) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200702 uint8_t* auth_key = NULL;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000703 int key_len;
704 res = srtp_filter_.GetRtpAuthParams(
stefanc1aeaf02015-10-15 07:26:07 -0700705 &auth_key, &key_len,
706 &updated_options.packet_time_params.srtp_auth_tag_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000707 if (res) {
stefanc1aeaf02015-10-15 07:26:07 -0700708 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
709 updated_options.packet_time_params.srtp_auth_key.assign(
710 auth_key, auth_key + key_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000711 }
712 }
713#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000714 if (!res) {
715 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200716 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000717 GetRtpSeqNum(data, len, &seq_num);
718 GetRtpSsrc(data, len, &ssrc);
719 LOG(LS_ERROR) << "Failed to protect " << content_name_
720 << " RTP packet: size=" << len
721 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
722 return false;
723 }
724 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000725 res = srtp_filter_.ProtectRtcp(data, len,
726 static_cast<int>(packet->capacity()),
727 &len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000728 if (!res) {
729 int type = -1;
730 GetRtcpType(data, len, &type);
731 LOG(LS_ERROR) << "Failed to protect " << content_name_
732 << " RTCP packet: size=" << len << ", type=" << type;
733 return false;
734 }
735 }
736
737 // Update the length of the packet now that we've added the auth tag.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000738 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000739 } else if (secure_required_) {
740 // This is a double check for something that supposedly can't happen.
741 LOG(LS_ERROR) << "Can't send outgoing " << PacketType(rtcp)
742 << " packet when SRTP is inactive and crypto is required";
743
744 ASSERT(false);
745 return false;
746 }
747
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000748 // Bon voyage.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200749 int flags = (secure() && secure_dtls()) ? PF_SRTP_BYPASS : PF_NORMAL;
750 int ret = channel->SendPacket(packet->data<char>(), packet->size(),
751 updated_options, flags);
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000752 if (ret != static_cast<int>(packet->size())) {
skvladc309e0e2016-07-28 17:15:20 -0700753 if (channel->GetError() == ENOTCONN) {
754 LOG(LS_WARNING) << "Got ENOTCONN from transport.";
deadbeefcbecd352015-09-23 11:50:27 -0700755 SetReadyToSend(rtcp, false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000756 }
757 return false;
758 }
759 return true;
760}
761
jbaucheec21bd2016-03-20 06:15:43 -0700762bool BaseChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000763 // Protect ourselves against crazy data.
764 if (!ValidPacket(rtcp, packet)) {
765 LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000766 << PacketType(rtcp)
767 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000768 return false;
769 }
pbos482b12e2015-11-16 10:19:58 -0800770 if (rtcp) {
771 // Permit all (seemingly valid) RTCP packets.
772 return true;
773 }
774 // Check whether we handle this payload.
jbaucheec21bd2016-03-20 06:15:43 -0700775 return bundle_filter_.DemuxPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000776}
777
jbaucheec21bd2016-03-20 06:15:43 -0700778void BaseChannel::HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000779 const rtc::PacketTime& packet_time) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200780 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000781 if (!WantsPacket(rtcp, packet)) {
782 return;
783 }
784
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000785 // We are only interested in the first rtp packet because that
786 // indicates the media has started flowing.
787 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000788 has_received_packet_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700789 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000790 }
791
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000792 // Unprotect the packet, if needed.
793 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200794 TRACE_EVENT0("webrtc", "SRTP Decode");
Karl Wiberg94784372015-04-20 14:03:07 +0200795 char* data = packet->data<char>();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000796 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000797 bool res;
798 if (!rtcp) {
799 res = srtp_filter_.UnprotectRtp(data, len, &len);
800 if (!res) {
801 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200802 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000803 GetRtpSeqNum(data, len, &seq_num);
804 GetRtpSsrc(data, len, &ssrc);
805 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
806 << " RTP packet: size=" << len
807 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
808 return;
809 }
810 } else {
811 res = srtp_filter_.UnprotectRtcp(data, len, &len);
812 if (!res) {
813 int type = -1;
814 GetRtcpType(data, len, &type);
815 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
816 << " RTCP packet: size=" << len << ", type=" << type;
817 return;
818 }
819 }
820
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000821 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000822 } else if (secure_required_) {
823 // Our session description indicates that SRTP is required, but we got a
824 // packet before our SRTP filter is active. This means either that
825 // a) we got SRTP packets before we received the SDES keys, in which case
826 // we can't decrypt it anyway, or
827 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
828 // channels, so we haven't yet extracted keys, even if DTLS did complete
829 // on the channel that the packets are being sent on. It's really good
830 // practice to wait for both RTP and RTCP to be good to go before sending
831 // media, to prevent weird failure modes, so it's fine for us to just eat
832 // packets here. This is all sidestepped if RTCP mux is used anyway.
833 LOG(LS_WARNING) << "Can't process incoming " << PacketType(rtcp)
834 << " packet when SRTP is inactive and crypto is required";
835 return;
836 }
837
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200838 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700839 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200840 Bind(&BaseChannel::OnPacketReceived, this, rtcp, *packet, packet_time));
841}
842
843void BaseChannel::OnPacketReceived(bool rtcp,
844 const rtc::CopyOnWriteBuffer& packet,
845 const rtc::PacketTime& packet_time) {
846 RTC_DCHECK(worker_thread_->IsCurrent());
847 // Need to copy variable because OnRtcpReceived/OnPacketReceived
848 // requires non-const pointer to buffer. This doesn't memcpy the actual data.
849 rtc::CopyOnWriteBuffer data(packet);
850 if (rtcp) {
851 media_channel_->OnRtcpReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000852 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200853 media_channel_->OnPacketReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000854 }
855}
856
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000857bool BaseChannel::PushdownLocalDescription(
858 const SessionDescription* local_desc, ContentAction action,
859 std::string* error_desc) {
860 const ContentInfo* content_info = GetFirstContent(local_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861 const MediaContentDescription* content_desc =
862 GetContentDescription(content_info);
863 if (content_desc && content_info && !content_info->rejected &&
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000864 !SetLocalContent(content_desc, action, error_desc)) {
865 LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
866 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000867 }
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000868 return true;
869}
870
871bool BaseChannel::PushdownRemoteDescription(
872 const SessionDescription* remote_desc, ContentAction action,
873 std::string* error_desc) {
874 const ContentInfo* content_info = GetFirstContent(remote_desc);
875 const MediaContentDescription* content_desc =
876 GetContentDescription(content_info);
877 if (content_desc && content_info && !content_info->rejected &&
878 !SetRemoteContent(content_desc, action, error_desc)) {
879 LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
880 return false;
881 }
882 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000883}
884
885void BaseChannel::EnableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000886 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000887 if (enabled_)
888 return;
889
890 LOG(LS_INFO) << "Channel enabled";
891 enabled_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200892 ChangeState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000893}
894
895void BaseChannel::DisableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000896 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000897 if (!enabled_)
898 return;
899
900 LOG(LS_INFO) << "Channel disabled";
901 enabled_ = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200902 ChangeState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000903}
904
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200905void BaseChannel::UpdateWritableState_n() {
deadbeefcbecd352015-09-23 11:50:27 -0700906 if (transport_channel_ && transport_channel_->writable() &&
907 (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200908 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700909 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200910 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700911 }
912}
913
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200914void BaseChannel::ChannelWritable_n() {
915 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800916 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000917 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800918 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000919
deadbeefcbecd352015-09-23 11:50:27 -0700920 LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000921 << (was_ever_writable_ ? "" : " for the first time");
922
923 std::vector<ConnectionInfo> infos;
924 transport_channel_->GetStats(&infos);
925 for (std::vector<ConnectionInfo>::const_iterator it = infos.begin();
926 it != infos.end(); ++it) {
927 if (it->best_connection) {
928 LOG(LS_INFO) << "Using " << it->local_candidate.ToSensitiveString()
929 << "->" << it->remote_candidate.ToSensitiveString();
930 break;
931 }
932 }
933
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000934 was_ever_writable_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200935 MaybeSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000936 writable_ = true;
937 ChangeState();
938}
939
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200940void BaseChannel::SignalDtlsSetupFailure_n(bool rtcp) {
941 RTC_DCHECK(network_thread_->IsCurrent());
942 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700943 RTC_FROM_HERE, signaling_thread(),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200944 Bind(&BaseChannel::SignalDtlsSetupFailure_s, this, rtcp));
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000945}
946
947void BaseChannel::SignalDtlsSetupFailure_s(bool rtcp) {
948 ASSERT(signaling_thread() == rtc::Thread::Current());
949 SignalDtlsSetupFailure(this, rtcp);
950}
951
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200952bool BaseChannel::SetDtlsSrtpCryptoSuites_n(TransportChannel* tc, bool rtcp) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800953 std::vector<int> crypto_suites;
954 // We always use the default SRTP crypto suites for RTCP, but we may use
955 // different crypto suites for RTP depending on the media type.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000956 if (!rtcp) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200957 GetSrtpCryptoSuites_n(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000958 } else {
jbauchcb560652016-08-04 05:20:32 -0700959 GetDefaultSrtpCryptoSuites(crypto_options(), &crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000960 }
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800961 return tc->SetSrtpCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000962}
963
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200964bool BaseChannel::ShouldSetupDtlsSrtp_n() const {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800965 // Since DTLS is applied to all channels, checking RTP should be enough.
966 return transport_channel_ && transport_channel_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000967}
968
969// This function returns true if either DTLS-SRTP is not in use
970// *or* DTLS-SRTP is successfully set up.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200971bool BaseChannel::SetupDtlsSrtp_n(bool rtcp_channel) {
972 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000973 bool ret = false;
974
deadbeefcbecd352015-09-23 11:50:27 -0700975 TransportChannel* channel =
976 rtcp_channel ? rtcp_transport_channel_ : transport_channel_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000977
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800978 RTC_DCHECK(channel->IsDtlsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000979
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800980 int selected_crypto_suite;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000981
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800982 if (!channel->GetSrtpCryptoSuite(&selected_crypto_suite)) {
983 LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000984 return false;
985 }
986
987 LOG(LS_INFO) << "Installing keys from DTLS-SRTP on "
988 << content_name() << " "
989 << PacketType(rtcp_channel);
990
jbauchcb560652016-08-04 05:20:32 -0700991 int key_len;
992 int salt_len;
993 if (!rtc::GetSrtpKeyAndSaltLengths(selected_crypto_suite, &key_len,
994 &salt_len)) {
995 LOG(LS_ERROR) << "Unknown DTLS-SRTP crypto suite" << selected_crypto_suite;
996 return false;
997 }
998
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000999 // OK, we're now doing DTLS (RFC 5764)
jbauchcb560652016-08-04 05:20:32 -07001000 std::vector<unsigned char> dtls_buffer(key_len * 2 + salt_len * 2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001001
1002 // RFC 5705 exporter using the RFC 5764 parameters
1003 if (!channel->ExportKeyingMaterial(
1004 kDtlsSrtpExporterLabel,
1005 NULL, 0, false,
1006 &dtls_buffer[0], dtls_buffer.size())) {
1007 LOG(LS_WARNING) << "DTLS-SRTP key export failed";
1008 ASSERT(false); // This should never happen
1009 return false;
1010 }
1011
1012 // Sync up the keys with the DTLS-SRTP interface
jbauchcb560652016-08-04 05:20:32 -07001013 std::vector<unsigned char> client_write_key(key_len + salt_len);
1014 std::vector<unsigned char> server_write_key(key_len + salt_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001015 size_t offset = 0;
jbauchcb560652016-08-04 05:20:32 -07001016 memcpy(&client_write_key[0], &dtls_buffer[offset], key_len);
1017 offset += key_len;
1018 memcpy(&server_write_key[0], &dtls_buffer[offset], key_len);
1019 offset += key_len;
1020 memcpy(&client_write_key[key_len], &dtls_buffer[offset], salt_len);
1021 offset += salt_len;
1022 memcpy(&server_write_key[key_len], &dtls_buffer[offset], salt_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001023
1024 std::vector<unsigned char> *send_key, *recv_key;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001025 rtc::SSLRole role;
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00001026 if (!channel->GetSslRole(&role)) {
1027 LOG(LS_WARNING) << "GetSslRole failed";
1028 return false;
1029 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001030
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001031 if (role == rtc::SSL_SERVER) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001032 send_key = &server_write_key;
1033 recv_key = &client_write_key;
1034 } else {
1035 send_key = &client_write_key;
1036 recv_key = &server_write_key;
1037 }
1038
1039 if (rtcp_channel) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001040 ret = srtp_filter_.SetRtcpParams(selected_crypto_suite, &(*send_key)[0],
1041 static_cast<int>(send_key->size()),
1042 selected_crypto_suite, &(*recv_key)[0],
1043 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001044 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001045 ret = srtp_filter_.SetRtpParams(selected_crypto_suite, &(*send_key)[0],
1046 static_cast<int>(send_key->size()),
1047 selected_crypto_suite, &(*recv_key)[0],
1048 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001049 }
1050
1051 if (!ret)
1052 LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
1053 else
1054 dtls_keyed_ = true;
1055
1056 return ret;
1057}
1058
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001059void BaseChannel::MaybeSetupDtlsSrtp_n() {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001060 if (srtp_filter_.IsActive()) {
1061 return;
1062 }
1063
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001064 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001065 return;
1066 }
1067
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001068 if (!SetupDtlsSrtp_n(false)) {
1069 SignalDtlsSetupFailure_n(false);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001070 return;
1071 }
1072
1073 if (rtcp_transport_channel_) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001074 if (!SetupDtlsSrtp_n(true)) {
1075 SignalDtlsSetupFailure_n(true);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001076 return;
1077 }
1078 }
1079}
1080
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001081void BaseChannel::ChannelNotWritable_n() {
1082 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001083 if (!writable_)
1084 return;
1085
deadbeefcbecd352015-09-23 11:50:27 -07001086 LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001087 writable_ = false;
1088 ChangeState();
1089}
1090
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001091bool BaseChannel::SetRtpTransportParameters(
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001092 const MediaContentDescription* content,
1093 ContentAction action,
1094 ContentSource src,
1095 std::string* error_desc) {
1096 if (action == CA_UPDATE) {
1097 // These parameters never get changed by a CA_UDPATE.
1098 return true;
1099 }
1100
1101 // Cache secure_required_ for belt and suspenders check on SendPacket
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001102 return network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001103 RTC_FROM_HERE, Bind(&BaseChannel::SetRtpTransportParameters_n, this,
1104 content, action, src, error_desc));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001105}
1106
1107bool BaseChannel::SetRtpTransportParameters_n(
1108 const MediaContentDescription* content,
1109 ContentAction action,
1110 ContentSource src,
1111 std::string* error_desc) {
1112 RTC_DCHECK(network_thread_->IsCurrent());
1113
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001114 if (src == CS_LOCAL) {
1115 set_secure_required(content->crypto_required() != CT_NONE);
1116 }
1117
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001118 if (!SetSrtp_n(content->cryptos(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001119 return false;
1120 }
1121
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001122 if (!SetRtcpMux_n(content->rtcp_mux(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001123 return false;
1124 }
1125
1126 return true;
1127}
1128
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001129// |dtls| will be set to true if DTLS is active for transport channel and
1130// crypto is empty.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001131bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
1132 bool* dtls,
1133 std::string* error_desc) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001134 *dtls = transport_channel_->IsDtlsActive();
1135 if (*dtls && !cryptos.empty()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001136 SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001137 return false;
1138 }
1139 return true;
1140}
1141
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001142bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001143 ContentAction action,
1144 ContentSource src,
1145 std::string* error_desc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001146 TRACE_EVENT0("webrtc", "BaseChannel::SetSrtp_w");
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001147 if (action == CA_UPDATE) {
1148 // no crypto params.
1149 return true;
1150 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001151 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001152 bool dtls = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001153 ret = CheckSrtpConfig_n(cryptos, &dtls, error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001154 if (!ret) {
1155 return false;
1156 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001157 switch (action) {
1158 case CA_OFFER:
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001159 // If DTLS is already active on the channel, we could be renegotiating
1160 // here. We don't update the srtp filter.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001161 if (!dtls) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001162 ret = srtp_filter_.SetOffer(cryptos, src);
1163 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001164 break;
1165 case CA_PRANSWER:
1166 // If we're doing DTLS-SRTP, we don't want to update the filter
1167 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001168 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001169 ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
1170 }
1171 break;
1172 case CA_ANSWER:
1173 // If we're doing DTLS-SRTP, we don't want to update the filter
1174 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001175 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001176 ret = srtp_filter_.SetAnswer(cryptos, src);
1177 }
1178 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001179 default:
1180 break;
1181 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001182 if (!ret) {
1183 SafeSetError("Failed to setup SRTP filter.", error_desc);
1184 return false;
1185 }
1186 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001187}
1188
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001189void BaseChannel::ActivateRtcpMux() {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001190 network_thread_->Invoke<void>(RTC_FROM_HERE,
1191 Bind(&BaseChannel::ActivateRtcpMux_n, this));
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001192}
1193
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001194void BaseChannel::ActivateRtcpMux_n() {
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001195 if (!rtcp_mux_filter_.IsActive()) {
1196 rtcp_mux_filter_.SetActive();
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001197 SetRtcpTransportChannel_n(nullptr, true);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001198 }
1199}
1200
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001201bool BaseChannel::SetRtcpMux_n(bool enable,
1202 ContentAction action,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001203 ContentSource src,
1204 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001205 bool ret = false;
1206 switch (action) {
1207 case CA_OFFER:
1208 ret = rtcp_mux_filter_.SetOffer(enable, src);
1209 break;
1210 case CA_PRANSWER:
1211 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
1212 break;
1213 case CA_ANSWER:
1214 ret = rtcp_mux_filter_.SetAnswer(enable, src);
1215 if (ret && rtcp_mux_filter_.IsActive()) {
1216 // We activated RTCP mux, close down the RTCP transport.
deadbeefcbecd352015-09-23 11:50:27 -07001217 LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
1218 << " by destroying RTCP transport channel for "
1219 << transport_name();
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001220 SetRtcpTransportChannel_n(nullptr, true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001221 }
1222 break;
1223 case CA_UPDATE:
1224 // No RTCP mux info.
1225 ret = true;
Henrik Kjellander7c027b62015-04-22 13:21:30 +02001226 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001227 default:
1228 break;
1229 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001230 if (!ret) {
1231 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
1232 return false;
1233 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001234 // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
1235 // CA_ANSWER, but we only want to tear down the RTCP transport channel if we
1236 // received a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001237 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001238 // If the RTP transport is already writable, then so are we.
1239 if (transport_channel_->writable()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001240 ChannelWritable_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001241 }
1242 }
1243
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001244 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001245}
1246
1247bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001248 ASSERT(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -08001249 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001250}
1251
Peter Boström0c4e06b2015-10-07 12:23:21 +02001252bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001253 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001254 return media_channel()->RemoveRecvStream(ssrc);
1255}
1256
1257bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001258 ContentAction action,
1259 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001260 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1261 action == CA_PRANSWER || action == CA_UPDATE))
1262 return false;
1263
1264 // If this is an update, streams only contain streams that have changed.
1265 if (action == CA_UPDATE) {
1266 for (StreamParamsVec::const_iterator it = streams.begin();
1267 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001268 const StreamParams* existing_stream =
1269 GetStreamByIds(local_streams_, it->groupid, it->id);
1270 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001271 if (media_channel()->AddSendStream(*it)) {
1272 local_streams_.push_back(*it);
1273 LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
1274 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001275 std::ostringstream desc;
1276 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1277 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001278 return false;
1279 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001280 } else if (existing_stream && !it->has_ssrcs()) {
1281 if (!media_channel()->RemoveSendStream(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001282 std::ostringstream desc;
1283 desc << "Failed to remove send stream with ssrc "
1284 << it->first_ssrc() << ".";
1285 SafeSetError(desc.str(), error_desc);
1286 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001287 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001288 RemoveStreamBySsrc(&local_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001289 } else {
1290 LOG(LS_WARNING) << "Ignore unsupported stream update";
1291 }
1292 }
1293 return true;
1294 }
1295 // Else streams are all the streams we want to send.
1296
1297 // Check for streams that have been removed.
1298 bool ret = true;
1299 for (StreamParamsVec::const_iterator it = local_streams_.begin();
1300 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001301 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001302 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001303 std::ostringstream desc;
1304 desc << "Failed to remove send stream with ssrc "
1305 << it->first_ssrc() << ".";
1306 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001307 ret = false;
1308 }
1309 }
1310 }
1311 // Check for new streams.
1312 for (StreamParamsVec::const_iterator it = streams.begin();
1313 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001314 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001315 if (media_channel()->AddSendStream(*it)) {
stefanc1aeaf02015-10-15 07:26:07 -07001316 LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001317 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001318 std::ostringstream desc;
1319 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1320 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001321 ret = false;
1322 }
1323 }
1324 }
1325 local_streams_ = streams;
1326 return ret;
1327}
1328
1329bool BaseChannel::UpdateRemoteStreams_w(
1330 const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001331 ContentAction action,
1332 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001333 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1334 action == CA_PRANSWER || action == CA_UPDATE))
1335 return false;
1336
1337 // If this is an update, streams only contain streams that have changed.
1338 if (action == CA_UPDATE) {
1339 for (StreamParamsVec::const_iterator it = streams.begin();
1340 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001341 const StreamParams* existing_stream =
1342 GetStreamByIds(remote_streams_, it->groupid, it->id);
1343 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001344 if (AddRecvStream_w(*it)) {
1345 remote_streams_.push_back(*it);
1346 LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
1347 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001348 std::ostringstream desc;
1349 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1350 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001351 return false;
1352 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001353 } else if (existing_stream && !it->has_ssrcs()) {
1354 if (!RemoveRecvStream_w(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001355 std::ostringstream desc;
1356 desc << "Failed to remove remote stream with ssrc "
1357 << it->first_ssrc() << ".";
1358 SafeSetError(desc.str(), error_desc);
1359 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001360 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001361 RemoveStreamBySsrc(&remote_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001362 } else {
1363 LOG(LS_WARNING) << "Ignore unsupported stream update."
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001364 << " Stream exists? " << (existing_stream != nullptr)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001365 << " new stream = " << it->ToString();
1366 }
1367 }
1368 return true;
1369 }
1370 // Else streams are all the streams we want to receive.
1371
1372 // Check for streams that have been removed.
1373 bool ret = true;
1374 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
1375 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001376 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001377 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001378 std::ostringstream desc;
1379 desc << "Failed to remove remote stream with ssrc "
1380 << it->first_ssrc() << ".";
1381 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001382 ret = false;
1383 }
1384 }
1385 }
1386 // Check for new streams.
1387 for (StreamParamsVec::const_iterator it = streams.begin();
1388 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001389 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001390 if (AddRecvStream_w(*it)) {
1391 LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
1392 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001393 std::ostringstream desc;
1394 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1395 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001396 ret = false;
1397 }
1398 }
1399 }
1400 remote_streams_ = streams;
1401 return ret;
1402}
1403
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001404void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w(
isheriff6f8d6862016-05-26 11:24:55 -07001405 const std::vector<webrtc::RtpExtension>& extensions) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001406// Absolute Send Time extension id is used only with external auth,
1407// so do not bother searching for it and making asyncronious call to set
1408// something that is not used.
1409#if defined(ENABLE_EXTERNAL_AUTH)
isheriff6f8d6862016-05-26 11:24:55 -07001410 const webrtc::RtpExtension* send_time_extension =
1411 FindHeaderExtension(extensions, webrtc::RtpExtension::kAbsSendTimeUri);
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001412 int rtp_abs_sendtime_extn_id =
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001413 send_time_extension ? send_time_extension->id : -1;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001414 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001415 RTC_FROM_HERE, network_thread_,
1416 Bind(&BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n, this,
1417 rtp_abs_sendtime_extn_id));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001418#endif
1419}
1420
1421void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n(
1422 int rtp_abs_sendtime_extn_id) {
1423 rtp_abs_sendtime_extn_id_ = rtp_abs_sendtime_extn_id;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001424}
1425
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001426void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001427 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001428 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001429 case MSG_SEND_RTP_PACKET:
1430 case MSG_SEND_RTCP_PACKET: {
1431 RTC_DCHECK(network_thread_->IsCurrent());
1432 SendPacketMessageData* data =
1433 static_cast<SendPacketMessageData*>(pmsg->pdata);
1434 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
1435 SendPacket(rtcp, &data->packet, data->options);
1436 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001437 break;
1438 }
1439 case MSG_FIRSTPACKETRECEIVED: {
1440 SignalFirstPacketReceived(this);
1441 break;
1442 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001443 }
1444}
1445
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001446void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001447 // Flush all remaining RTCP messages. This should only be called in
1448 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001449 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001450 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001451 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
1452 for (const auto& message : rtcp_messages) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001453 network_thread_->Send(RTC_FROM_HERE, this, MSG_SEND_RTCP_PACKET,
1454 message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001455 }
1456}
1457
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001458void BaseChannel::SignalSentPacket_n(TransportChannel* /* channel */,
1459 const rtc::SentPacket& sent_packet) {
1460 RTC_DCHECK(network_thread_->IsCurrent());
1461 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001462 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001463 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
1464}
1465
1466void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
1467 RTC_DCHECK(worker_thread_->IsCurrent());
1468 SignalSentPacket(sent_packet);
1469}
1470
1471VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
1472 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001473 MediaEngineInterface* media_engine,
1474 VoiceMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001475 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001476 const std::string& content_name,
1477 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001478 : BaseChannel(worker_thread,
1479 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001480 media_channel,
1481 transport_controller,
1482 content_name,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001483 rtcp),
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001484 media_engine_(media_engine),
deadbeefcbecd352015-09-23 11:50:27 -07001485 received_media_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001486
1487VoiceChannel::~VoiceChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001488 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001489 StopAudioMonitor();
1490 StopMediaMonitor();
1491 // this can't be done in the base class, since it calls a virtual
1492 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001493 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001494}
1495
skvlad6c87a672016-05-17 17:49:52 -07001496bool VoiceChannel::Init_w(const std::string* bundle_transport_name) {
1497 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001498 return false;
1499 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001500 return true;
1501}
1502
Peter Boström0c4e06b2015-10-07 12:23:21 +02001503bool VoiceChannel::SetAudioSend(uint32_t ssrc,
solenbergdfc8f4f2015-10-01 02:31:10 -07001504 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001505 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001506 AudioSource* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001507 return InvokeOnWorker(RTC_FROM_HERE,
1508 Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001509 ssrc, enable, options, source));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001510}
1511
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001512// TODO(juberti): Handle early media the right way. We should get an explicit
1513// ringing message telling us to start playing local ringback, which we cancel
1514// if any early media actually arrives. For now, we do the opposite, which is
1515// to wait 1 second for early media, and start playing local ringback if none
1516// arrives.
1517void VoiceChannel::SetEarlyMedia(bool enable) {
1518 if (enable) {
1519 // Start the early media timeout
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001520 worker_thread()->PostDelayed(RTC_FROM_HERE, kEarlyMediaTimeout, this,
1521 MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001522 } else {
1523 // Stop the timeout if currently going.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001524 worker_thread()->Clear(this, MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001525 }
1526}
1527
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528bool VoiceChannel::CanInsertDtmf() {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001529 return InvokeOnWorker(
1530 RTC_FROM_HERE, Bind(&VoiceMediaChannel::CanInsertDtmf, media_channel()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001531}
1532
Peter Boström0c4e06b2015-10-07 12:23:21 +02001533bool VoiceChannel::InsertDtmf(uint32_t ssrc,
1534 int event_code,
solenberg1d63dd02015-12-02 12:35:09 -08001535 int duration) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001536 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceChannel::InsertDtmf_w, this,
1537 ssrc, event_code, duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001538}
1539
solenberg4bac9c52015-10-09 02:32:53 -07001540bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001541 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::SetOutputVolume,
1542 media_channel(), ssrc, volume));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001543}
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001544
Tommif888bb52015-12-12 01:37:01 +01001545void VoiceChannel::SetRawAudioSink(
1546 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -08001547 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
1548 // We need to work around Bind's lack of support for unique_ptr and ownership
deadbeef2d110be2016-01-13 12:00:26 -08001549 // passing. So we invoke to our own little routine that gets a pointer to
1550 // our local variable. This is OK since we're synchronously invoking.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001551 InvokeOnWorker(RTC_FROM_HERE,
1552 Bind(&SetRawAudioSink_w, media_channel(), ssrc, &sink));
Tommif888bb52015-12-12 01:37:01 +01001553}
1554
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001555webrtc::RtpParameters VoiceChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001556 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001557 RTC_FROM_HERE, Bind(&VoiceChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001558}
1559
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001560webrtc::RtpParameters VoiceChannel::GetRtpSendParameters_w(
1561 uint32_t ssrc) const {
1562 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001563}
1564
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001565bool VoiceChannel::SetRtpSendParameters(
1566 uint32_t ssrc,
1567 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001568 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001569 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001570 Bind(&VoiceChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001571}
1572
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001573bool VoiceChannel::SetRtpSendParameters_w(uint32_t ssrc,
1574 webrtc::RtpParameters parameters) {
1575 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1576}
1577
1578webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters(
1579 uint32_t ssrc) const {
1580 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001581 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001582 Bind(&VoiceChannel::GetRtpReceiveParameters_w, this, ssrc));
1583}
1584
1585webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters_w(
1586 uint32_t ssrc) const {
1587 return media_channel()->GetRtpReceiveParameters(ssrc);
1588}
1589
1590bool VoiceChannel::SetRtpReceiveParameters(
1591 uint32_t ssrc,
1592 const webrtc::RtpParameters& parameters) {
1593 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001594 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001595 Bind(&VoiceChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1596}
1597
1598bool VoiceChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1599 webrtc::RtpParameters parameters) {
1600 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001601}
1602
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001603bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001604 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::GetStats,
1605 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001606}
1607
1608void VoiceChannel::StartMediaMonitor(int cms) {
1609 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001610 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001611 media_monitor_->SignalUpdate.connect(
1612 this, &VoiceChannel::OnMediaMonitorUpdate);
1613 media_monitor_->Start(cms);
1614}
1615
1616void VoiceChannel::StopMediaMonitor() {
1617 if (media_monitor_) {
1618 media_monitor_->Stop();
1619 media_monitor_->SignalUpdate.disconnect(this);
1620 media_monitor_.reset();
1621 }
1622}
1623
1624void VoiceChannel::StartAudioMonitor(int cms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001625 audio_monitor_.reset(new AudioMonitor(this, rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001626 audio_monitor_
1627 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1628 audio_monitor_->Start(cms);
1629}
1630
1631void VoiceChannel::StopAudioMonitor() {
1632 if (audio_monitor_) {
1633 audio_monitor_->Stop();
1634 audio_monitor_.reset();
1635 }
1636}
1637
1638bool VoiceChannel::IsAudioMonitorRunning() const {
1639 return (audio_monitor_.get() != NULL);
1640}
1641
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001642int VoiceChannel::GetInputLevel_w() {
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001643 return media_engine_->GetInputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001644}
1645
1646int VoiceChannel::GetOutputLevel_w() {
1647 return media_channel()->GetOutputLevel();
1648}
1649
1650void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1651 media_channel()->GetActiveStreams(actives);
1652}
1653
1654void VoiceChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001655 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001656 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001657 int flags) {
1658 BaseChannel::OnChannelRead(channel, data, len, packet_time, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001659
1660 // Set a flag when we've received an RTP packet. If we're waiting for early
1661 // media, this will disable the timeout.
1662 if (!received_media_ && !PacketIsRtcp(channel, data, len)) {
1663 received_media_ = true;
1664 }
1665}
1666
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001667void BaseChannel::ChangeState() {
1668 RTC_DCHECK(network_thread_->IsCurrent());
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001669 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001670 Bind(&BaseChannel::ChangeState_w, this));
1671}
1672
1673void VoiceChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001674 // Render incoming data if we're the active call, and we have the local
1675 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001676 bool recv = IsReadyToReceive_w();
solenberg5b14b422015-10-01 04:10:31 -07001677 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001678
1679 // Send outgoing data if we're the active call, we have the remote content,
1680 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001681 bool send = IsReadyToSend_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001682 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001683
1684 LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
1685}
1686
1687const ContentInfo* VoiceChannel::GetFirstContent(
1688 const SessionDescription* sdesc) {
1689 return GetFirstAudioContent(sdesc);
1690}
1691
1692bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001693 ContentAction action,
1694 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001695 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001696 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001697 LOG(LS_INFO) << "Setting local voice description";
1698
1699 const AudioContentDescription* audio =
1700 static_cast<const AudioContentDescription*>(content);
1701 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001702 if (!audio) {
1703 SafeSetError("Can't find audio content in local description.", error_desc);
1704 return false;
1705 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001706
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001707 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001708 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001709 }
1710
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001711 AudioRecvParameters recv_params = last_recv_params_;
1712 RtpParametersFromMediaDescription(audio, &recv_params);
1713 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001714 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001715 error_desc);
1716 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001717 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001718 for (const AudioCodec& codec : audio->codecs()) {
1719 bundle_filter()->AddPayloadType(codec.id);
1720 }
1721 last_recv_params_ = recv_params;
1722
1723 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1724 // only give it to the media channel once we have a remote
1725 // description too (without a remote description, we won't be able
1726 // to send them anyway).
1727 if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) {
1728 SafeSetError("Failed to set local audio description streams.", error_desc);
1729 return false;
1730 }
1731
1732 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001733 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001734 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001735}
1736
1737bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001738 ContentAction action,
1739 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001740 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001741 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001742 LOG(LS_INFO) << "Setting remote voice description";
1743
1744 const AudioContentDescription* audio =
1745 static_cast<const AudioContentDescription*>(content);
1746 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001747 if (!audio) {
1748 SafeSetError("Can't find audio content in remote description.", error_desc);
1749 return false;
1750 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001751
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001752 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001753 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001754 }
1755
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001756 AudioSendParameters send_params = last_send_params_;
1757 RtpSendParametersFromMediaDescription(audio, &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001758 if (audio->agc_minus_10db()) {
Karl Wibergbe579832015-11-10 22:34:18 +01001759 send_params.options.adjust_agc_delta = rtc::Optional<int>(kAgcMinus10db);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001760 }
skvladdc1c62c2016-03-16 19:07:43 -07001761
1762 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1763 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001764 SafeSetError("Failed to set remote audio description send parameters.",
1765 error_desc);
1766 return false;
1767 }
1768 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001769
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001770 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1771 // and only give it to the media channel once we have a local
1772 // description too (without a local description, we won't be able to
1773 // recv them anyway).
1774 if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) {
1775 SafeSetError("Failed to set remote audio description streams.", error_desc);
1776 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001777 }
1778
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001779 if (audio->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001780 MaybeCacheRtpAbsSendTimeHeaderExtension_w(audio->rtp_header_extensions());
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001781 }
1782
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001783 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001784 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001785 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001786}
1787
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001788void VoiceChannel::HandleEarlyMediaTimeout() {
1789 // This occurs on the main thread, not the worker thread.
1790 if (!received_media_) {
1791 LOG(LS_INFO) << "No early media received before timeout";
1792 SignalEarlyMediaTimeout(this);
1793 }
1794}
1795
Peter Boström0c4e06b2015-10-07 12:23:21 +02001796bool VoiceChannel::InsertDtmf_w(uint32_t ssrc,
1797 int event,
solenberg1d63dd02015-12-02 12:35:09 -08001798 int duration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001799 if (!enabled()) {
1800 return false;
1801 }
solenberg1d63dd02015-12-02 12:35:09 -08001802 return media_channel()->InsertDtmf(ssrc, event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001803}
1804
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001805void VoiceChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001806 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001807 case MSG_EARLYMEDIATIMEOUT:
1808 HandleEarlyMediaTimeout();
1809 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001810 case MSG_CHANNEL_ERROR: {
1811 VoiceChannelErrorMessageData* data =
1812 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001813 delete data;
1814 break;
1815 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001816 default:
1817 BaseChannel::OnMessage(pmsg);
1818 break;
1819 }
1820}
1821
1822void VoiceChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001823 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001824 SignalConnectionMonitor(this, infos);
1825}
1826
1827void VoiceChannel::OnMediaMonitorUpdate(
1828 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
1829 ASSERT(media_channel == this->media_channel());
1830 SignalMediaMonitor(this, info);
1831}
1832
1833void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1834 const AudioInfo& info) {
1835 SignalAudioMonitor(this, info);
1836}
1837
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001838void VoiceChannel::GetSrtpCryptoSuites_n(
1839 std::vector<int>* crypto_suites) const {
jbauchcb560652016-08-04 05:20:32 -07001840 GetSupportedAudioCryptoSuites(crypto_options(), crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001841}
1842
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001843VideoChannel::VideoChannel(rtc::Thread* worker_thread,
1844 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001845 VideoMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001846 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001847 const std::string& content_name,
Fredrik Solenberg7fb711f2015-04-22 15:30:51 +02001848 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001849 : BaseChannel(worker_thread,
1850 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001851 media_channel,
1852 transport_controller,
1853 content_name,
perkjc11b1842016-03-07 17:34:13 -08001854 rtcp) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001855
skvlad6c87a672016-05-17 17:49:52 -07001856bool VideoChannel::Init_w(const std::string* bundle_transport_name) {
1857 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001858 return false;
1859 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001860 return true;
1861}
1862
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001863VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001864 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001865 StopMediaMonitor();
1866 // this can't be done in the base class, since it calls a virtual
1867 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001868
1869 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001870}
1871
nisse08582ff2016-02-04 01:24:52 -08001872bool VideoChannel::SetSink(uint32_t ssrc,
1873 rtc::VideoSinkInterface<VideoFrame>* sink) {
1874 worker_thread()->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001875 RTC_FROM_HERE,
nisse08582ff2016-02-04 01:24:52 -08001876 Bind(&VideoMediaChannel::SetSink, media_channel(), ssrc, sink));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001877 return true;
1878}
1879
deadbeef5a4a75a2016-06-02 16:23:38 -07001880bool VideoChannel::SetVideoSend(
nisse2ded9b12016-04-08 02:23:55 -07001881 uint32_t ssrc,
deadbeef5a4a75a2016-06-02 16:23:38 -07001882 bool mute,
1883 const VideoOptions* options,
nisse2ded9b12016-04-08 02:23:55 -07001884 rtc::VideoSourceInterface<cricket::VideoFrame>* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001885 return InvokeOnWorker(RTC_FROM_HERE,
1886 Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
deadbeef5a4a75a2016-06-02 16:23:38 -07001887 ssrc, mute, options, source));
solenberg1dd98f32015-09-10 01:57:14 -07001888}
1889
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001890webrtc::RtpParameters VideoChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001891 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001892 RTC_FROM_HERE, Bind(&VideoChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001893}
1894
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001895webrtc::RtpParameters VideoChannel::GetRtpSendParameters_w(
1896 uint32_t ssrc) const {
1897 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001898}
1899
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001900bool VideoChannel::SetRtpSendParameters(
1901 uint32_t ssrc,
1902 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001903 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001904 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001905 Bind(&VideoChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001906}
1907
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001908bool VideoChannel::SetRtpSendParameters_w(uint32_t ssrc,
1909 webrtc::RtpParameters parameters) {
1910 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1911}
1912
1913webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters(
1914 uint32_t ssrc) const {
1915 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001916 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001917 Bind(&VideoChannel::GetRtpReceiveParameters_w, this, ssrc));
1918}
1919
1920webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters_w(
1921 uint32_t ssrc) const {
1922 return media_channel()->GetRtpReceiveParameters(ssrc);
1923}
1924
1925bool VideoChannel::SetRtpReceiveParameters(
1926 uint32_t ssrc,
1927 const webrtc::RtpParameters& parameters) {
1928 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001929 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001930 Bind(&VideoChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1931}
1932
1933bool VideoChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1934 webrtc::RtpParameters parameters) {
1935 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001936}
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001937
1938void VideoChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001939 // Send outgoing data if we're the active call, we have the remote content,
1940 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001941 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001942 if (!media_channel()->SetSend(send)) {
1943 LOG(LS_ERROR) << "Failed to SetSend on video channel";
1944 // TODO(gangji): Report error back to server.
1945 }
1946
Peter Boström34fbfff2015-09-24 19:20:30 +02001947 LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001948}
1949
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00001950bool VideoChannel::GetStats(VideoMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001951 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VideoMediaChannel::GetStats,
1952 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001953}
1954
1955void VideoChannel::StartMediaMonitor(int cms) {
1956 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001957 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001958 media_monitor_->SignalUpdate.connect(
1959 this, &VideoChannel::OnMediaMonitorUpdate);
1960 media_monitor_->Start(cms);
1961}
1962
1963void VideoChannel::StopMediaMonitor() {
1964 if (media_monitor_) {
1965 media_monitor_->Stop();
1966 media_monitor_.reset();
1967 }
1968}
1969
1970const ContentInfo* VideoChannel::GetFirstContent(
1971 const SessionDescription* sdesc) {
1972 return GetFirstVideoContent(sdesc);
1973}
1974
1975bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001976 ContentAction action,
1977 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001978 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001979 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001980 LOG(LS_INFO) << "Setting local video description";
1981
1982 const VideoContentDescription* video =
1983 static_cast<const VideoContentDescription*>(content);
1984 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001985 if (!video) {
1986 SafeSetError("Can't find video content in local description.", error_desc);
1987 return false;
1988 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001989
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001990 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001991 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001992 }
1993
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001994 VideoRecvParameters recv_params = last_recv_params_;
1995 RtpParametersFromMediaDescription(video, &recv_params);
1996 if (!media_channel()->SetRecvParameters(recv_params)) {
1997 SafeSetError("Failed to set local video description recv parameters.",
1998 error_desc);
1999 return false;
2000 }
2001 for (const VideoCodec& codec : video->codecs()) {
2002 bundle_filter()->AddPayloadType(codec.id);
2003 }
2004 last_recv_params_ = recv_params;
2005
2006 // TODO(pthatcher): Move local streams into VideoSendParameters, and
2007 // only give it to the media channel once we have a remote
2008 // description too (without a remote description, we won't be able
2009 // to send them anyway).
2010 if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) {
2011 SafeSetError("Failed to set local video description streams.", error_desc);
2012 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002013 }
2014
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002015 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002016 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002017 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002018}
2019
2020bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002021 ContentAction action,
2022 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002023 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002024 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002025 LOG(LS_INFO) << "Setting remote video description";
2026
2027 const VideoContentDescription* video =
2028 static_cast<const VideoContentDescription*>(content);
2029 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002030 if (!video) {
2031 SafeSetError("Can't find video content in remote description.", error_desc);
2032 return false;
2033 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002034
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002035 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002036 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002037 }
2038
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002039 VideoSendParameters send_params = last_send_params_;
2040 RtpSendParametersFromMediaDescription(video, &send_params);
2041 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08002042 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002043 }
skvladdc1c62c2016-03-16 19:07:43 -07002044
2045 bool parameters_applied = media_channel()->SetSendParameters(send_params);
2046
2047 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002048 SafeSetError("Failed to set remote video description send parameters.",
2049 error_desc);
2050 return false;
2051 }
2052 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002053
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002054 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
2055 // and only give it to the media channel once we have a local
2056 // description too (without a local description, we won't be able to
2057 // recv them anyway).
2058 if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) {
2059 SafeSetError("Failed to set remote video description streams.", error_desc);
2060 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002061 }
2062
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002063 if (video->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002064 MaybeCacheRtpAbsSendTimeHeaderExtension_w(video->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002065 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002066
2067 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002068 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002069 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002070}
2071
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002072void VideoChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002073 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002074 case MSG_CHANNEL_ERROR: {
2075 const VideoChannelErrorMessageData* data =
2076 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002077 delete data;
2078 break;
2079 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002080 default:
2081 BaseChannel::OnMessage(pmsg);
2082 break;
2083 }
2084}
2085
2086void VideoChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002087 ConnectionMonitor* monitor, const std::vector<ConnectionInfo> &infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002088 SignalConnectionMonitor(this, infos);
2089}
2090
2091// TODO(pthatcher): Look into removing duplicate code between
2092// audio, video, and data, perhaps by using templates.
2093void VideoChannel::OnMediaMonitorUpdate(
2094 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
2095 ASSERT(media_channel == this->media_channel());
2096 SignalMediaMonitor(this, info);
2097}
2098
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002099void VideoChannel::GetSrtpCryptoSuites_n(
2100 std::vector<int>* crypto_suites) const {
jbauchcb560652016-08-04 05:20:32 -07002101 GetSupportedVideoCryptoSuites(crypto_options(), crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002102}
2103
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002104DataChannel::DataChannel(rtc::Thread* worker_thread,
2105 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002106 DataMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07002107 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002108 const std::string& content_name,
2109 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002110 : BaseChannel(worker_thread,
2111 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07002112 media_channel,
2113 transport_controller,
2114 content_name,
2115 rtcp),
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002116 data_channel_type_(cricket::DCT_NONE),
deadbeefcbecd352015-09-23 11:50:27 -07002117 ready_to_send_data_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002118
2119DataChannel::~DataChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08002120 TRACE_EVENT0("webrtc", "DataChannel::~DataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002121 StopMediaMonitor();
2122 // this can't be done in the base class, since it calls a virtual
2123 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00002124
2125 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002126}
2127
skvlad6c87a672016-05-17 17:49:52 -07002128bool DataChannel::Init_w(const std::string* bundle_transport_name) {
2129 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002130 return false;
2131 }
2132 media_channel()->SignalDataReceived.connect(
2133 this, &DataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002134 media_channel()->SignalReadyToSend.connect(
2135 this, &DataChannel::OnDataChannelReadyToSend);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002136 media_channel()->SignalStreamClosedRemotely.connect(
2137 this, &DataChannel::OnStreamClosedRemotely);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002138 return true;
2139}
2140
2141bool DataChannel::SendData(const SendDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -07002142 const rtc::CopyOnWriteBuffer& payload,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002143 SendDataResult* result) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002144 return InvokeOnWorker(
2145 RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params,
2146 payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002147}
2148
2149const ContentInfo* DataChannel::GetFirstContent(
2150 const SessionDescription* sdesc) {
2151 return GetFirstDataContent(sdesc);
2152}
2153
jbaucheec21bd2016-03-20 06:15:43 -07002154bool DataChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002155 if (data_channel_type_ == DCT_SCTP) {
2156 // TODO(pthatcher): Do this in a more robust way by checking for
2157 // SCTP or DTLS.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +00002158 return !IsRtpPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002159 } else if (data_channel_type_ == DCT_RTP) {
2160 return BaseChannel::WantsPacket(rtcp, packet);
2161 }
2162 return false;
2163}
2164
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002165bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
2166 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002167 // It hasn't been set before, so set it now.
2168 if (data_channel_type_ == DCT_NONE) {
2169 data_channel_type_ = new_data_channel_type;
2170 return true;
2171 }
2172
2173 // It's been set before, but doesn't match. That's bad.
2174 if (data_channel_type_ != new_data_channel_type) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002175 std::ostringstream desc;
2176 desc << "Data channel type mismatch."
2177 << " Expected " << data_channel_type_
2178 << " Got " << new_data_channel_type;
2179 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002180 return false;
2181 }
2182
2183 // It's hasn't changed. Nothing to do.
2184 return true;
2185}
2186
2187bool DataChannel::SetDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002188 const DataContentDescription* content,
2189 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002190 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
2191 (content->protocol() == kMediaProtocolDtlsSctp));
2192 DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002193 return SetDataChannelType(data_channel_type, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002194}
2195
2196bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002197 ContentAction action,
2198 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002199 TRACE_EVENT0("webrtc", "DataChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002200 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002201 LOG(LS_INFO) << "Setting local data description";
2202
2203 const DataContentDescription* data =
2204 static_cast<const DataContentDescription*>(content);
2205 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002206 if (!data) {
2207 SafeSetError("Can't find data content in local description.", error_desc);
2208 return false;
2209 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002210
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002211 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002212 return false;
2213 }
2214
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002215 if (data_channel_type_ == DCT_RTP) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002216 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002217 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002218 }
2219 }
2220
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002221 // FYI: We send the SCTP port number (not to be confused with the
2222 // underlying UDP port number) as a codec parameter. So even SCTP
2223 // data channels need codecs.
2224 DataRecvParameters recv_params = last_recv_params_;
2225 RtpParametersFromMediaDescription(data, &recv_params);
2226 if (!media_channel()->SetRecvParameters(recv_params)) {
2227 SafeSetError("Failed to set remote data description recv parameters.",
2228 error_desc);
2229 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002230 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002231 if (data_channel_type_ == DCT_RTP) {
2232 for (const DataCodec& codec : data->codecs()) {
2233 bundle_filter()->AddPayloadType(codec.id);
2234 }
2235 }
2236 last_recv_params_ = recv_params;
2237
2238 // TODO(pthatcher): Move local streams into DataSendParameters, and
2239 // only give it to the media channel once we have a remote
2240 // description too (without a remote description, we won't be able
2241 // to send them anyway).
2242 if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) {
2243 SafeSetError("Failed to set local data description streams.", error_desc);
2244 return false;
2245 }
2246
2247 set_local_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002248 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002249 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250}
2251
2252bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002253 ContentAction action,
2254 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002255 TRACE_EVENT0("webrtc", "DataChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002256 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002257
2258 const DataContentDescription* data =
2259 static_cast<const DataContentDescription*>(content);
2260 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002261 if (!data) {
2262 SafeSetError("Can't find data content in remote description.", error_desc);
2263 return false;
2264 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002265
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002266 // If the remote data doesn't have codecs and isn't an update, it
2267 // must be empty, so ignore it.
2268 if (!data->has_codecs() && action != CA_UPDATE) {
2269 return true;
2270 }
2271
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002272 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002273 return false;
2274 }
2275
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002276 LOG(LS_INFO) << "Setting remote data description";
2277 if (data_channel_type_ == DCT_RTP &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002278 !SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002279 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002280 }
2281
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002282
2283 DataSendParameters send_params = last_send_params_;
2284 RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params);
2285 if (!media_channel()->SetSendParameters(send_params)) {
2286 SafeSetError("Failed to set remote data description send parameters.",
2287 error_desc);
2288 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002289 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002290 last_send_params_ = send_params;
2291
2292 // TODO(pthatcher): Move remote streams into DataRecvParameters,
2293 // and only give it to the media channel once we have a local
2294 // description too (without a local description, we won't be able to
2295 // recv them anyway).
2296 if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) {
2297 SafeSetError("Failed to set remote data description streams.",
2298 error_desc);
2299 return false;
2300 }
2301
2302 set_remote_content_direction(content->direction());
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002303 ChangeState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002304 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002305}
2306
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002307void DataChannel::ChangeState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002308 // Render incoming data if we're the active call, and we have the local
2309 // content. We receive data on the default channel and multiplexed streams.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002310 bool recv = IsReadyToReceive_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002311 if (!media_channel()->SetReceive(recv)) {
2312 LOG(LS_ERROR) << "Failed to SetReceive on data channel";
2313 }
2314
2315 // Send outgoing data if we're the active call, we have the remote content,
2316 // and we have had some form of connectivity.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002317 bool send = IsReadyToSend_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002318 if (!media_channel()->SetSend(send)) {
2319 LOG(LS_ERROR) << "Failed to SetSend on data channel";
2320 }
2321
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002322 // Trigger SignalReadyToSendData asynchronously.
2323 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002324
2325 LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
2326}
2327
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002328void DataChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002329 switch (pmsg->message_id) {
2330 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002331 DataChannelReadyToSendMessageData* data =
2332 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002333 ready_to_send_data_ = data->data();
2334 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002335 delete data;
2336 break;
2337 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002338 case MSG_DATARECEIVED: {
2339 DataReceivedMessageData* data =
2340 static_cast<DataReceivedMessageData*>(pmsg->pdata);
2341 SignalDataReceived(this, data->params, data->payload);
2342 delete data;
2343 break;
2344 }
2345 case MSG_CHANNEL_ERROR: {
2346 const DataChannelErrorMessageData* data =
2347 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002348 delete data;
2349 break;
2350 }
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002351 case MSG_STREAMCLOSEDREMOTELY: {
Peter Boström0c4e06b2015-10-07 12:23:21 +02002352 rtc::TypedMessageData<uint32_t>* data =
2353 static_cast<rtc::TypedMessageData<uint32_t>*>(pmsg->pdata);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002354 SignalStreamClosedRemotely(data->data());
2355 delete data;
2356 break;
2357 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002358 default:
2359 BaseChannel::OnMessage(pmsg);
2360 break;
2361 }
2362}
2363
2364void DataChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002365 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002366 SignalConnectionMonitor(this, infos);
2367}
2368
2369void DataChannel::StartMediaMonitor(int cms) {
2370 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002371 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002372 media_monitor_->SignalUpdate.connect(
2373 this, &DataChannel::OnMediaMonitorUpdate);
2374 media_monitor_->Start(cms);
2375}
2376
2377void DataChannel::StopMediaMonitor() {
2378 if (media_monitor_) {
2379 media_monitor_->Stop();
2380 media_monitor_->SignalUpdate.disconnect(this);
2381 media_monitor_.reset();
2382 }
2383}
2384
2385void DataChannel::OnMediaMonitorUpdate(
2386 DataMediaChannel* media_channel, const DataMediaInfo& info) {
2387 ASSERT(media_channel == this->media_channel());
2388 SignalMediaMonitor(this, info);
2389}
2390
2391void DataChannel::OnDataReceived(
2392 const ReceiveDataParams& params, const char* data, size_t len) {
2393 DataReceivedMessageData* msg = new DataReceivedMessageData(
2394 params, data, len);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002395 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002396}
2397
Peter Boström0c4e06b2015-10-07 12:23:21 +02002398void DataChannel::OnDataChannelError(uint32_t ssrc,
2399 DataMediaChannel::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002400 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2401 ssrc, err);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002402 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_CHANNEL_ERROR, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002403}
2404
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002405void DataChannel::OnDataChannelReadyToSend(bool writable) {
2406 // This is usded for congestion control to indicate that the stream is ready
2407 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2408 // that the transport channel is ready.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002409 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002410 new DataChannelReadyToSendMessageData(writable));
2411}
2412
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002413void DataChannel::GetSrtpCryptoSuites_n(std::vector<int>* crypto_suites) const {
jbauchcb560652016-08-04 05:20:32 -07002414 GetSupportedDataCryptoSuites(crypto_options(), crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002415}
2416
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002417bool DataChannel::ShouldSetupDtlsSrtp_n() const {
2418 return data_channel_type_ == DCT_RTP && BaseChannel::ShouldSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002419}
2420
Peter Boström0c4e06b2015-10-07 12:23:21 +02002421void DataChannel::OnStreamClosedRemotely(uint32_t sid) {
2422 rtc::TypedMessageData<uint32_t>* message =
2423 new rtc::TypedMessageData<uint32_t>(sid);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002424 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_STREAMCLOSEDREMOTELY,
2425 message);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002426}
2427
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002428} // namespace cricket