blob: f3c3211fdfbf2d5f5f42ba52f4dd2f26c81d72da [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
kjellandera69d9732016-08-31 07:33:05 -070015#include "webrtc/api/call/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"
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -070018#include "webrtc/base/checks.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000019#include "webrtc/base/common.h"
jbaucheec21bd2016-03-20 06:15:43 -070020#include "webrtc/base/copyonwritebuffer.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000021#include "webrtc/base/dscp.h"
22#include "webrtc/base/logging.h"
Honghai Zhangcc411c02016-03-29 17:27:21 -070023#include "webrtc/base/networkroute.h"
Peter Boström6f28cf02015-12-07 23:17:15 +010024#include "webrtc/base/trace_event.h"
kjellanderf4752772016-03-02 05:42:30 -080025#include "webrtc/media/base/mediaconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080026#include "webrtc/media/base/rtputils.h"
johand89ab142016-10-25 10:50:32 -070027#include "webrtc/p2p/base/packettransportinterface.h"
Peter Boström6f28cf02015-12-07 23:17:15 +010028#include "webrtc/p2p/base/transportchannel.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010029#include "webrtc/pc/channelmanager.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000030
31namespace cricket {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000032using rtc::Bind;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000033
deadbeef2d110be2016-01-13 12:00:26 -080034namespace {
kwiberg31022942016-03-11 14:18:21 -080035// See comment below for why we need to use a pointer to a unique_ptr.
deadbeef2d110be2016-01-13 12:00:26 -080036bool SetRawAudioSink_w(VoiceMediaChannel* channel,
37 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -080038 std::unique_ptr<webrtc::AudioSinkInterface>* sink) {
39 channel->SetRawAudioSink(ssrc, std::move(*sink));
deadbeef2d110be2016-01-13 12:00:26 -080040 return true;
41}
Danil Chapovalov33b01f22016-05-11 19:55:27 +020042
43struct SendPacketMessageData : public rtc::MessageData {
44 rtc::CopyOnWriteBuffer packet;
45 rtc::PacketOptions options;
46};
47
isheriff6f8d6862016-05-26 11:24:55 -070048#if defined(ENABLE_EXTERNAL_AUTH)
49// Returns the named header extension if found among all extensions,
50// nullptr otherwise.
51const webrtc::RtpExtension* FindHeaderExtension(
52 const std::vector<webrtc::RtpExtension>& extensions,
53 const std::string& uri) {
54 for (const auto& extension : extensions) {
55 if (extension.uri == uri)
56 return &extension;
57 }
58 return nullptr;
59}
60#endif
61
deadbeef2d110be2016-01-13 12:00:26 -080062} // namespace
63
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064enum {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000065 MSG_EARLYMEDIATIMEOUT = 1,
Danil Chapovalov33b01f22016-05-11 19:55:27 +020066 MSG_SEND_RTP_PACKET,
67 MSG_SEND_RTCP_PACKET,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068 MSG_CHANNEL_ERROR,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000069 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000070 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000071 MSG_FIRSTPACKETRECEIVED,
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +000072 MSG_STREAMCLOSEDREMOTELY,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000073};
74
75// Value specified in RFC 5764.
76static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
77
78static const int kAgcMinus10db = -10;
79
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000080static void SafeSetError(const std::string& message, std::string* error_desc) {
81 if (error_desc) {
82 *error_desc = message;
83 }
84}
85
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000086struct VoiceChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020087 VoiceChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000088 VoiceMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020089 : ssrc(in_ssrc), error(in_error) {}
90 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000091 VoiceMediaChannel::Error error;
92};
93
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000094struct VideoChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020095 VideoChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000096 VideoMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020097 : ssrc(in_ssrc), error(in_error) {}
98 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099 VideoMediaChannel::Error error;
100};
101
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000102struct DataChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200103 DataChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000104 DataMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +0200105 : ssrc(in_ssrc), error(in_error) {}
106 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000107 DataMediaChannel::Error error;
108};
109
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000110static const char* PacketType(bool rtcp) {
111 return (!rtcp) ? "RTP" : "RTCP";
112}
113
jbaucheec21bd2016-03-20 06:15:43 -0700114static bool ValidPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115 // Check the packet size. We could check the header too if needed.
116 return (packet &&
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000117 packet->size() >= (!rtcp ? kMinRtpPacketLen : kMinRtcpPacketLen) &&
118 packet->size() <= kMaxRtpPacketLen);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119}
120
121static bool IsReceiveContentDirection(MediaContentDirection direction) {
122 return direction == MD_SENDRECV || direction == MD_RECVONLY;
123}
124
125static bool IsSendContentDirection(MediaContentDirection direction) {
126 return direction == MD_SENDRECV || direction == MD_SENDONLY;
127}
128
129static const MediaContentDescription* GetContentDescription(
130 const ContentInfo* cinfo) {
131 if (cinfo == NULL)
132 return NULL;
133 return static_cast<const MediaContentDescription*>(cinfo->description);
134}
135
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700136template <class Codec>
137void RtpParametersFromMediaDescription(
138 const MediaContentDescriptionImpl<Codec>* desc,
139 RtpParameters<Codec>* params) {
140 // TODO(pthatcher): Remove this once we're sure no one will give us
141 // a description without codecs (currently a CA_UPDATE with just
142 // streams can).
143 if (desc->has_codecs()) {
144 params->codecs = desc->codecs();
145 }
146 // TODO(pthatcher): See if we really need
147 // rtp_header_extensions_set() and remove it if we don't.
148 if (desc->rtp_header_extensions_set()) {
149 params->extensions = desc->rtp_header_extensions();
150 }
deadbeef13871492015-12-09 12:37:51 -0800151 params->rtcp.reduced_size = desc->rtcp_reduced_size();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700152}
153
nisse05103312016-03-16 02:22:50 -0700154template <class Codec>
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700155void RtpSendParametersFromMediaDescription(
156 const MediaContentDescriptionImpl<Codec>* desc,
nisse05103312016-03-16 02:22:50 -0700157 RtpSendParameters<Codec>* send_params) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700158 RtpParametersFromMediaDescription(desc, send_params);
159 send_params->max_bandwidth_bps = desc->bandwidth();
160}
161
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200162BaseChannel::BaseChannel(rtc::Thread* worker_thread,
163 rtc::Thread* network_thread,
deadbeefcbecd352015-09-23 11:50:27 -0700164 MediaChannel* media_channel,
165 TransportController* transport_controller,
166 const std::string& content_name,
167 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200168 : worker_thread_(worker_thread),
169 network_thread_(network_thread),
170
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000171 content_name_(content_name),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200172
173 transport_controller_(transport_controller),
deadbeef23d947d2016-08-22 16:00:30 -0700174 rtcp_enabled_(rtcp),
michaelt79e05882016-11-08 02:50:09 -0800175 media_channel_(media_channel),
176 selected_candidate_pair_(nullptr) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700177 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200178 if (transport_controller) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200179 RTC_DCHECK_EQ(network_thread, transport_controller->network_thread());
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200180 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000181 LOG(LS_INFO) << "Created channel for " << content_name;
182}
183
184BaseChannel::~BaseChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800185 TRACE_EVENT0("webrtc", "BaseChannel::~BaseChannel");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700186 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
wu@webrtc.org78187522013-10-07 23:32:02 +0000187 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000188 StopConnectionMonitor();
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200189 // Eats any outstanding messages or packets.
190 worker_thread_->Clear(&invoker_);
191 worker_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000192 // We must destroy the media channel before the transport channel, otherwise
193 // the media channel may try to send on the dead transport channel. NULLing
194 // is not an effective strategy since the sends will come on another thread.
195 delete media_channel_;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200196 // Note that we don't just call SetTransportChannel_n(nullptr) because that
deadbeefcbecd352015-09-23 11:50:27 -0700197 // would call a pure virtual method which we can't do from a destructor.
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200198 network_thread_->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700199 RTC_FROM_HERE, Bind(&BaseChannel::DestroyTransportChannels_n, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200200 LOG(LS_INFO) << "Destroyed channel";
201}
202
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200203void BaseChannel::DisconnectTransportChannels_n() {
204 // Send any outstanding RTCP packets.
205 FlushRtcpMessages_n();
206
207 // Stop signals from transport channels, but keep them alive because
208 // media_channel may use them from a different thread.
deadbeefcbecd352015-09-23 11:50:27 -0700209 if (transport_channel_) {
210 DisconnectFromTransportChannel(transport_channel_);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200211 }
212 if (rtcp_transport_channel_) {
213 DisconnectFromTransportChannel(rtcp_transport_channel_);
214 }
215
216 // Clear pending read packets/messages.
217 network_thread_->Clear(&invoker_);
218 network_thread_->Clear(this);
219}
220
221void BaseChannel::DestroyTransportChannels_n() {
222 if (transport_channel_) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200223 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700224 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
225 }
226 if (rtcp_transport_channel_) {
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200227 transport_controller_->DestroyTransportChannel_n(
deadbeefcbecd352015-09-23 11:50:27 -0700228 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
229 }
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200230 // Clear pending send packets/messages.
231 network_thread_->Clear(&invoker_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200232 network_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000233}
234
skvlad6c87a672016-05-17 17:49:52 -0700235bool BaseChannel::Init_w(const std::string* bundle_transport_name) {
236 if (!network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700237 RTC_FROM_HERE,
skvlad6c87a672016-05-17 17:49:52 -0700238 Bind(&BaseChannel::InitNetwork_n, this, bundle_transport_name))) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000239 return false;
240 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000241
wu@webrtc.orgde305012013-10-31 15:40:38 +0000242 // Both RTP and RTCP channels are set, we can call SetInterface on
243 // media channel and it can set network options.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200244 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.orgde305012013-10-31 15:40:38 +0000245 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000246 return true;
247}
248
skvlad6c87a672016-05-17 17:49:52 -0700249bool BaseChannel::InitNetwork_n(const std::string* bundle_transport_name) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200250 RTC_DCHECK(network_thread_->IsCurrent());
skvlad6c87a672016-05-17 17:49:52 -0700251 const std::string& transport_name =
252 (bundle_transport_name ? *bundle_transport_name : content_name());
253 if (!SetTransport_n(transport_name)) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200254 return false;
255 }
256
257 if (!SetDtlsSrtpCryptoSuites_n(transport_channel_, false)) {
258 return false;
259 }
deadbeef23d947d2016-08-22 16:00:30 -0700260 if (rtcp_transport_channel_ &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200261 !SetDtlsSrtpCryptoSuites_n(rtcp_transport_channel_, true)) {
262 return false;
263 }
264 return true;
265}
266
wu@webrtc.org78187522013-10-07 23:32:02 +0000267void BaseChannel::Deinit() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200268 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.org78187522013-10-07 23:32:02 +0000269 media_channel_->SetInterface(NULL);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200270 // Packets arrive on the network thread, processing packets calls virtual
271 // functions, so need to stop this process in Deinit that is called in
272 // derived classes destructor.
273 network_thread_->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700274 RTC_FROM_HERE, Bind(&BaseChannel::DisconnectTransportChannels_n, this));
wu@webrtc.org78187522013-10-07 23:32:02 +0000275}
276
deadbeefcbecd352015-09-23 11:50:27 -0700277bool BaseChannel::SetTransport(const std::string& transport_name) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200278 return network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700279 RTC_FROM_HERE, Bind(&BaseChannel::SetTransport_n, this, transport_name));
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000280}
281
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200282bool BaseChannel::SetTransport_n(const std::string& transport_name) {
283 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000284
deadbeefcbecd352015-09-23 11:50:27 -0700285 if (transport_name == transport_name_) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700286 // Nothing to do if transport name isn't changing.
deadbeefcbecd352015-09-23 11:50:27 -0700287 return true;
288 }
289
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800290 // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport
291 // changes and wait until the DTLS handshake is complete to set the newly
292 // negotiated parameters.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200293 if (ShouldSetupDtlsSrtp_n()) {
guoweis46383312015-12-17 16:45:59 -0800294 // Set |writable_| to false such that UpdateWritableState_w can set up
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700295 // DTLS-SRTP when |writable_| becomes true again.
guoweis46383312015-12-17 16:45:59 -0800296 writable_ = false;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800297 srtp_filter_.ResetParams();
298 }
299
deadbeef23d947d2016-08-22 16:00:30 -0700300 // If this BaseChannel uses RTCP and we haven't fully negotiated RTCP mux,
301 // we need an RTCP channel.
302 if (rtcp_enabled_ && !rtcp_mux_filter_.IsFullyActive()) {
deadbeefcbecd352015-09-23 11:50:27 -0700303 LOG(LS_INFO) << "Create RTCP TransportChannel for " << content_name()
304 << " on " << transport_name << " transport ";
deadbeef062ce9f2016-08-26 21:42:15 -0700305 SetTransportChannel_n(
306 true, transport_controller_->CreateTransportChannel_n(
307 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200308 if (!rtcp_transport_channel_) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000309 return false;
310 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000311 }
312
deadbeef062ce9f2016-08-26 21:42:15 -0700313 LOG(LS_INFO) << "Create non-RTCP TransportChannel for " << content_name()
314 << " on " << transport_name << " transport ";
315 SetTransportChannel_n(
316 false, transport_controller_->CreateTransportChannel_n(
317 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200318 if (!transport_channel_) {
guoweis46383312015-12-17 16:45:59 -0800319 return false;
320 }
321
deadbeefcbecd352015-09-23 11:50:27 -0700322 transport_name_ = transport_name;
deadbeefcbecd352015-09-23 11:50:27 -0700323
324 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700325 // setting new transport channels.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200326 UpdateWritableState_n();
deadbeef062ce9f2016-08-26 21:42:15 -0700327 // We can only update ready-to-send after updating writability.
328 //
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700329 // On setting a new channel, assume it's ready to send if it's writable,
330 // because we have no way of knowing otherwise (the channel doesn't give us
331 // "was last send successful?").
332 //
333 // This won't always be accurate (the last SendPacket call from another
334 // BaseChannel could have resulted in an error), but even so, we'll just
335 // encounter the error again and update "ready to send" accordingly.
deadbeef062ce9f2016-08-26 21:42:15 -0700336 SetTransportChannelReadyToSend(
337 false, transport_channel_ && transport_channel_->writable());
338 SetTransportChannelReadyToSend(
339 true, rtcp_transport_channel_ && rtcp_transport_channel_->writable());
340 return true;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000341}
342
deadbeef062ce9f2016-08-26 21:42:15 -0700343void BaseChannel::SetTransportChannel_n(bool rtcp,
344 TransportChannel* new_channel) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200345 RTC_DCHECK(network_thread_->IsCurrent());
deadbeef062ce9f2016-08-26 21:42:15 -0700346 TransportChannel*& old_channel =
347 rtcp ? rtcp_transport_channel_ : transport_channel_;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000348
deadbeef062ce9f2016-08-26 21:42:15 -0700349 if (!old_channel && !new_channel) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700350 // Nothing to do.
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000351 return;
352 }
deadbeef062ce9f2016-08-26 21:42:15 -0700353 RTC_DCHECK(old_channel != new_channel);
deadbeefcbecd352015-09-23 11:50:27 -0700354
deadbeef062ce9f2016-08-26 21:42:15 -0700355 if (old_channel) {
356 DisconnectFromTransportChannel(old_channel);
Danil Chapovalov7f216b72016-05-12 09:20:31 +0200357 transport_controller_->DestroyTransportChannel_n(
deadbeef062ce9f2016-08-26 21:42:15 -0700358 transport_name_, rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP
359 : cricket::ICE_CANDIDATE_COMPONENT_RTP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000360 }
361
deadbeef062ce9f2016-08-26 21:42:15 -0700362 old_channel = new_channel;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000363
deadbeef062ce9f2016-08-26 21:42:15 -0700364 if (new_channel) {
365 if (rtcp) {
366 RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_filter_.IsActive()))
367 << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
368 << "should never happen.";
deadbeefcbecd352015-09-23 11:50:27 -0700369 }
deadbeef062ce9f2016-08-26 21:42:15 -0700370 ConnectToTransportChannel(new_channel);
371 auto& socket_options = rtcp ? rtcp_socket_options_ : socket_options_;
372 for (const auto& pair : socket_options) {
373 new_channel->SetOption(pair.first, pair.second);
374 }
guoweis46383312015-12-17 16:45:59 -0800375 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000376}
377
378void BaseChannel::ConnectToTransportChannel(TransportChannel* tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200379 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000380
381 tc->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
johand89ab142016-10-25 10:50:32 -0700382 tc->SignalReadPacket.connect(this, &BaseChannel::OnPacketRead);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000383 tc->SignalReadyToSend.connect(this, &BaseChannel::OnReadyToSend);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800384 tc->SignalDtlsState.connect(this, &BaseChannel::OnDtlsState);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700385 tc->SignalSelectedCandidatePairChanged.connect(
386 this, &BaseChannel::OnSelectedCandidatePairChanged);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200387 tc->SignalSentPacket.connect(this, &BaseChannel::SignalSentPacket_n);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000388}
389
390void BaseChannel::DisconnectFromTransportChannel(TransportChannel* tc) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200391 RTC_DCHECK(network_thread_->IsCurrent());
michaelt79e05882016-11-08 02:50:09 -0800392 OnSelectedCandidatePairChanged(tc, nullptr, -1, false);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000393
394 tc->SignalWritableState.disconnect(this);
395 tc->SignalReadPacket.disconnect(this);
396 tc->SignalReadyToSend.disconnect(this);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800397 tc->SignalDtlsState.disconnect(this);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200398 tc->SignalSelectedCandidatePairChanged.disconnect(this);
399 tc->SignalSentPacket.disconnect(this);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000400}
401
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000402bool BaseChannel::Enable(bool enable) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700403 worker_thread_->Invoke<void>(
404 RTC_FROM_HERE,
405 Bind(enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
406 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000407 return true;
408}
409
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000410bool BaseChannel::AddRecvStream(const StreamParams& sp) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700411 return InvokeOnWorker(RTC_FROM_HERE,
412 Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000413}
414
Peter Boström0c4e06b2015-10-07 12:23:21 +0200415bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700416 return InvokeOnWorker(RTC_FROM_HERE,
417 Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000418}
419
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000420bool BaseChannel::AddSendStream(const StreamParams& sp) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000421 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700422 RTC_FROM_HERE, Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000423}
424
Peter Boström0c4e06b2015-10-07 12:23:21 +0200425bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700426 return InvokeOnWorker(RTC_FROM_HERE, Bind(&MediaChannel::RemoveSendStream,
427 media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000428}
429
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000430bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000431 ContentAction action,
432 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100433 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700434 return InvokeOnWorker(RTC_FROM_HERE, Bind(&BaseChannel::SetLocalContent_w,
435 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000436}
437
438bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000439 ContentAction action,
440 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100441 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700442 return InvokeOnWorker(RTC_FROM_HERE, Bind(&BaseChannel::SetRemoteContent_w,
443 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000444}
445
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000446void BaseChannel::StartConnectionMonitor(int cms) {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000447 // We pass in the BaseChannel instead of the transport_channel_
448 // because if the transport_channel_ changes, the ConnectionMonitor
449 // would be pointing to the wrong TransportChannel.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200450 // We pass in the network thread because on that thread connection monitor
451 // will call BaseChannel::GetConnectionStats which must be called on the
452 // network thread.
453 connection_monitor_.reset(
454 new ConnectionMonitor(this, network_thread(), rtc::Thread::Current()));
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000455 connection_monitor_->SignalUpdate.connect(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000456 this, &BaseChannel::OnConnectionMonitorUpdate);
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000457 connection_monitor_->Start(cms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000458}
459
460void BaseChannel::StopConnectionMonitor() {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000461 if (connection_monitor_) {
462 connection_monitor_->Stop();
463 connection_monitor_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000464 }
465}
466
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000467bool BaseChannel::GetConnectionStats(ConnectionInfos* infos) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200468 RTC_DCHECK(network_thread_->IsCurrent());
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000469 return transport_channel_->GetStats(infos);
470}
471
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700472bool BaseChannel::IsReadyToReceiveMedia_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000473 // Receive data if we are enabled and have local content,
474 return enabled() && IsReceiveContentDirection(local_content_direction_);
475}
476
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700477bool BaseChannel::IsReadyToSendMedia_w() const {
478 // Need to access some state updated on the network thread.
479 return network_thread_->Invoke<bool>(
480 RTC_FROM_HERE, Bind(&BaseChannel::IsReadyToSendMedia_n, this));
481}
482
483bool BaseChannel::IsReadyToSendMedia_n() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000484 // Send outgoing data if we are enabled, have local and remote content,
485 // and we have had some form of connectivity.
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800486 return enabled() && IsReceiveContentDirection(remote_content_direction_) &&
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000487 IsSendContentDirection(local_content_direction_) &&
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700488 was_ever_writable() &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200489 (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp_n());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000490}
491
jbaucheec21bd2016-03-20 06:15:43 -0700492bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700493 const rtc::PacketOptions& options) {
494 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000495}
496
jbaucheec21bd2016-03-20 06:15:43 -0700497bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700498 const rtc::PacketOptions& options) {
499 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000500}
501
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000502int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000503 int value) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200504 return network_thread_->Invoke<int>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700505 RTC_FROM_HERE, Bind(&BaseChannel::SetOption_n, this, type, opt, value));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200506}
507
508int BaseChannel::SetOption_n(SocketType type,
509 rtc::Socket::Option opt,
510 int value) {
511 RTC_DCHECK(network_thread_->IsCurrent());
512 TransportChannel* channel = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000513 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000514 case ST_RTP:
515 channel = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700516 socket_options_.push_back(
517 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000518 break;
519 case ST_RTCP:
520 channel = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700521 rtcp_socket_options_.push_back(
522 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000523 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000524 }
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000525 return channel ? channel->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000526}
527
jbauchcb560652016-08-04 05:20:32 -0700528bool BaseChannel::SetCryptoOptions(const rtc::CryptoOptions& crypto_options) {
529 crypto_options_ = crypto_options;
530 return true;
531}
532
johand89ab142016-10-25 10:50:32 -0700533void BaseChannel::OnWritableState(rtc::PacketTransportInterface* transport) {
534 RTC_DCHECK(transport == transport_channel_ ||
535 transport == rtcp_transport_channel_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200536 RTC_DCHECK(network_thread_->IsCurrent());
537 UpdateWritableState_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000538}
539
johand89ab142016-10-25 10:50:32 -0700540void BaseChannel::OnPacketRead(rtc::PacketTransportInterface* transport,
541 const char* data,
542 size_t len,
543 const rtc::PacketTime& packet_time,
544 int flags) {
545 TRACE_EVENT0("webrtc", "BaseChannel::OnPacketRead");
546 // OnPacketRead gets called from P2PSocket; now pass data to MediaEngine
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200547 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000548
549 // When using RTCP multiplexing we might get RTCP packets on the RTP
550 // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
johand89ab142016-10-25 10:50:32 -0700551 bool rtcp = PacketIsRtcp(transport, data, len);
jbaucheec21bd2016-03-20 06:15:43 -0700552 rtc::CopyOnWriteBuffer packet(data, len);
wu@webrtc.orga9890802013-12-13 00:21:03 +0000553 HandlePacket(rtcp, &packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000554}
555
johand89ab142016-10-25 10:50:32 -0700556void BaseChannel::OnReadyToSend(rtc::PacketTransportInterface* transport) {
557 RTC_DCHECK(transport == transport_channel_ ||
558 transport == rtcp_transport_channel_);
559 SetTransportChannelReadyToSend(transport == rtcp_transport_channel_, true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000560}
561
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800562void BaseChannel::OnDtlsState(TransportChannel* channel,
563 DtlsTransportState state) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200564 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800565 return;
566 }
567
568 // Reset the srtp filter if it's not the CONNECTED state. For the CONNECTED
569 // state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to
570 // cover other scenarios like the whole channel is writable (not just this
571 // TransportChannel) or when TransportChannel is attached after DTLS is
572 // negotiated.
573 if (state != DTLS_TRANSPORT_CONNECTED) {
574 srtp_filter_.ResetParams();
575 }
576}
577
Honghai Zhangcc411c02016-03-29 17:27:21 -0700578void BaseChannel::OnSelectedCandidatePairChanged(
579 TransportChannel* channel,
Honghai Zhang52dce732016-03-31 12:37:31 -0700580 CandidatePairInterface* selected_candidate_pair,
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -0700581 int last_sent_packet_id,
582 bool ready_to_send) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700583 RTC_DCHECK(channel == transport_channel_ ||
584 channel == rtcp_transport_channel_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200585 RTC_DCHECK(network_thread_->IsCurrent());
michaelt79e05882016-11-08 02:50:09 -0800586 selected_candidate_pair_ = selected_candidate_pair;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200587 std::string transport_name = channel->transport_name();
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700588 rtc::NetworkRoute network_route;
Honghai Zhangcc411c02016-03-29 17:27:21 -0700589 if (selected_candidate_pair) {
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700590 network_route = rtc::NetworkRoute(
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -0700591 ready_to_send, selected_candidate_pair->local_candidate().network_id(),
Honghai Zhang0e533ef2016-04-19 15:41:36 -0700592 selected_candidate_pair->remote_candidate().network_id(),
593 last_sent_packet_id);
michaelt79e05882016-11-08 02:50:09 -0800594
595 UpdateTransportOverhead();
Honghai Zhangcc411c02016-03-29 17:27:21 -0700596 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200597 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700598 RTC_FROM_HERE, worker_thread_,
599 Bind(&MediaChannel::OnNetworkRouteChanged, media_channel_, transport_name,
600 network_route));
Honghai Zhangcc411c02016-03-29 17:27:21 -0700601}
602
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700603void BaseChannel::SetTransportChannelReadyToSend(bool rtcp, bool ready) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200604 RTC_DCHECK(network_thread_->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -0700605 if (rtcp) {
606 rtcp_ready_to_send_ = ready;
607 } else {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000608 rtp_ready_to_send_ = ready;
609 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000610
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200611 bool ready_to_send =
612 (rtp_ready_to_send_ &&
613 // In the case of rtcp mux |rtcp_transport_channel_| will be null.
614 (rtcp_ready_to_send_ || !rtcp_transport_channel_));
615
616 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700617 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200618 Bind(&MediaChannel::OnReadyToSend, media_channel_, ready_to_send));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000619}
620
johand89ab142016-10-25 10:50:32 -0700621bool BaseChannel::PacketIsRtcp(const rtc::PacketTransportInterface* transport,
622 const char* data,
623 size_t len) {
624 return (transport == rtcp_transport_channel_ ||
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000625 rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000626}
627
stefanc1aeaf02015-10-15 07:26:07 -0700628bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700629 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700630 const rtc::PacketOptions& options) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200631 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
632 // If the thread is not our network thread, we will post to our network
633 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000634 // synchronize access to all the pieces of the send path, including
635 // SRTP and the inner workings of the transport channels.
636 // The only downside is that we can't return a proper failure code if
637 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200638 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000639 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200640 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
641 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800642 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700643 data->options = options;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700644 network_thread_->Post(RTC_FROM_HERE, this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000645 return true;
646 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200647 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000648
649 // Now that we are on the correct thread, ensure we have a place to send this
650 // packet before doing anything. (We might get RTCP packets that we don't
651 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
652 // transport.
653 TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
654 transport_channel_ : rtcp_transport_channel_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000655 if (!channel || !channel->writable()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000656 return false;
657 }
658
659 // Protect ourselves against crazy data.
660 if (!ValidPacket(rtcp, packet)) {
661 LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000662 << PacketType(rtcp)
663 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000664 return false;
665 }
666
stefanc1aeaf02015-10-15 07:26:07 -0700667 rtc::PacketOptions updated_options;
668 updated_options = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669 // Protect if needed.
670 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200671 TRACE_EVENT0("webrtc", "SRTP Encode");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000672 bool res;
Karl Wibergc56ac1e2015-05-04 14:54:55 +0200673 uint8_t* data = packet->data();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000674 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000675 if (!rtcp) {
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000676 // If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
677 // inside libsrtp for a RTP packet. A external HMAC module will be writing
678 // a fake HMAC value. This is ONLY done for a RTP packet.
679 // Socket layer will update rtp sendtime extension header if present in
680 // packet with current time before updating the HMAC.
681#if !defined(ENABLE_EXTERNAL_AUTH)
682 res = srtp_filter_.ProtectRtp(
683 data, len, static_cast<int>(packet->capacity()), &len);
684#else
stefanc1aeaf02015-10-15 07:26:07 -0700685 updated_options.packet_time_params.rtp_sendtime_extension_id =
henrike@webrtc.org05376342014-03-10 15:53:12 +0000686 rtp_abs_sendtime_extn_id_;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000687 res = srtp_filter_.ProtectRtp(
688 data, len, static_cast<int>(packet->capacity()), &len,
stefanc1aeaf02015-10-15 07:26:07 -0700689 &updated_options.packet_time_params.srtp_packet_index);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000690 // If protection succeeds, let's get auth params from srtp.
691 if (res) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200692 uint8_t* auth_key = NULL;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000693 int key_len;
694 res = srtp_filter_.GetRtpAuthParams(
stefanc1aeaf02015-10-15 07:26:07 -0700695 &auth_key, &key_len,
696 &updated_options.packet_time_params.srtp_auth_tag_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000697 if (res) {
stefanc1aeaf02015-10-15 07:26:07 -0700698 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
699 updated_options.packet_time_params.srtp_auth_key.assign(
700 auth_key, auth_key + key_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000701 }
702 }
703#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000704 if (!res) {
705 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200706 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000707 GetRtpSeqNum(data, len, &seq_num);
708 GetRtpSsrc(data, len, &ssrc);
709 LOG(LS_ERROR) << "Failed to protect " << content_name_
710 << " RTP packet: size=" << len
711 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
712 return false;
713 }
714 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000715 res = srtp_filter_.ProtectRtcp(data, len,
716 static_cast<int>(packet->capacity()),
717 &len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000718 if (!res) {
719 int type = -1;
720 GetRtcpType(data, len, &type);
721 LOG(LS_ERROR) << "Failed to protect " << content_name_
722 << " RTCP packet: size=" << len << ", type=" << type;
723 return false;
724 }
725 }
726
727 // Update the length of the packet now that we've added the auth tag.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000728 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000729 } else if (secure_required_) {
730 // This is a double check for something that supposedly can't happen.
731 LOG(LS_ERROR) << "Can't send outgoing " << PacketType(rtcp)
732 << " packet when SRTP is inactive and crypto is required";
733
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700734 RTC_DCHECK(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000735 return false;
736 }
737
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000738 // Bon voyage.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200739 int flags = (secure() && secure_dtls()) ? PF_SRTP_BYPASS : PF_NORMAL;
740 int ret = channel->SendPacket(packet->data<char>(), packet->size(),
741 updated_options, flags);
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000742 if (ret != static_cast<int>(packet->size())) {
skvladc309e0e2016-07-28 17:15:20 -0700743 if (channel->GetError() == ENOTCONN) {
744 LOG(LS_WARNING) << "Got ENOTCONN from transport.";
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700745 SetTransportChannelReadyToSend(rtcp, false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000746 }
747 return false;
748 }
749 return true;
750}
751
jbaucheec21bd2016-03-20 06:15:43 -0700752bool BaseChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000753 // Protect ourselves against crazy data.
754 if (!ValidPacket(rtcp, packet)) {
755 LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000756 << PacketType(rtcp)
757 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000758 return false;
759 }
pbos482b12e2015-11-16 10:19:58 -0800760 if (rtcp) {
761 // Permit all (seemingly valid) RTCP packets.
762 return true;
763 }
764 // Check whether we handle this payload.
jbaucheec21bd2016-03-20 06:15:43 -0700765 return bundle_filter_.DemuxPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000766}
767
jbaucheec21bd2016-03-20 06:15:43 -0700768void BaseChannel::HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000769 const rtc::PacketTime& packet_time) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200770 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000771 if (!WantsPacket(rtcp, packet)) {
772 return;
773 }
774
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000775 // We are only interested in the first rtp packet because that
776 // indicates the media has started flowing.
777 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000778 has_received_packet_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700779 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000780 }
781
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000782 // Unprotect the packet, if needed.
783 if (srtp_filter_.IsActive()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200784 TRACE_EVENT0("webrtc", "SRTP Decode");
Karl Wiberg94784372015-04-20 14:03:07 +0200785 char* data = packet->data<char>();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000786 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000787 bool res;
788 if (!rtcp) {
789 res = srtp_filter_.UnprotectRtp(data, len, &len);
790 if (!res) {
791 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200792 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000793 GetRtpSeqNum(data, len, &seq_num);
794 GetRtpSsrc(data, len, &ssrc);
795 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
796 << " RTP packet: size=" << len
797 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
798 return;
799 }
800 } else {
801 res = srtp_filter_.UnprotectRtcp(data, len, &len);
802 if (!res) {
803 int type = -1;
804 GetRtcpType(data, len, &type);
805 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
806 << " RTCP packet: size=" << len << ", type=" << type;
807 return;
808 }
809 }
810
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000811 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000812 } else if (secure_required_) {
813 // Our session description indicates that SRTP is required, but we got a
814 // packet before our SRTP filter is active. This means either that
815 // a) we got SRTP packets before we received the SDES keys, in which case
816 // we can't decrypt it anyway, or
817 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
818 // channels, so we haven't yet extracted keys, even if DTLS did complete
819 // on the channel that the packets are being sent on. It's really good
820 // practice to wait for both RTP and RTCP to be good to go before sending
821 // media, to prevent weird failure modes, so it's fine for us to just eat
822 // packets here. This is all sidestepped if RTCP mux is used anyway.
823 LOG(LS_WARNING) << "Can't process incoming " << PacketType(rtcp)
824 << " packet when SRTP is inactive and crypto is required";
825 return;
826 }
827
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200828 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700829 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200830 Bind(&BaseChannel::OnPacketReceived, this, rtcp, *packet, packet_time));
831}
832
833void BaseChannel::OnPacketReceived(bool rtcp,
834 const rtc::CopyOnWriteBuffer& packet,
835 const rtc::PacketTime& packet_time) {
836 RTC_DCHECK(worker_thread_->IsCurrent());
837 // Need to copy variable because OnRtcpReceived/OnPacketReceived
838 // requires non-const pointer to buffer. This doesn't memcpy the actual data.
839 rtc::CopyOnWriteBuffer data(packet);
840 if (rtcp) {
841 media_channel_->OnRtcpReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000842 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200843 media_channel_->OnPacketReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000844 }
845}
846
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000847bool BaseChannel::PushdownLocalDescription(
848 const SessionDescription* local_desc, ContentAction action,
849 std::string* error_desc) {
850 const ContentInfo* content_info = GetFirstContent(local_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000851 const MediaContentDescription* content_desc =
852 GetContentDescription(content_info);
853 if (content_desc && content_info && !content_info->rejected &&
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000854 !SetLocalContent(content_desc, action, error_desc)) {
855 LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
856 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000857 }
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000858 return true;
859}
860
861bool BaseChannel::PushdownRemoteDescription(
862 const SessionDescription* remote_desc, ContentAction action,
863 std::string* error_desc) {
864 const ContentInfo* content_info = GetFirstContent(remote_desc);
865 const MediaContentDescription* content_desc =
866 GetContentDescription(content_info);
867 if (content_desc && content_info && !content_info->rejected &&
868 !SetRemoteContent(content_desc, action, error_desc)) {
869 LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
870 return false;
871 }
872 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000873}
874
875void BaseChannel::EnableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700876 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000877 if (enabled_)
878 return;
879
880 LOG(LS_INFO) << "Channel enabled";
881 enabled_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700882 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000883}
884
885void BaseChannel::DisableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700886 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000887 if (!enabled_)
888 return;
889
890 LOG(LS_INFO) << "Channel disabled";
891 enabled_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700892 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000893}
894
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200895void BaseChannel::UpdateWritableState_n() {
deadbeefcbecd352015-09-23 11:50:27 -0700896 if (transport_channel_ && transport_channel_->writable() &&
897 (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200898 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700899 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200900 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700901 }
902}
903
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200904void BaseChannel::ChannelWritable_n() {
905 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800906 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000907 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800908 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000909
deadbeefcbecd352015-09-23 11:50:27 -0700910 LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000911 << (was_ever_writable_ ? "" : " for the first time");
912
michaelt79e05882016-11-08 02:50:09 -0800913 if (selected_candidate_pair_)
914 LOG(LS_INFO)
915 << "Using "
916 << selected_candidate_pair_->local_candidate().ToSensitiveString()
917 << "->"
918 << selected_candidate_pair_->remote_candidate().ToSensitiveString();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000919
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000920 was_ever_writable_ = true;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200921 MaybeSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000922 writable_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700923 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000924}
925
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200926void BaseChannel::SignalDtlsSetupFailure_n(bool rtcp) {
927 RTC_DCHECK(network_thread_->IsCurrent());
928 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700929 RTC_FROM_HERE, signaling_thread(),
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200930 Bind(&BaseChannel::SignalDtlsSetupFailure_s, this, rtcp));
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000931}
932
933void BaseChannel::SignalDtlsSetupFailure_s(bool rtcp) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700934 RTC_DCHECK(signaling_thread() == rtc::Thread::Current());
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000935 SignalDtlsSetupFailure(this, rtcp);
936}
937
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200938bool BaseChannel::SetDtlsSrtpCryptoSuites_n(TransportChannel* tc, bool rtcp) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800939 std::vector<int> crypto_suites;
940 // We always use the default SRTP crypto suites for RTCP, but we may use
941 // different crypto suites for RTP depending on the media type.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000942 if (!rtcp) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200943 GetSrtpCryptoSuites_n(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000944 } else {
jbauchcb560652016-08-04 05:20:32 -0700945 GetDefaultSrtpCryptoSuites(crypto_options(), &crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000946 }
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800947 return tc->SetSrtpCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000948}
949
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200950bool BaseChannel::ShouldSetupDtlsSrtp_n() const {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800951 // Since DTLS is applied to all channels, checking RTP should be enough.
952 return transport_channel_ && transport_channel_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000953}
954
955// This function returns true if either DTLS-SRTP is not in use
956// *or* DTLS-SRTP is successfully set up.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200957bool BaseChannel::SetupDtlsSrtp_n(bool rtcp_channel) {
958 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000959 bool ret = false;
960
deadbeefcbecd352015-09-23 11:50:27 -0700961 TransportChannel* channel =
962 rtcp_channel ? rtcp_transport_channel_ : transport_channel_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000963
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800964 RTC_DCHECK(channel->IsDtlsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000965
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800966 int selected_crypto_suite;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000967
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800968 if (!channel->GetSrtpCryptoSuite(&selected_crypto_suite)) {
969 LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000970 return false;
971 }
972
973 LOG(LS_INFO) << "Installing keys from DTLS-SRTP on "
974 << content_name() << " "
975 << PacketType(rtcp_channel);
976
jbauchcb560652016-08-04 05:20:32 -0700977 int key_len;
978 int salt_len;
979 if (!rtc::GetSrtpKeyAndSaltLengths(selected_crypto_suite, &key_len,
980 &salt_len)) {
981 LOG(LS_ERROR) << "Unknown DTLS-SRTP crypto suite" << selected_crypto_suite;
982 return false;
983 }
984
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000985 // OK, we're now doing DTLS (RFC 5764)
jbauchcb560652016-08-04 05:20:32 -0700986 std::vector<unsigned char> dtls_buffer(key_len * 2 + salt_len * 2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000987
988 // RFC 5705 exporter using the RFC 5764 parameters
989 if (!channel->ExportKeyingMaterial(
990 kDtlsSrtpExporterLabel,
991 NULL, 0, false,
992 &dtls_buffer[0], dtls_buffer.size())) {
993 LOG(LS_WARNING) << "DTLS-SRTP key export failed";
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700994 RTC_DCHECK(false); // This should never happen
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000995 return false;
996 }
997
998 // Sync up the keys with the DTLS-SRTP interface
jbauchcb560652016-08-04 05:20:32 -0700999 std::vector<unsigned char> client_write_key(key_len + salt_len);
1000 std::vector<unsigned char> server_write_key(key_len + salt_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001001 size_t offset = 0;
jbauchcb560652016-08-04 05:20:32 -07001002 memcpy(&client_write_key[0], &dtls_buffer[offset], key_len);
1003 offset += key_len;
1004 memcpy(&server_write_key[0], &dtls_buffer[offset], key_len);
1005 offset += key_len;
1006 memcpy(&client_write_key[key_len], &dtls_buffer[offset], salt_len);
1007 offset += salt_len;
1008 memcpy(&server_write_key[key_len], &dtls_buffer[offset], salt_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001009
1010 std::vector<unsigned char> *send_key, *recv_key;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001011 rtc::SSLRole role;
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00001012 if (!channel->GetSslRole(&role)) {
1013 LOG(LS_WARNING) << "GetSslRole failed";
1014 return false;
1015 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001016
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001017 if (role == rtc::SSL_SERVER) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001018 send_key = &server_write_key;
1019 recv_key = &client_write_key;
1020 } else {
1021 send_key = &client_write_key;
1022 recv_key = &server_write_key;
1023 }
1024
1025 if (rtcp_channel) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001026 ret = srtp_filter_.SetRtcpParams(selected_crypto_suite, &(*send_key)[0],
1027 static_cast<int>(send_key->size()),
1028 selected_crypto_suite, &(*recv_key)[0],
1029 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001030 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001031 ret = srtp_filter_.SetRtpParams(selected_crypto_suite, &(*send_key)[0],
1032 static_cast<int>(send_key->size()),
1033 selected_crypto_suite, &(*recv_key)[0],
1034 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001035 }
1036
michaelt79e05882016-11-08 02:50:09 -08001037 if (!ret) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001038 LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
michaelt79e05882016-11-08 02:50:09 -08001039 } else {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001040 dtls_keyed_ = true;
michaelt79e05882016-11-08 02:50:09 -08001041 UpdateTransportOverhead();
1042 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001043 return ret;
1044}
1045
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001046void BaseChannel::MaybeSetupDtlsSrtp_n() {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001047 if (srtp_filter_.IsActive()) {
1048 return;
1049 }
1050
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001051 if (!ShouldSetupDtlsSrtp_n()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001052 return;
1053 }
1054
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001055 if (!SetupDtlsSrtp_n(false)) {
1056 SignalDtlsSetupFailure_n(false);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001057 return;
1058 }
1059
1060 if (rtcp_transport_channel_) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001061 if (!SetupDtlsSrtp_n(true)) {
1062 SignalDtlsSetupFailure_n(true);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08001063 return;
1064 }
1065 }
1066}
1067
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001068void BaseChannel::ChannelNotWritable_n() {
1069 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001070 if (!writable_)
1071 return;
1072
deadbeefcbecd352015-09-23 11:50:27 -07001073 LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001074 writable_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001075 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001076}
1077
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001078bool BaseChannel::SetRtpTransportParameters(
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001079 const MediaContentDescription* content,
1080 ContentAction action,
1081 ContentSource src,
1082 std::string* error_desc) {
1083 if (action == CA_UPDATE) {
1084 // These parameters never get changed by a CA_UDPATE.
1085 return true;
1086 }
1087
1088 // Cache secure_required_ for belt and suspenders check on SendPacket
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001089 return network_thread_->Invoke<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001090 RTC_FROM_HERE, Bind(&BaseChannel::SetRtpTransportParameters_n, this,
1091 content, action, src, error_desc));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001092}
1093
1094bool BaseChannel::SetRtpTransportParameters_n(
1095 const MediaContentDescription* content,
1096 ContentAction action,
1097 ContentSource src,
1098 std::string* error_desc) {
1099 RTC_DCHECK(network_thread_->IsCurrent());
1100
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001101 if (src == CS_LOCAL) {
1102 set_secure_required(content->crypto_required() != CT_NONE);
1103 }
1104
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001105 if (!SetSrtp_n(content->cryptos(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001106 return false;
1107 }
1108
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001109 if (!SetRtcpMux_n(content->rtcp_mux(), action, src, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001110 return false;
1111 }
1112
1113 return true;
1114}
1115
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001116// |dtls| will be set to true if DTLS is active for transport channel and
1117// crypto is empty.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001118bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
1119 bool* dtls,
1120 std::string* error_desc) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001121 *dtls = transport_channel_->IsDtlsActive();
1122 if (*dtls && !cryptos.empty()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001123 SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001124 return false;
1125 }
1126 return true;
1127}
1128
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001129bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001130 ContentAction action,
1131 ContentSource src,
1132 std::string* error_desc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001133 TRACE_EVENT0("webrtc", "BaseChannel::SetSrtp_w");
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001134 if (action == CA_UPDATE) {
1135 // no crypto params.
1136 return true;
1137 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001138 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001139 bool dtls = false;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001140 ret = CheckSrtpConfig_n(cryptos, &dtls, error_desc);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001141 if (!ret) {
1142 return false;
1143 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001144 switch (action) {
1145 case CA_OFFER:
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001146 // If DTLS is already active on the channel, we could be renegotiating
1147 // here. We don't update the srtp filter.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001148 if (!dtls) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001149 ret = srtp_filter_.SetOffer(cryptos, src);
1150 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001151 break;
1152 case CA_PRANSWER:
1153 // If we're doing DTLS-SRTP, we don't want to update the filter
1154 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001155 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001156 ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
1157 }
1158 break;
1159 case CA_ANSWER:
1160 // If we're doing DTLS-SRTP, we don't want to update the filter
1161 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001162 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001163 ret = srtp_filter_.SetAnswer(cryptos, src);
1164 }
1165 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001166 default:
1167 break;
1168 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001169 if (!ret) {
1170 SafeSetError("Failed to setup SRTP filter.", error_desc);
1171 return false;
1172 }
1173 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001174}
1175
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001176void BaseChannel::ActivateRtcpMux() {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001177 network_thread_->Invoke<void>(RTC_FROM_HERE,
1178 Bind(&BaseChannel::ActivateRtcpMux_n, this));
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001179}
1180
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001181void BaseChannel::ActivateRtcpMux_n() {
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001182 if (!rtcp_mux_filter_.IsActive()) {
1183 rtcp_mux_filter_.SetActive();
deadbeef062ce9f2016-08-26 21:42:15 -07001184 SetTransportChannel_n(true, nullptr);
1185 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
1186 // removing channel.
1187 UpdateWritableState_n();
1188 SetTransportChannelReadyToSend(true, false);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001189 }
1190}
1191
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001192bool BaseChannel::SetRtcpMux_n(bool enable,
1193 ContentAction action,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001194 ContentSource src,
1195 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001196 bool ret = false;
1197 switch (action) {
1198 case CA_OFFER:
1199 ret = rtcp_mux_filter_.SetOffer(enable, src);
1200 break;
1201 case CA_PRANSWER:
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001202 // This may activate RTCP muxing, but we don't yet destroy the channel
1203 // because the final answer may deactivate it.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001204 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
1205 break;
1206 case CA_ANSWER:
1207 ret = rtcp_mux_filter_.SetAnswer(enable, src);
1208 if (ret && rtcp_mux_filter_.IsActive()) {
1209 // We activated RTCP mux, close down the RTCP transport.
deadbeefcbecd352015-09-23 11:50:27 -07001210 LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
1211 << " by destroying RTCP transport channel for "
1212 << transport_name();
deadbeef062ce9f2016-08-26 21:42:15 -07001213 SetTransportChannel_n(true, nullptr);
1214 UpdateWritableState_n();
1215 SetTransportChannelReadyToSend(true, false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001216 }
1217 break;
1218 case CA_UPDATE:
1219 // No RTCP mux info.
1220 ret = true;
Henrik Kjellander7c027b62015-04-22 13:21:30 +02001221 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001222 default:
1223 break;
1224 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001225 if (!ret) {
1226 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
1227 return false;
1228 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001229 // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
1230 // CA_ANSWER, but we only want to tear down the RTCP transport channel if we
1231 // received a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001232 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001233 // If the RTP transport is already writable, then so are we.
1234 if (transport_channel_->writable()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001235 ChannelWritable_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001236 }
1237 }
1238
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001239 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001240}
1241
1242bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001243 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -08001244 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001245}
1246
Peter Boström0c4e06b2015-10-07 12:23:21 +02001247bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001248 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001249 return media_channel()->RemoveRecvStream(ssrc);
1250}
1251
1252bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001253 ContentAction action,
1254 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001255 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1256 action == CA_PRANSWER || action == CA_UPDATE))
1257 return false;
1258
1259 // If this is an update, streams only contain streams that have changed.
1260 if (action == CA_UPDATE) {
1261 for (StreamParamsVec::const_iterator it = streams.begin();
1262 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001263 const StreamParams* existing_stream =
1264 GetStreamByIds(local_streams_, it->groupid, it->id);
1265 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001266 if (media_channel()->AddSendStream(*it)) {
1267 local_streams_.push_back(*it);
1268 LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
1269 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001270 std::ostringstream desc;
1271 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1272 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001273 return false;
1274 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001275 } else if (existing_stream && !it->has_ssrcs()) {
1276 if (!media_channel()->RemoveSendStream(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001277 std::ostringstream desc;
1278 desc << "Failed to remove send stream with ssrc "
1279 << it->first_ssrc() << ".";
1280 SafeSetError(desc.str(), error_desc);
1281 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001282 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001283 RemoveStreamBySsrc(&local_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001284 } else {
1285 LOG(LS_WARNING) << "Ignore unsupported stream update";
1286 }
1287 }
1288 return true;
1289 }
1290 // Else streams are all the streams we want to send.
1291
1292 // Check for streams that have been removed.
1293 bool ret = true;
1294 for (StreamParamsVec::const_iterator it = local_streams_.begin();
1295 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001296 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001297 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001298 std::ostringstream desc;
1299 desc << "Failed to remove send stream with ssrc "
1300 << it->first_ssrc() << ".";
1301 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001302 ret = false;
1303 }
1304 }
1305 }
1306 // Check for new streams.
1307 for (StreamParamsVec::const_iterator it = streams.begin();
1308 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001309 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001310 if (media_channel()->AddSendStream(*it)) {
stefanc1aeaf02015-10-15 07:26:07 -07001311 LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001312 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001313 std::ostringstream desc;
1314 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1315 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001316 ret = false;
1317 }
1318 }
1319 }
1320 local_streams_ = streams;
1321 return ret;
1322}
1323
1324bool BaseChannel::UpdateRemoteStreams_w(
1325 const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001326 ContentAction action,
1327 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001328 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1329 action == CA_PRANSWER || action == CA_UPDATE))
1330 return false;
1331
1332 // If this is an update, streams only contain streams that have changed.
1333 if (action == CA_UPDATE) {
1334 for (StreamParamsVec::const_iterator it = streams.begin();
1335 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001336 const StreamParams* existing_stream =
1337 GetStreamByIds(remote_streams_, it->groupid, it->id);
1338 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001339 if (AddRecvStream_w(*it)) {
1340 remote_streams_.push_back(*it);
1341 LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
1342 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001343 std::ostringstream desc;
1344 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1345 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001346 return false;
1347 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001348 } else if (existing_stream && !it->has_ssrcs()) {
1349 if (!RemoveRecvStream_w(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001350 std::ostringstream desc;
1351 desc << "Failed to remove remote stream with ssrc "
1352 << it->first_ssrc() << ".";
1353 SafeSetError(desc.str(), error_desc);
1354 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001355 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001356 RemoveStreamBySsrc(&remote_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001357 } else {
1358 LOG(LS_WARNING) << "Ignore unsupported stream update."
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001359 << " Stream exists? " << (existing_stream != nullptr)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001360 << " new stream = " << it->ToString();
1361 }
1362 }
1363 return true;
1364 }
1365 // Else streams are all the streams we want to receive.
1366
1367 // Check for streams that have been removed.
1368 bool ret = true;
1369 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
1370 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001371 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001372 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001373 std::ostringstream desc;
1374 desc << "Failed to remove remote stream with ssrc "
1375 << it->first_ssrc() << ".";
1376 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001377 ret = false;
1378 }
1379 }
1380 }
1381 // Check for new streams.
1382 for (StreamParamsVec::const_iterator it = streams.begin();
1383 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001384 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001385 if (AddRecvStream_w(*it)) {
1386 LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
1387 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001388 std::ostringstream desc;
1389 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1390 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001391 ret = false;
1392 }
1393 }
1394 }
1395 remote_streams_ = streams;
1396 return ret;
1397}
1398
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001399void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w(
isheriff6f8d6862016-05-26 11:24:55 -07001400 const std::vector<webrtc::RtpExtension>& extensions) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001401// Absolute Send Time extension id is used only with external auth,
1402// so do not bother searching for it and making asyncronious call to set
1403// something that is not used.
1404#if defined(ENABLE_EXTERNAL_AUTH)
isheriff6f8d6862016-05-26 11:24:55 -07001405 const webrtc::RtpExtension* send_time_extension =
1406 FindHeaderExtension(extensions, webrtc::RtpExtension::kAbsSendTimeUri);
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001407 int rtp_abs_sendtime_extn_id =
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001408 send_time_extension ? send_time_extension->id : -1;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001409 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001410 RTC_FROM_HERE, network_thread_,
1411 Bind(&BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n, this,
1412 rtp_abs_sendtime_extn_id));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001413#endif
1414}
1415
1416void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n(
1417 int rtp_abs_sendtime_extn_id) {
1418 rtp_abs_sendtime_extn_id_ = rtp_abs_sendtime_extn_id;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001419}
1420
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001421void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001422 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001423 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001424 case MSG_SEND_RTP_PACKET:
1425 case MSG_SEND_RTCP_PACKET: {
1426 RTC_DCHECK(network_thread_->IsCurrent());
1427 SendPacketMessageData* data =
1428 static_cast<SendPacketMessageData*>(pmsg->pdata);
1429 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
1430 SendPacket(rtcp, &data->packet, data->options);
1431 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001432 break;
1433 }
1434 case MSG_FIRSTPACKETRECEIVED: {
1435 SignalFirstPacketReceived(this);
1436 break;
1437 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001438 }
1439}
1440
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001441void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001442 // Flush all remaining RTCP messages. This should only be called in
1443 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001444 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001445 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001446 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
1447 for (const auto& message : rtcp_messages) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001448 network_thread_->Send(RTC_FROM_HERE, this, MSG_SEND_RTCP_PACKET,
1449 message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001450 }
1451}
1452
johand89ab142016-10-25 10:50:32 -07001453void BaseChannel::SignalSentPacket_n(
1454 rtc::PacketTransportInterface* /* transport */,
1455 const rtc::SentPacket& sent_packet) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001456 RTC_DCHECK(network_thread_->IsCurrent());
1457 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001458 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001459 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
1460}
1461
1462void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
1463 RTC_DCHECK(worker_thread_->IsCurrent());
1464 SignalSentPacket(sent_packet);
1465}
1466
1467VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
1468 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001469 MediaEngineInterface* media_engine,
1470 VoiceMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001471 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001472 const std::string& content_name,
1473 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001474 : BaseChannel(worker_thread,
1475 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001476 media_channel,
1477 transport_controller,
1478 content_name,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001479 rtcp),
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001480 media_engine_(media_engine),
deadbeefcbecd352015-09-23 11:50:27 -07001481 received_media_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001482
1483VoiceChannel::~VoiceChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001484 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001485 StopAudioMonitor();
1486 StopMediaMonitor();
1487 // this can't be done in the base class, since it calls a virtual
1488 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001489 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001490}
1491
skvlad6c87a672016-05-17 17:49:52 -07001492bool VoiceChannel::Init_w(const std::string* bundle_transport_name) {
1493 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001494 return false;
1495 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001496 return true;
1497}
1498
Peter Boström0c4e06b2015-10-07 12:23:21 +02001499bool VoiceChannel::SetAudioSend(uint32_t ssrc,
solenbergdfc8f4f2015-10-01 02:31:10 -07001500 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001501 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001502 AudioSource* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001503 return InvokeOnWorker(RTC_FROM_HERE,
1504 Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001505 ssrc, enable, options, source));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506}
1507
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001508// TODO(juberti): Handle early media the right way. We should get an explicit
1509// ringing message telling us to start playing local ringback, which we cancel
1510// if any early media actually arrives. For now, we do the opposite, which is
1511// to wait 1 second for early media, and start playing local ringback if none
1512// arrives.
1513void VoiceChannel::SetEarlyMedia(bool enable) {
1514 if (enable) {
1515 // Start the early media timeout
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001516 worker_thread()->PostDelayed(RTC_FROM_HERE, kEarlyMediaTimeout, this,
1517 MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001518 } else {
1519 // Stop the timeout if currently going.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001520 worker_thread()->Clear(this, MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001521 }
1522}
1523
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001524bool VoiceChannel::CanInsertDtmf() {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001525 return InvokeOnWorker(
1526 RTC_FROM_HERE, Bind(&VoiceMediaChannel::CanInsertDtmf, media_channel()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001527}
1528
Peter Boström0c4e06b2015-10-07 12:23:21 +02001529bool VoiceChannel::InsertDtmf(uint32_t ssrc,
1530 int event_code,
solenberg1d63dd02015-12-02 12:35:09 -08001531 int duration) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001532 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceChannel::InsertDtmf_w, this,
1533 ssrc, event_code, duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001534}
1535
solenberg4bac9c52015-10-09 02:32:53 -07001536bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001537 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::SetOutputVolume,
1538 media_channel(), ssrc, volume));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539}
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001540
Tommif888bb52015-12-12 01:37:01 +01001541void VoiceChannel::SetRawAudioSink(
1542 uint32_t ssrc,
kwiberg31022942016-03-11 14:18:21 -08001543 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
1544 // We need to work around Bind's lack of support for unique_ptr and ownership
deadbeef2d110be2016-01-13 12:00:26 -08001545 // passing. So we invoke to our own little routine that gets a pointer to
1546 // our local variable. This is OK since we're synchronously invoking.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001547 InvokeOnWorker(RTC_FROM_HERE,
1548 Bind(&SetRawAudioSink_w, media_channel(), ssrc, &sink));
Tommif888bb52015-12-12 01:37:01 +01001549}
1550
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001551webrtc::RtpParameters VoiceChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001552 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001553 RTC_FROM_HERE, Bind(&VoiceChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001554}
1555
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001556webrtc::RtpParameters VoiceChannel::GetRtpSendParameters_w(
1557 uint32_t ssrc) const {
1558 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001559}
1560
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001561bool VoiceChannel::SetRtpSendParameters(
1562 uint32_t ssrc,
1563 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001564 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001565 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001566 Bind(&VoiceChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001567}
1568
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001569bool VoiceChannel::SetRtpSendParameters_w(uint32_t ssrc,
1570 webrtc::RtpParameters parameters) {
1571 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1572}
1573
1574webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters(
1575 uint32_t ssrc) const {
1576 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001577 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001578 Bind(&VoiceChannel::GetRtpReceiveParameters_w, this, ssrc));
1579}
1580
1581webrtc::RtpParameters VoiceChannel::GetRtpReceiveParameters_w(
1582 uint32_t ssrc) const {
1583 return media_channel()->GetRtpReceiveParameters(ssrc);
1584}
1585
1586bool VoiceChannel::SetRtpReceiveParameters(
1587 uint32_t ssrc,
1588 const webrtc::RtpParameters& parameters) {
1589 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001590 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001591 Bind(&VoiceChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1592}
1593
1594bool VoiceChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1595 webrtc::RtpParameters parameters) {
1596 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001597}
1598
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001599bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001600 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VoiceMediaChannel::GetStats,
1601 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001602}
1603
1604void VoiceChannel::StartMediaMonitor(int cms) {
1605 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001606 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607 media_monitor_->SignalUpdate.connect(
1608 this, &VoiceChannel::OnMediaMonitorUpdate);
1609 media_monitor_->Start(cms);
1610}
1611
1612void VoiceChannel::StopMediaMonitor() {
1613 if (media_monitor_) {
1614 media_monitor_->Stop();
1615 media_monitor_->SignalUpdate.disconnect(this);
1616 media_monitor_.reset();
1617 }
1618}
1619
1620void VoiceChannel::StartAudioMonitor(int cms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001621 audio_monitor_.reset(new AudioMonitor(this, rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001622 audio_monitor_
1623 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1624 audio_monitor_->Start(cms);
1625}
1626
1627void VoiceChannel::StopAudioMonitor() {
1628 if (audio_monitor_) {
1629 audio_monitor_->Stop();
1630 audio_monitor_.reset();
1631 }
1632}
1633
1634bool VoiceChannel::IsAudioMonitorRunning() const {
1635 return (audio_monitor_.get() != NULL);
1636}
1637
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001638int VoiceChannel::GetInputLevel_w() {
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001639 return media_engine_->GetInputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001640}
1641
1642int VoiceChannel::GetOutputLevel_w() {
1643 return media_channel()->GetOutputLevel();
1644}
1645
1646void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1647 media_channel()->GetActiveStreams(actives);
1648}
1649
johand89ab142016-10-25 10:50:32 -07001650void VoiceChannel::OnPacketRead(rtc::PacketTransportInterface* transport,
1651 const char* data,
1652 size_t len,
1653 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001654 int flags) {
johand89ab142016-10-25 10:50:32 -07001655 BaseChannel::OnPacketRead(transport, data, len, packet_time, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001656 // Set a flag when we've received an RTP packet. If we're waiting for early
1657 // media, this will disable the timeout.
johand89ab142016-10-25 10:50:32 -07001658 if (!received_media_ && !PacketIsRtcp(transport, data, len)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001659 received_media_ = true;
1660 }
1661}
1662
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001663void BaseChannel::UpdateMediaSendRecvState() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001664 RTC_DCHECK(network_thread_->IsCurrent());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001665 invoker_.AsyncInvoke<void>(
1666 RTC_FROM_HERE, worker_thread_,
1667 Bind(&BaseChannel::UpdateMediaSendRecvState_w, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001668}
1669
michaelt79e05882016-11-08 02:50:09 -08001670int BaseChannel::GetTransportOverheadPerPacket() const {
1671 RTC_DCHECK(network_thread_->IsCurrent());
1672
1673 if (!selected_candidate_pair_)
1674 return 0;
1675
1676 int transport_overhead_per_packet = 0;
1677
1678 constexpr int kIpv4Overhaed = 20;
1679 constexpr int kIpv6Overhaed = 40;
1680 transport_overhead_per_packet +=
1681 selected_candidate_pair_->local_candidate().address().family() == AF_INET
1682 ? kIpv4Overhaed
1683 : kIpv6Overhaed;
1684
1685 constexpr int kUdpOverhaed = 8;
1686 constexpr int kTcpOverhaed = 20;
1687 transport_overhead_per_packet +=
1688 selected_candidate_pair_->local_candidate().protocol() ==
1689 TCP_PROTOCOL_NAME
1690 ? kTcpOverhaed
1691 : kUdpOverhaed;
1692
1693 if (secure()) {
1694 int srtp_overhead = 0;
1695 if (srtp_filter_.GetSrtpOverhead(&srtp_overhead))
1696 transport_overhead_per_packet += srtp_overhead;
1697 }
1698
1699 return transport_overhead_per_packet;
1700}
1701
1702void BaseChannel::UpdateTransportOverhead() {
1703 int transport_overhead_per_packet = GetTransportOverheadPerPacket();
1704 if (transport_overhead_per_packet)
1705 invoker_.AsyncInvoke<void>(
1706 RTC_FROM_HERE, worker_thread_,
1707 Bind(&MediaChannel::OnTransportOverheadChanged, media_channel_,
1708 transport_overhead_per_packet));
1709}
1710
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001711void VoiceChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001712 // Render incoming data if we're the active call, and we have the local
1713 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001714 bool recv = IsReadyToReceiveMedia_w();
solenberg5b14b422015-10-01 04:10:31 -07001715 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001716
1717 // Send outgoing data if we're the active call, we have the remote content,
1718 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001719 bool send = IsReadyToSendMedia_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001720 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001721
1722 LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
1723}
1724
1725const ContentInfo* VoiceChannel::GetFirstContent(
1726 const SessionDescription* sdesc) {
1727 return GetFirstAudioContent(sdesc);
1728}
1729
1730bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001731 ContentAction action,
1732 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001733 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001734 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001735 LOG(LS_INFO) << "Setting local voice description";
1736
1737 const AudioContentDescription* audio =
1738 static_cast<const AudioContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001739 RTC_DCHECK(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001740 if (!audio) {
1741 SafeSetError("Can't find audio content in local description.", error_desc);
1742 return false;
1743 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001744
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001745 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001746 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001747 }
1748
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001749 AudioRecvParameters recv_params = last_recv_params_;
1750 RtpParametersFromMediaDescription(audio, &recv_params);
1751 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001752 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001753 error_desc);
1754 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001755 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001756 for (const AudioCodec& codec : audio->codecs()) {
1757 bundle_filter()->AddPayloadType(codec.id);
1758 }
1759 last_recv_params_ = recv_params;
1760
1761 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1762 // only give it to the media channel once we have a remote
1763 // description too (without a remote description, we won't be able
1764 // to send them anyway).
1765 if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) {
1766 SafeSetError("Failed to set local audio description streams.", error_desc);
1767 return false;
1768 }
1769
1770 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001771 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001772 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001773}
1774
1775bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001776 ContentAction action,
1777 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001778 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001779 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001780 LOG(LS_INFO) << "Setting remote voice description";
1781
1782 const AudioContentDescription* audio =
1783 static_cast<const AudioContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001784 RTC_DCHECK(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001785 if (!audio) {
1786 SafeSetError("Can't find audio content in remote description.", error_desc);
1787 return false;
1788 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001789
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001790 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001791 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001792 }
1793
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001794 AudioSendParameters send_params = last_send_params_;
1795 RtpSendParametersFromMediaDescription(audio, &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001796 if (audio->agc_minus_10db()) {
Karl Wibergbe579832015-11-10 22:34:18 +01001797 send_params.options.adjust_agc_delta = rtc::Optional<int>(kAgcMinus10db);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001798 }
skvladdc1c62c2016-03-16 19:07:43 -07001799
1800 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1801 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001802 SafeSetError("Failed to set remote audio description send parameters.",
1803 error_desc);
1804 return false;
1805 }
1806 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001807
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001808 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1809 // and only give it to the media channel once we have a local
1810 // description too (without a local description, we won't be able to
1811 // recv them anyway).
1812 if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) {
1813 SafeSetError("Failed to set remote audio description streams.", error_desc);
1814 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001815 }
1816
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001817 if (audio->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001818 MaybeCacheRtpAbsSendTimeHeaderExtension_w(audio->rtp_header_extensions());
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001819 }
1820
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001821 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001822 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001823 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001824}
1825
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001826void VoiceChannel::HandleEarlyMediaTimeout() {
1827 // This occurs on the main thread, not the worker thread.
1828 if (!received_media_) {
1829 LOG(LS_INFO) << "No early media received before timeout";
1830 SignalEarlyMediaTimeout(this);
1831 }
1832}
1833
Peter Boström0c4e06b2015-10-07 12:23:21 +02001834bool VoiceChannel::InsertDtmf_w(uint32_t ssrc,
1835 int event,
solenberg1d63dd02015-12-02 12:35:09 -08001836 int duration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001837 if (!enabled()) {
1838 return false;
1839 }
solenberg1d63dd02015-12-02 12:35:09 -08001840 return media_channel()->InsertDtmf(ssrc, event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001841}
1842
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001843void VoiceChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001844 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001845 case MSG_EARLYMEDIATIMEOUT:
1846 HandleEarlyMediaTimeout();
1847 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001848 case MSG_CHANNEL_ERROR: {
1849 VoiceChannelErrorMessageData* data =
1850 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001851 delete data;
1852 break;
1853 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001854 default:
1855 BaseChannel::OnMessage(pmsg);
1856 break;
1857 }
1858}
1859
1860void VoiceChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001861 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001862 SignalConnectionMonitor(this, infos);
1863}
1864
1865void VoiceChannel::OnMediaMonitorUpdate(
1866 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001867 RTC_DCHECK(media_channel == this->media_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001868 SignalMediaMonitor(this, info);
1869}
1870
1871void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1872 const AudioInfo& info) {
1873 SignalAudioMonitor(this, info);
1874}
1875
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001876void VoiceChannel::GetSrtpCryptoSuites_n(
1877 std::vector<int>* crypto_suites) const {
jbauchcb560652016-08-04 05:20:32 -07001878 GetSupportedAudioCryptoSuites(crypto_options(), crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001879}
1880
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001881VideoChannel::VideoChannel(rtc::Thread* worker_thread,
1882 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001883 VideoMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001884 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001885 const std::string& content_name,
Fredrik Solenberg7fb711f2015-04-22 15:30:51 +02001886 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001887 : BaseChannel(worker_thread,
1888 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07001889 media_channel,
1890 transport_controller,
1891 content_name,
perkjc11b1842016-03-07 17:34:13 -08001892 rtcp) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001893
skvlad6c87a672016-05-17 17:49:52 -07001894bool VideoChannel::Init_w(const std::string* bundle_transport_name) {
1895 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001896 return false;
1897 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001898 return true;
1899}
1900
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001901VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08001902 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001903 StopMediaMonitor();
1904 // this can't be done in the base class, since it calls a virtual
1905 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001906
1907 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001908}
1909
nisse08582ff2016-02-04 01:24:52 -08001910bool VideoChannel::SetSink(uint32_t ssrc,
nisseacd935b2016-11-11 03:55:13 -08001911 rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) {
nisse08582ff2016-02-04 01:24:52 -08001912 worker_thread()->Invoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001913 RTC_FROM_HERE,
nisse08582ff2016-02-04 01:24:52 -08001914 Bind(&VideoMediaChannel::SetSink, media_channel(), ssrc, sink));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001915 return true;
1916}
1917
deadbeef5a4a75a2016-06-02 16:23:38 -07001918bool VideoChannel::SetVideoSend(
nisse2ded9b12016-04-08 02:23:55 -07001919 uint32_t ssrc,
deadbeef5a4a75a2016-06-02 16:23:38 -07001920 bool mute,
1921 const VideoOptions* options,
nisseacd935b2016-11-11 03:55:13 -08001922 rtc::VideoSourceInterface<webrtc::VideoFrame>* source) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001923 return InvokeOnWorker(RTC_FROM_HERE,
1924 Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
deadbeef5a4a75a2016-06-02 16:23:38 -07001925 ssrc, mute, options, source));
solenberg1dd98f32015-09-10 01:57:14 -07001926}
1927
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001928webrtc::RtpParameters VideoChannel::GetRtpSendParameters(uint32_t ssrc) const {
skvladdc1c62c2016-03-16 19:07:43 -07001929 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001930 RTC_FROM_HERE, Bind(&VideoChannel::GetRtpSendParameters_w, this, ssrc));
skvladdc1c62c2016-03-16 19:07:43 -07001931}
1932
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001933webrtc::RtpParameters VideoChannel::GetRtpSendParameters_w(
1934 uint32_t ssrc) const {
1935 return media_channel()->GetRtpSendParameters(ssrc);
skvladdc1c62c2016-03-16 19:07:43 -07001936}
1937
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001938bool VideoChannel::SetRtpSendParameters(
1939 uint32_t ssrc,
1940 const webrtc::RtpParameters& parameters) {
skvladdc1c62c2016-03-16 19:07:43 -07001941 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001942 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001943 Bind(&VideoChannel::SetRtpSendParameters_w, this, ssrc, parameters));
skvladdc1c62c2016-03-16 19:07:43 -07001944}
1945
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001946bool VideoChannel::SetRtpSendParameters_w(uint32_t ssrc,
1947 webrtc::RtpParameters parameters) {
1948 return media_channel()->SetRtpSendParameters(ssrc, parameters);
1949}
1950
1951webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters(
1952 uint32_t ssrc) const {
1953 return worker_thread()->Invoke<webrtc::RtpParameters>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001954 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001955 Bind(&VideoChannel::GetRtpReceiveParameters_w, this, ssrc));
1956}
1957
1958webrtc::RtpParameters VideoChannel::GetRtpReceiveParameters_w(
1959 uint32_t ssrc) const {
1960 return media_channel()->GetRtpReceiveParameters(ssrc);
1961}
1962
1963bool VideoChannel::SetRtpReceiveParameters(
1964 uint32_t ssrc,
1965 const webrtc::RtpParameters& parameters) {
1966 return InvokeOnWorker(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001967 RTC_FROM_HERE,
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001968 Bind(&VideoChannel::SetRtpReceiveParameters_w, this, ssrc, parameters));
1969}
1970
1971bool VideoChannel::SetRtpReceiveParameters_w(uint32_t ssrc,
1972 webrtc::RtpParameters parameters) {
1973 return media_channel()->SetRtpReceiveParameters(ssrc, parameters);
skvladdc1c62c2016-03-16 19:07:43 -07001974}
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001975
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001976void VideoChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001977 // Send outgoing data if we're the active call, we have the remote content,
1978 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001979 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001980 if (!media_channel()->SetSend(send)) {
1981 LOG(LS_ERROR) << "Failed to SetSend on video channel";
1982 // TODO(gangji): Report error back to server.
1983 }
1984
Peter Boström34fbfff2015-09-24 19:20:30 +02001985 LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001986}
1987
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00001988bool VideoChannel::GetStats(VideoMediaInfo* stats) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001989 return InvokeOnWorker(RTC_FROM_HERE, Bind(&VideoMediaChannel::GetStats,
1990 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001991}
1992
1993void VideoChannel::StartMediaMonitor(int cms) {
1994 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001995 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001996 media_monitor_->SignalUpdate.connect(
1997 this, &VideoChannel::OnMediaMonitorUpdate);
1998 media_monitor_->Start(cms);
1999}
2000
2001void VideoChannel::StopMediaMonitor() {
2002 if (media_monitor_) {
2003 media_monitor_->Stop();
2004 media_monitor_.reset();
2005 }
2006}
2007
2008const ContentInfo* VideoChannel::GetFirstContent(
2009 const SessionDescription* sdesc) {
2010 return GetFirstVideoContent(sdesc);
2011}
2012
2013bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002014 ContentAction action,
2015 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002016 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002017 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002018 LOG(LS_INFO) << "Setting local video description";
2019
2020 const VideoContentDescription* video =
2021 static_cast<const VideoContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002022 RTC_DCHECK(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002023 if (!video) {
2024 SafeSetError("Can't find video content in local description.", error_desc);
2025 return false;
2026 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002027
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002028 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002029 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002030 }
2031
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002032 VideoRecvParameters recv_params = last_recv_params_;
2033 RtpParametersFromMediaDescription(video, &recv_params);
2034 if (!media_channel()->SetRecvParameters(recv_params)) {
2035 SafeSetError("Failed to set local video description recv parameters.",
2036 error_desc);
2037 return false;
2038 }
2039 for (const VideoCodec& codec : video->codecs()) {
2040 bundle_filter()->AddPayloadType(codec.id);
2041 }
2042 last_recv_params_ = recv_params;
2043
2044 // TODO(pthatcher): Move local streams into VideoSendParameters, and
2045 // only give it to the media channel once we have a remote
2046 // description too (without a remote description, we won't be able
2047 // to send them anyway).
2048 if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) {
2049 SafeSetError("Failed to set local video description streams.", error_desc);
2050 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002051 }
2052
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002053 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002054 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002055 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002056}
2057
2058bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002059 ContentAction action,
2060 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002061 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002062 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002063 LOG(LS_INFO) << "Setting remote video description";
2064
2065 const VideoContentDescription* video =
2066 static_cast<const VideoContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002067 RTC_DCHECK(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002068 if (!video) {
2069 SafeSetError("Can't find video content in remote description.", error_desc);
2070 return false;
2071 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002072
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002073 if (!SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002074 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002075 }
2076
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002077 VideoSendParameters send_params = last_send_params_;
2078 RtpSendParametersFromMediaDescription(video, &send_params);
2079 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08002080 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002081 }
skvladdc1c62c2016-03-16 19:07:43 -07002082
2083 bool parameters_applied = media_channel()->SetSendParameters(send_params);
2084
2085 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002086 SafeSetError("Failed to set remote video description send parameters.",
2087 error_desc);
2088 return false;
2089 }
2090 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002091
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002092 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
2093 // and only give it to the media channel once we have a local
2094 // description too (without a local description, we won't be able to
2095 // recv them anyway).
2096 if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) {
2097 SafeSetError("Failed to set remote video description streams.", error_desc);
2098 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002099 }
2100
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002101 if (video->rtp_header_extensions_set()) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002102 MaybeCacheRtpAbsSendTimeHeaderExtension_w(video->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002103 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002104
2105 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002106 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002107 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002108}
2109
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002110void VideoChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002111 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002112 case MSG_CHANNEL_ERROR: {
2113 const VideoChannelErrorMessageData* data =
2114 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002115 delete data;
2116 break;
2117 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002118 default:
2119 BaseChannel::OnMessage(pmsg);
2120 break;
2121 }
2122}
2123
2124void VideoChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002125 ConnectionMonitor* monitor, const std::vector<ConnectionInfo> &infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002126 SignalConnectionMonitor(this, infos);
2127}
2128
2129// TODO(pthatcher): Look into removing duplicate code between
2130// audio, video, and data, perhaps by using templates.
2131void VideoChannel::OnMediaMonitorUpdate(
2132 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002133 RTC_DCHECK(media_channel == this->media_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002134 SignalMediaMonitor(this, info);
2135}
2136
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002137void VideoChannel::GetSrtpCryptoSuites_n(
2138 std::vector<int>* crypto_suites) const {
jbauchcb560652016-08-04 05:20:32 -07002139 GetSupportedVideoCryptoSuites(crypto_options(), crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002140}
2141
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002142DataChannel::DataChannel(rtc::Thread* worker_thread,
2143 rtc::Thread* network_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002144 DataMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07002145 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002146 const std::string& content_name,
2147 bool rtcp)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002148 : BaseChannel(worker_thread,
2149 network_thread,
deadbeefcbecd352015-09-23 11:50:27 -07002150 media_channel,
2151 transport_controller,
2152 content_name,
2153 rtcp),
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002154 data_channel_type_(cricket::DCT_NONE),
deadbeefcbecd352015-09-23 11:50:27 -07002155 ready_to_send_data_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002156
2157DataChannel::~DataChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -08002158 TRACE_EVENT0("webrtc", "DataChannel::~DataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002159 StopMediaMonitor();
2160 // this can't be done in the base class, since it calls a virtual
2161 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00002162
2163 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002164}
2165
skvlad6c87a672016-05-17 17:49:52 -07002166bool DataChannel::Init_w(const std::string* bundle_transport_name) {
2167 if (!BaseChannel::Init_w(bundle_transport_name)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002168 return false;
2169 }
2170 media_channel()->SignalDataReceived.connect(
2171 this, &DataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002172 media_channel()->SignalReadyToSend.connect(
2173 this, &DataChannel::OnDataChannelReadyToSend);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002174 media_channel()->SignalStreamClosedRemotely.connect(
2175 this, &DataChannel::OnStreamClosedRemotely);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002176 return true;
2177}
2178
2179bool DataChannel::SendData(const SendDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -07002180 const rtc::CopyOnWriteBuffer& payload,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002181 SendDataResult* result) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002182 return InvokeOnWorker(
2183 RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params,
2184 payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002185}
2186
2187const ContentInfo* DataChannel::GetFirstContent(
2188 const SessionDescription* sdesc) {
2189 return GetFirstDataContent(sdesc);
2190}
2191
jbaucheec21bd2016-03-20 06:15:43 -07002192bool DataChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002193 if (data_channel_type_ == DCT_SCTP) {
2194 // TODO(pthatcher): Do this in a more robust way by checking for
2195 // SCTP or DTLS.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +00002196 return !IsRtpPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002197 } else if (data_channel_type_ == DCT_RTP) {
2198 return BaseChannel::WantsPacket(rtcp, packet);
2199 }
2200 return false;
2201}
2202
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002203bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
2204 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002205 // It hasn't been set before, so set it now.
2206 if (data_channel_type_ == DCT_NONE) {
2207 data_channel_type_ = new_data_channel_type;
2208 return true;
2209 }
2210
2211 // It's been set before, but doesn't match. That's bad.
2212 if (data_channel_type_ != new_data_channel_type) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002213 std::ostringstream desc;
2214 desc << "Data channel type mismatch."
2215 << " Expected " << data_channel_type_
2216 << " Got " << new_data_channel_type;
2217 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002218 return false;
2219 }
2220
2221 // It's hasn't changed. Nothing to do.
2222 return true;
2223}
2224
2225bool DataChannel::SetDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002226 const DataContentDescription* content,
2227 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002228 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
2229 (content->protocol() == kMediaProtocolDtlsSctp));
2230 DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002231 return SetDataChannelType(data_channel_type, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002232}
2233
2234bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002235 ContentAction action,
2236 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002237 TRACE_EVENT0("webrtc", "DataChannel::SetLocalContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002238 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002239 LOG(LS_INFO) << "Setting local data description";
2240
2241 const DataContentDescription* data =
2242 static_cast<const DataContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002243 RTC_DCHECK(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002244 if (!data) {
2245 SafeSetError("Can't find data content in local description.", error_desc);
2246 return false;
2247 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002248
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002249 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250 return false;
2251 }
2252
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002253 if (data_channel_type_ == DCT_RTP) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002254 if (!SetRtpTransportParameters(content, action, CS_LOCAL, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002255 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002256 }
2257 }
2258
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002259 // FYI: We send the SCTP port number (not to be confused with the
2260 // underlying UDP port number) as a codec parameter. So even SCTP
2261 // data channels need codecs.
2262 DataRecvParameters recv_params = last_recv_params_;
2263 RtpParametersFromMediaDescription(data, &recv_params);
2264 if (!media_channel()->SetRecvParameters(recv_params)) {
2265 SafeSetError("Failed to set remote data description recv parameters.",
2266 error_desc);
2267 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002268 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002269 if (data_channel_type_ == DCT_RTP) {
2270 for (const DataCodec& codec : data->codecs()) {
2271 bundle_filter()->AddPayloadType(codec.id);
2272 }
2273 }
2274 last_recv_params_ = recv_params;
2275
2276 // TODO(pthatcher): Move local streams into DataSendParameters, and
2277 // only give it to the media channel once we have a remote
2278 // description too (without a remote description, we won't be able
2279 // to send them anyway).
2280 if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) {
2281 SafeSetError("Failed to set local data description streams.", error_desc);
2282 return false;
2283 }
2284
2285 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002286 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002287 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002288}
2289
2290bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002291 ContentAction action,
2292 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002293 TRACE_EVENT0("webrtc", "DataChannel::SetRemoteContent_w");
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002294 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002295
2296 const DataContentDescription* data =
2297 static_cast<const DataContentDescription*>(content);
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002298 RTC_DCHECK(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002299 if (!data) {
2300 SafeSetError("Can't find data content in remote description.", error_desc);
2301 return false;
2302 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002303
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002304 // If the remote data doesn't have codecs and isn't an update, it
2305 // must be empty, so ignore it.
2306 if (!data->has_codecs() && action != CA_UPDATE) {
2307 return true;
2308 }
2309
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002310 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002311 return false;
2312 }
2313
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002314 LOG(LS_INFO) << "Setting remote data description";
2315 if (data_channel_type_ == DCT_RTP &&
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002316 !SetRtpTransportParameters(content, action, CS_REMOTE, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002317 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002318 }
2319
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002320
2321 DataSendParameters send_params = last_send_params_;
2322 RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params);
2323 if (!media_channel()->SetSendParameters(send_params)) {
2324 SafeSetError("Failed to set remote data description send parameters.",
2325 error_desc);
2326 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002327 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002328 last_send_params_ = send_params;
2329
2330 // TODO(pthatcher): Move remote streams into DataRecvParameters,
2331 // and only give it to the media channel once we have a local
2332 // description too (without a local description, we won't be able to
2333 // recv them anyway).
2334 if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) {
2335 SafeSetError("Failed to set remote data description streams.",
2336 error_desc);
2337 return false;
2338 }
2339
2340 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002341 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002342 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002343}
2344
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002345void DataChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002346 // Render incoming data if we're the active call, and we have the local
2347 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002348 bool recv = IsReadyToReceiveMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002349 if (!media_channel()->SetReceive(recv)) {
2350 LOG(LS_ERROR) << "Failed to SetReceive on data channel";
2351 }
2352
2353 // Send outgoing data if we're the active call, we have the remote content,
2354 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002355 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002356 if (!media_channel()->SetSend(send)) {
2357 LOG(LS_ERROR) << "Failed to SetSend on data channel";
2358 }
2359
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002360 // Trigger SignalReadyToSendData asynchronously.
2361 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002362
2363 LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
2364}
2365
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002366void DataChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002367 switch (pmsg->message_id) {
2368 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002369 DataChannelReadyToSendMessageData* data =
2370 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002371 ready_to_send_data_ = data->data();
2372 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002373 delete data;
2374 break;
2375 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002376 case MSG_DATARECEIVED: {
2377 DataReceivedMessageData* data =
2378 static_cast<DataReceivedMessageData*>(pmsg->pdata);
2379 SignalDataReceived(this, data->params, data->payload);
2380 delete data;
2381 break;
2382 }
2383 case MSG_CHANNEL_ERROR: {
2384 const DataChannelErrorMessageData* data =
2385 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002386 delete data;
2387 break;
2388 }
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002389 case MSG_STREAMCLOSEDREMOTELY: {
Peter Boström0c4e06b2015-10-07 12:23:21 +02002390 rtc::TypedMessageData<uint32_t>* data =
2391 static_cast<rtc::TypedMessageData<uint32_t>*>(pmsg->pdata);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002392 SignalStreamClosedRemotely(data->data());
2393 delete data;
2394 break;
2395 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002396 default:
2397 BaseChannel::OnMessage(pmsg);
2398 break;
2399 }
2400}
2401
2402void DataChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002403 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002404 SignalConnectionMonitor(this, infos);
2405}
2406
2407void DataChannel::StartMediaMonitor(int cms) {
2408 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002409 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002410 media_monitor_->SignalUpdate.connect(
2411 this, &DataChannel::OnMediaMonitorUpdate);
2412 media_monitor_->Start(cms);
2413}
2414
2415void DataChannel::StopMediaMonitor() {
2416 if (media_monitor_) {
2417 media_monitor_->Stop();
2418 media_monitor_->SignalUpdate.disconnect(this);
2419 media_monitor_.reset();
2420 }
2421}
2422
2423void DataChannel::OnMediaMonitorUpdate(
2424 DataMediaChannel* media_channel, const DataMediaInfo& info) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07002425 RTC_DCHECK(media_channel == this->media_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002426 SignalMediaMonitor(this, info);
2427}
2428
2429void DataChannel::OnDataReceived(
2430 const ReceiveDataParams& params, const char* data, size_t len) {
2431 DataReceivedMessageData* msg = new DataReceivedMessageData(
2432 params, data, len);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002433 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002434}
2435
Peter Boström0c4e06b2015-10-07 12:23:21 +02002436void DataChannel::OnDataChannelError(uint32_t ssrc,
2437 DataMediaChannel::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002438 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2439 ssrc, err);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002440 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_CHANNEL_ERROR, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002441}
2442
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002443void DataChannel::OnDataChannelReadyToSend(bool writable) {
2444 // This is usded for congestion control to indicate that the stream is ready
2445 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2446 // that the transport channel is ready.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002447 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002448 new DataChannelReadyToSendMessageData(writable));
2449}
2450
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002451void DataChannel::GetSrtpCryptoSuites_n(std::vector<int>* crypto_suites) const {
jbauchcb560652016-08-04 05:20:32 -07002452 GetSupportedDataCryptoSuites(crypto_options(), crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002453}
2454
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002455bool DataChannel::ShouldSetupDtlsSrtp_n() const {
2456 return data_channel_type_ == DCT_RTP && BaseChannel::ShouldSetupDtlsSrtp_n();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002457}
2458
Peter Boström0c4e06b2015-10-07 12:23:21 +02002459void DataChannel::OnStreamClosedRemotely(uint32_t sid) {
2460 rtc::TypedMessageData<uint32_t>* message =
2461 new rtc::TypedMessageData<uint32_t>(sid);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002462 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_STREAMCLOSEDREMOTELY,
2463 message);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002464}
2465
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002466} // namespace cricket