blob: 1dc8e7f6bdaa84dfbe9728b14e17d27500ac39de [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
Tommif888bb52015-12-12 01:37:01 +010015#include "webrtc/audio/audio_sink.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000016#include "webrtc/base/bind.h"
17#include "webrtc/base/buffer.h"
18#include "webrtc/base/byteorder.h"
19#include "webrtc/base/common.h"
20#include "webrtc/base/dscp.h"
21#include "webrtc/base/logging.h"
Peter Boström6f28cf02015-12-07 23:17:15 +010022#include "webrtc/base/trace_event.h"
kjellandera96e2d72016-02-04 23:52:28 -080023#include "webrtc/media/base/constants.h"
24#include "webrtc/media/base/rtputils.h"
Peter Boström6f28cf02015-12-07 23:17:15 +010025#include "webrtc/p2p/base/transportchannel.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010026#include "webrtc/pc/channelmanager.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000027
28namespace cricket {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000029using rtc::Bind;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000030
deadbeef2d110be2016-01-13 12:00:26 -080031namespace {
32// See comment below for why we need to use a pointer to a scoped_ptr.
33bool SetRawAudioSink_w(VoiceMediaChannel* channel,
34 uint32_t ssrc,
35 rtc::scoped_ptr<webrtc::AudioSinkInterface>* sink) {
36 channel->SetRawAudioSink(ssrc, std::move(*sink));
37 return true;
38}
39} // namespace
40
henrike@webrtc.org28e20752013-07-10 00:45:36 +000041enum {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000042 MSG_EARLYMEDIATIMEOUT = 1,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000043 MSG_SCREENCASTWINDOWEVENT,
44 MSG_RTPPACKET,
45 MSG_RTCPPACKET,
46 MSG_CHANNEL_ERROR,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000047 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000048 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000049 MSG_FIRSTPACKETRECEIVED,
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +000050 MSG_STREAMCLOSEDREMOTELY,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051};
52
53// Value specified in RFC 5764.
54static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
55
56static const int kAgcMinus10db = -10;
57
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000058static void SafeSetError(const std::string& message, std::string* error_desc) {
59 if (error_desc) {
60 *error_desc = message;
61 }
62}
63
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000064struct PacketMessageData : public rtc::MessageData {
65 rtc::Buffer packet;
stefanc1aeaf02015-10-15 07:26:07 -070066 rtc::PacketOptions options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067};
68
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000069struct ScreencastEventMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020070 ScreencastEventMessageData(uint32_t s, rtc::WindowEvent we)
71 : ssrc(s), event(we) {}
72 uint32_t ssrc;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000073 rtc::WindowEvent event;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000074};
75
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000076struct VoiceChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020077 VoiceChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000078 VoiceMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020079 : ssrc(in_ssrc), error(in_error) {}
80 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000081 VoiceMediaChannel::Error error;
82};
83
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000084struct VideoChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020085 VideoChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086 VideoMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020087 : ssrc(in_ssrc), error(in_error) {}
88 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089 VideoMediaChannel::Error error;
90};
91
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000092struct DataChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020093 DataChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094 DataMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020095 : ssrc(in_ssrc), error(in_error) {}
96 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097 DataMediaChannel::Error error;
98};
99
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100static const char* PacketType(bool rtcp) {
101 return (!rtcp) ? "RTP" : "RTCP";
102}
103
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000104static bool ValidPacket(bool rtcp, const rtc::Buffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000105 // Check the packet size. We could check the header too if needed.
106 return (packet &&
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000107 packet->size() >= (!rtcp ? kMinRtpPacketLen : kMinRtcpPacketLen) &&
108 packet->size() <= kMaxRtpPacketLen);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000109}
110
111static bool IsReceiveContentDirection(MediaContentDirection direction) {
112 return direction == MD_SENDRECV || direction == MD_RECVONLY;
113}
114
115static bool IsSendContentDirection(MediaContentDirection direction) {
116 return direction == MD_SENDRECV || direction == MD_SENDONLY;
117}
118
119static const MediaContentDescription* GetContentDescription(
120 const ContentInfo* cinfo) {
121 if (cinfo == NULL)
122 return NULL;
123 return static_cast<const MediaContentDescription*>(cinfo->description);
124}
125
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700126template <class Codec>
127void RtpParametersFromMediaDescription(
128 const MediaContentDescriptionImpl<Codec>* desc,
129 RtpParameters<Codec>* params) {
130 // TODO(pthatcher): Remove this once we're sure no one will give us
131 // a description without codecs (currently a CA_UPDATE with just
132 // streams can).
133 if (desc->has_codecs()) {
134 params->codecs = desc->codecs();
135 }
136 // TODO(pthatcher): See if we really need
137 // rtp_header_extensions_set() and remove it if we don't.
138 if (desc->rtp_header_extensions_set()) {
139 params->extensions = desc->rtp_header_extensions();
140 }
deadbeef13871492015-12-09 12:37:51 -0800141 params->rtcp.reduced_size = desc->rtcp_reduced_size();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700142}
143
144template <class Codec, class Options>
145void RtpSendParametersFromMediaDescription(
146 const MediaContentDescriptionImpl<Codec>* desc,
147 RtpSendParameters<Codec, Options>* send_params) {
148 RtpParametersFromMediaDescription(desc, send_params);
149 send_params->max_bandwidth_bps = desc->bandwidth();
150}
151
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000152BaseChannel::BaseChannel(rtc::Thread* thread,
deadbeefcbecd352015-09-23 11:50:27 -0700153 MediaChannel* media_channel,
154 TransportController* transport_controller,
155 const std::string& content_name,
156 bool rtcp)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000157 : worker_thread_(thread),
deadbeefcbecd352015-09-23 11:50:27 -0700158 transport_controller_(transport_controller),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000159 media_channel_(media_channel),
160 content_name_(content_name),
deadbeefcbecd352015-09-23 11:50:27 -0700161 rtcp_transport_enabled_(rtcp),
162 transport_channel_(nullptr),
163 rtcp_transport_channel_(nullptr),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000164 enabled_(false),
165 writable_(false),
166 rtp_ready_to_send_(false),
167 rtcp_ready_to_send_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000168 was_ever_writable_(false),
169 local_content_direction_(MD_INACTIVE),
170 remote_content_direction_(MD_INACTIVE),
171 has_received_packet_(false),
172 dtls_keyed_(false),
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000173 secure_required_(false),
174 rtp_abs_sendtime_extn_id_(-1) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000175 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000176 LOG(LS_INFO) << "Created channel for " << content_name;
177}
178
179BaseChannel::~BaseChannel() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000180 ASSERT(worker_thread_ == rtc::Thread::Current());
wu@webrtc.org78187522013-10-07 23:32:02 +0000181 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000182 StopConnectionMonitor();
183 FlushRtcpMessages(); // Send any outstanding RTCP packets.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000184 worker_thread_->Clear(this); // eats any outstanding messages or packets
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000185 // We must destroy the media channel before the transport channel, otherwise
186 // the media channel may try to send on the dead transport channel. NULLing
187 // is not an effective strategy since the sends will come on another thread.
188 delete media_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700189 // Note that we don't just call set_transport_channel(nullptr) because that
190 // would call a pure virtual method which we can't do from a destructor.
191 if (transport_channel_) {
192 DisconnectFromTransportChannel(transport_channel_);
193 transport_controller_->DestroyTransportChannel_w(
194 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
195 }
196 if (rtcp_transport_channel_) {
197 DisconnectFromTransportChannel(rtcp_transport_channel_);
198 transport_controller_->DestroyTransportChannel_w(
199 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
200 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000201 LOG(LS_INFO) << "Destroyed channel";
202}
203
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000204bool BaseChannel::Init() {
deadbeefcbecd352015-09-23 11:50:27 -0700205 if (!SetTransport(content_name())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000206 return false;
207 }
208
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800209 if (!SetDtlsSrtpCryptoSuites(transport_channel(), false)) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000210 return false;
211 }
deadbeefcbecd352015-09-23 11:50:27 -0700212 if (rtcp_transport_enabled() &&
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800213 !SetDtlsSrtpCryptoSuites(rtcp_transport_channel(), true)) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000214 return false;
215 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000216
wu@webrtc.orgde305012013-10-31 15:40:38 +0000217 // Both RTP and RTCP channels are set, we can call SetInterface on
218 // media channel and it can set network options.
219 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000220 return true;
221}
222
wu@webrtc.org78187522013-10-07 23:32:02 +0000223void BaseChannel::Deinit() {
224 media_channel_->SetInterface(NULL);
225}
226
deadbeefcbecd352015-09-23 11:50:27 -0700227bool BaseChannel::SetTransport(const std::string& transport_name) {
228 return worker_thread_->Invoke<bool>(
229 Bind(&BaseChannel::SetTransport_w, this, transport_name));
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000230}
231
deadbeefcbecd352015-09-23 11:50:27 -0700232bool BaseChannel::SetTransport_w(const std::string& transport_name) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000233 ASSERT(worker_thread_ == rtc::Thread::Current());
234
deadbeefcbecd352015-09-23 11:50:27 -0700235 if (transport_name == transport_name_) {
236 // Nothing to do if transport name isn't changing
237 return true;
238 }
239
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800240 // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport
241 // changes and wait until the DTLS handshake is complete to set the newly
242 // negotiated parameters.
243 if (ShouldSetupDtlsSrtp()) {
guoweis46383312015-12-17 16:45:59 -0800244 // Set |writable_| to false such that UpdateWritableState_w can set up
245 // DTLS-SRTP when the writable_ becomes true again.
246 writable_ = false;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800247 srtp_filter_.ResetParams();
248 }
249
guoweis46383312015-12-17 16:45:59 -0800250 // TODO(guoweis): Remove this grossness when we remove non-muxed RTCP.
deadbeefcbecd352015-09-23 11:50:27 -0700251 if (rtcp_transport_enabled()) {
252 LOG(LS_INFO) << "Create RTCP TransportChannel for " << content_name()
253 << " on " << transport_name << " transport ";
guoweis46383312015-12-17 16:45:59 -0800254 set_rtcp_transport_channel(
255 transport_controller_->CreateTransportChannel_w(
256 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP),
257 false /* update_writablity */);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000258 if (!rtcp_transport_channel()) {
259 return false;
260 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000261 }
262
guoweis46383312015-12-17 16:45:59 -0800263 // We're not updating the writablity during the transition state.
264 set_transport_channel(transport_controller_->CreateTransportChannel_w(
265 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP));
266 if (!transport_channel()) {
267 return false;
268 }
269
270 // TODO(guoweis): Remove this grossness when we remove non-muxed RTCP.
271 if (rtcp_transport_enabled()) {
272 // We can only update the RTCP ready to send after set_transport_channel has
273 // handled channel writability.
274 SetReadyToSend(
275 true, rtcp_transport_channel() && rtcp_transport_channel()->writable());
276 }
deadbeefcbecd352015-09-23 11:50:27 -0700277 transport_name_ = transport_name;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000278 return true;
279}
280
281void BaseChannel::set_transport_channel(TransportChannel* new_tc) {
282 ASSERT(worker_thread_ == rtc::Thread::Current());
283
284 TransportChannel* old_tc = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700285 if (!old_tc && !new_tc) {
286 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000287 return;
288 }
deadbeefcbecd352015-09-23 11:50:27 -0700289 ASSERT(old_tc != new_tc);
290
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000291 if (old_tc) {
292 DisconnectFromTransportChannel(old_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700293 transport_controller_->DestroyTransportChannel_w(
294 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000295 }
296
297 transport_channel_ = new_tc;
298
299 if (new_tc) {
300 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700301 for (const auto& pair : socket_options_) {
302 new_tc->SetOption(pair.first, pair.second);
303 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000304 }
deadbeefcbecd352015-09-23 11:50:27 -0700305
306 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
307 // setting new channel
308 UpdateWritableState_w();
309 SetReadyToSend(false, new_tc && new_tc->writable());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000310}
311
guoweis46383312015-12-17 16:45:59 -0800312void BaseChannel::set_rtcp_transport_channel(TransportChannel* new_tc,
313 bool update_writablity) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000314 ASSERT(worker_thread_ == rtc::Thread::Current());
315
316 TransportChannel* old_tc = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700317 if (!old_tc && !new_tc) {
318 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000319 return;
320 }
deadbeefcbecd352015-09-23 11:50:27 -0700321 ASSERT(old_tc != new_tc);
322
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000323 if (old_tc) {
324 DisconnectFromTransportChannel(old_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700325 transport_controller_->DestroyTransportChannel_w(
326 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000327 }
328
329 rtcp_transport_channel_ = new_tc;
330
331 if (new_tc) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800332 RTC_CHECK(!(ShouldSetupDtlsSrtp() && srtp_filter_.IsActive()))
333 << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
334 << "should never happen.";
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000335 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700336 for (const auto& pair : rtcp_socket_options_) {
337 new_tc->SetOption(pair.first, pair.second);
338 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000339 }
deadbeefcbecd352015-09-23 11:50:27 -0700340
guoweis46383312015-12-17 16:45:59 -0800341 if (update_writablity) {
342 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
343 // setting new channel
344 UpdateWritableState_w();
345 SetReadyToSend(true, new_tc && new_tc->writable());
346 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000347}
348
349void BaseChannel::ConnectToTransportChannel(TransportChannel* tc) {
350 ASSERT(worker_thread_ == rtc::Thread::Current());
351
352 tc->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
353 tc->SignalReadPacket.connect(this, &BaseChannel::OnChannelRead);
354 tc->SignalReadyToSend.connect(this, &BaseChannel::OnReadyToSend);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800355 tc->SignalDtlsState.connect(this, &BaseChannel::OnDtlsState);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000356}
357
358void BaseChannel::DisconnectFromTransportChannel(TransportChannel* tc) {
359 ASSERT(worker_thread_ == rtc::Thread::Current());
360
361 tc->SignalWritableState.disconnect(this);
362 tc->SignalReadPacket.disconnect(this);
363 tc->SignalReadyToSend.disconnect(this);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800364 tc->SignalDtlsState.disconnect(this);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000365}
366
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000367bool BaseChannel::Enable(bool enable) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000368 worker_thread_->Invoke<void>(Bind(
369 enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
370 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000371 return true;
372}
373
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000374bool BaseChannel::AddRecvStream(const StreamParams& sp) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000375 return InvokeOnWorker(Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000376}
377
Peter Boström0c4e06b2015-10-07 12:23:21 +0200378bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000379 return InvokeOnWorker(Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000380}
381
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000382bool BaseChannel::AddSendStream(const StreamParams& sp) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000383 return InvokeOnWorker(
384 Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000385}
386
Peter Boström0c4e06b2015-10-07 12:23:21 +0200387bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000388 return InvokeOnWorker(
389 Bind(&MediaChannel::RemoveSendStream, media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000390}
391
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000392bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000393 ContentAction action,
394 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100395 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000396 return InvokeOnWorker(Bind(&BaseChannel::SetLocalContent_w,
397 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000398}
399
400bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000401 ContentAction action,
402 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100403 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000404 return InvokeOnWorker(Bind(&BaseChannel::SetRemoteContent_w,
405 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000406}
407
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000408void BaseChannel::StartConnectionMonitor(int cms) {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000409 // We pass in the BaseChannel instead of the transport_channel_
410 // because if the transport_channel_ changes, the ConnectionMonitor
411 // would be pointing to the wrong TransportChannel.
412 connection_monitor_.reset(new ConnectionMonitor(
413 this, worker_thread(), rtc::Thread::Current()));
414 connection_monitor_->SignalUpdate.connect(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000415 this, &BaseChannel::OnConnectionMonitorUpdate);
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000416 connection_monitor_->Start(cms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000417}
418
419void BaseChannel::StopConnectionMonitor() {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000420 if (connection_monitor_) {
421 connection_monitor_->Stop();
422 connection_monitor_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000423 }
424}
425
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000426bool BaseChannel::GetConnectionStats(ConnectionInfos* infos) {
427 ASSERT(worker_thread_ == rtc::Thread::Current());
428 return transport_channel_->GetStats(infos);
429}
430
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000431bool BaseChannel::IsReadyToReceive() const {
432 // Receive data if we are enabled and have local content,
433 return enabled() && IsReceiveContentDirection(local_content_direction_);
434}
435
436bool BaseChannel::IsReadyToSend() const {
437 // Send outgoing data if we are enabled, have local and remote content,
438 // and we have had some form of connectivity.
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800439 return enabled() && IsReceiveContentDirection(remote_content_direction_) &&
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440 IsSendContentDirection(local_content_direction_) &&
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800441 was_ever_writable() &&
442 (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000443}
444
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000445bool BaseChannel::SendPacket(rtc::Buffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700446 const rtc::PacketOptions& options) {
447 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000448}
449
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000450bool BaseChannel::SendRtcp(rtc::Buffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700451 const rtc::PacketOptions& options) {
452 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000453}
454
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000455int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000456 int value) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000457 TransportChannel* channel = NULL;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000458 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000459 case ST_RTP:
460 channel = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700461 socket_options_.push_back(
462 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000463 break;
464 case ST_RTCP:
465 channel = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700466 rtcp_socket_options_.push_back(
467 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000468 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000469 }
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000470 return channel ? channel->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000471}
472
473void BaseChannel::OnWritableState(TransportChannel* channel) {
474 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
deadbeefcbecd352015-09-23 11:50:27 -0700475 UpdateWritableState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000476}
477
478void BaseChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000479 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000480 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000481 int flags) {
Peter Boström6f28cf02015-12-07 23:17:15 +0100482 TRACE_EVENT0("webrtc", "BaseChannel::OnChannelRead");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000483 // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000484 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000485
486 // When using RTCP multiplexing we might get RTCP packets on the RTP
487 // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
488 bool rtcp = PacketIsRtcp(channel, data, len);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000489 rtc::Buffer packet(data, len);
wu@webrtc.orga9890802013-12-13 00:21:03 +0000490 HandlePacket(rtcp, &packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000491}
492
493void BaseChannel::OnReadyToSend(TransportChannel* channel) {
deadbeefcbecd352015-09-23 11:50:27 -0700494 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
495 SetReadyToSend(channel == rtcp_transport_channel_, true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000496}
497
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800498void BaseChannel::OnDtlsState(TransportChannel* channel,
499 DtlsTransportState state) {
500 if (!ShouldSetupDtlsSrtp()) {
501 return;
502 }
503
504 // Reset the srtp filter if it's not the CONNECTED state. For the CONNECTED
505 // state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to
506 // cover other scenarios like the whole channel is writable (not just this
507 // TransportChannel) or when TransportChannel is attached after DTLS is
508 // negotiated.
509 if (state != DTLS_TRANSPORT_CONNECTED) {
510 srtp_filter_.ResetParams();
511 }
512}
513
deadbeefcbecd352015-09-23 11:50:27 -0700514void BaseChannel::SetReadyToSend(bool rtcp, bool ready) {
515 if (rtcp) {
516 rtcp_ready_to_send_ = ready;
517 } else {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000518 rtp_ready_to_send_ = ready;
519 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000520
deadbeefcbecd352015-09-23 11:50:27 -0700521 if (rtp_ready_to_send_ &&
522 // In the case of rtcp mux |rtcp_transport_channel_| will be null.
523 (rtcp_ready_to_send_ || !rtcp_transport_channel_)) {
torbjornga81a42f2015-09-23 02:16:58 -0700524 // Notify the MediaChannel when both rtp and rtcp channel can send.
525 media_channel_->OnReadyToSend(true);
deadbeefcbecd352015-09-23 11:50:27 -0700526 } else {
527 // Notify the MediaChannel when either rtp or rtcp channel can't send.
528 media_channel_->OnReadyToSend(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000529 }
530}
531
532bool BaseChannel::PacketIsRtcp(const TransportChannel* channel,
533 const char* data, size_t len) {
534 return (channel == rtcp_transport_channel_ ||
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000535 rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000536}
537
stefanc1aeaf02015-10-15 07:26:07 -0700538bool BaseChannel::SendPacket(bool rtcp,
539 rtc::Buffer* packet,
540 const rtc::PacketOptions& options) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000541 // SendPacket gets called from MediaEngine, typically on an encoder thread.
542 // If the thread is not our worker thread, we will post to our worker
543 // so that the real work happens on our worker. This avoids us having to
544 // synchronize access to all the pieces of the send path, including
545 // SRTP and the inner workings of the transport channels.
546 // The only downside is that we can't return a proper failure code if
547 // needed. Since UDP is unreliable anyway, this should be a non-issue.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000548 if (rtc::Thread::Current() != worker_thread_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000549 // Avoid a copy by transferring the ownership of the packet data.
550 int message_id = (!rtcp) ? MSG_RTPPACKET : MSG_RTCPPACKET;
551 PacketMessageData* data = new PacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800552 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700553 data->options = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000554 worker_thread_->Post(this, message_id, data);
555 return true;
556 }
557
558 // Now that we are on the correct thread, ensure we have a place to send this
559 // packet before doing anything. (We might get RTCP packets that we don't
560 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
561 // transport.
562 TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
563 transport_channel_ : rtcp_transport_channel_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000564 if (!channel || !channel->writable()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000565 return false;
566 }
567
568 // Protect ourselves against crazy data.
569 if (!ValidPacket(rtcp, packet)) {
570 LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000571 << PacketType(rtcp)
572 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000573 return false;
574 }
575
stefanc1aeaf02015-10-15 07:26:07 -0700576 rtc::PacketOptions updated_options;
577 updated_options = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000578 // Protect if needed.
579 if (srtp_filter_.IsActive()) {
580 bool res;
Karl Wibergc56ac1e2015-05-04 14:54:55 +0200581 uint8_t* data = packet->data();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000582 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000583 if (!rtcp) {
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000584 // If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
585 // inside libsrtp for a RTP packet. A external HMAC module will be writing
586 // a fake HMAC value. This is ONLY done for a RTP packet.
587 // Socket layer will update rtp sendtime extension header if present in
588 // packet with current time before updating the HMAC.
589#if !defined(ENABLE_EXTERNAL_AUTH)
590 res = srtp_filter_.ProtectRtp(
591 data, len, static_cast<int>(packet->capacity()), &len);
592#else
stefanc1aeaf02015-10-15 07:26:07 -0700593 updated_options.packet_time_params.rtp_sendtime_extension_id =
henrike@webrtc.org05376342014-03-10 15:53:12 +0000594 rtp_abs_sendtime_extn_id_;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000595 res = srtp_filter_.ProtectRtp(
596 data, len, static_cast<int>(packet->capacity()), &len,
stefanc1aeaf02015-10-15 07:26:07 -0700597 &updated_options.packet_time_params.srtp_packet_index);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000598 // If protection succeeds, let's get auth params from srtp.
599 if (res) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200600 uint8_t* auth_key = NULL;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000601 int key_len;
602 res = srtp_filter_.GetRtpAuthParams(
stefanc1aeaf02015-10-15 07:26:07 -0700603 &auth_key, &key_len,
604 &updated_options.packet_time_params.srtp_auth_tag_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000605 if (res) {
stefanc1aeaf02015-10-15 07:26:07 -0700606 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
607 updated_options.packet_time_params.srtp_auth_key.assign(
608 auth_key, auth_key + key_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000609 }
610 }
611#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000612 if (!res) {
613 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200614 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000615 GetRtpSeqNum(data, len, &seq_num);
616 GetRtpSsrc(data, len, &ssrc);
617 LOG(LS_ERROR) << "Failed to protect " << content_name_
618 << " RTP packet: size=" << len
619 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
620 return false;
621 }
622 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000623 res = srtp_filter_.ProtectRtcp(data, len,
624 static_cast<int>(packet->capacity()),
625 &len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000626 if (!res) {
627 int type = -1;
628 GetRtcpType(data, len, &type);
629 LOG(LS_ERROR) << "Failed to protect " << content_name_
630 << " RTCP packet: size=" << len << ", type=" << type;
631 return false;
632 }
633 }
634
635 // Update the length of the packet now that we've added the auth tag.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000636 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000637 } else if (secure_required_) {
638 // This is a double check for something that supposedly can't happen.
639 LOG(LS_ERROR) << "Can't send outgoing " << PacketType(rtcp)
640 << " packet when SRTP is inactive and crypto is required";
641
642 ASSERT(false);
643 return false;
644 }
645
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000646 // Bon voyage.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000647 int ret =
stefanc1aeaf02015-10-15 07:26:07 -0700648 channel->SendPacket(packet->data<char>(), packet->size(), updated_options,
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000649 (secure() && secure_dtls()) ? PF_SRTP_BYPASS : 0);
650 if (ret != static_cast<int>(packet->size())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000651 if (channel->GetError() == EWOULDBLOCK) {
652 LOG(LS_WARNING) << "Got EWOULDBLOCK from socket.";
deadbeefcbecd352015-09-23 11:50:27 -0700653 SetReadyToSend(rtcp, false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000654 }
655 return false;
656 }
657 return true;
658}
659
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000660bool BaseChannel::WantsPacket(bool rtcp, rtc::Buffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000661 // Protect ourselves against crazy data.
662 if (!ValidPacket(rtcp, packet)) {
663 LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000664 << PacketType(rtcp)
665 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666 return false;
667 }
pbos482b12e2015-11-16 10:19:58 -0800668 if (rtcp) {
669 // Permit all (seemingly valid) RTCP packets.
670 return true;
671 }
672 // Check whether we handle this payload.
673 return bundle_filter_.DemuxPacket(packet->data<uint8_t>(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000674}
675
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000676void BaseChannel::HandlePacket(bool rtcp, rtc::Buffer* packet,
677 const rtc::PacketTime& packet_time) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000678 if (!WantsPacket(rtcp, packet)) {
679 return;
680 }
681
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000682 // We are only interested in the first rtp packet because that
683 // indicates the media has started flowing.
684 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000685 has_received_packet_ = true;
686 signaling_thread()->Post(this, MSG_FIRSTPACKETRECEIVED);
687 }
688
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000689 // Unprotect the packet, if needed.
690 if (srtp_filter_.IsActive()) {
Karl Wiberg94784372015-04-20 14:03:07 +0200691 char* data = packet->data<char>();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000692 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000693 bool res;
694 if (!rtcp) {
695 res = srtp_filter_.UnprotectRtp(data, len, &len);
696 if (!res) {
697 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200698 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000699 GetRtpSeqNum(data, len, &seq_num);
700 GetRtpSsrc(data, len, &ssrc);
701 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
702 << " RTP packet: size=" << len
703 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
704 return;
705 }
706 } else {
707 res = srtp_filter_.UnprotectRtcp(data, len, &len);
708 if (!res) {
709 int type = -1;
710 GetRtcpType(data, len, &type);
711 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
712 << " RTCP packet: size=" << len << ", type=" << type;
713 return;
714 }
715 }
716
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000717 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000718 } else if (secure_required_) {
719 // Our session description indicates that SRTP is required, but we got a
720 // packet before our SRTP filter is active. This means either that
721 // a) we got SRTP packets before we received the SDES keys, in which case
722 // we can't decrypt it anyway, or
723 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
724 // channels, so we haven't yet extracted keys, even if DTLS did complete
725 // on the channel that the packets are being sent on. It's really good
726 // practice to wait for both RTP and RTCP to be good to go before sending
727 // media, to prevent weird failure modes, so it's fine for us to just eat
728 // packets here. This is all sidestepped if RTCP mux is used anyway.
729 LOG(LS_WARNING) << "Can't process incoming " << PacketType(rtcp)
730 << " packet when SRTP is inactive and crypto is required";
731 return;
732 }
733
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000734 // Push it down to the media channel.
735 if (!rtcp) {
wu@webrtc.orga9890802013-12-13 00:21:03 +0000736 media_channel_->OnPacketReceived(packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000737 } else {
wu@webrtc.orga9890802013-12-13 00:21:03 +0000738 media_channel_->OnRtcpReceived(packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000739 }
740}
741
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000742bool BaseChannel::PushdownLocalDescription(
743 const SessionDescription* local_desc, ContentAction action,
744 std::string* error_desc) {
745 const ContentInfo* content_info = GetFirstContent(local_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000746 const MediaContentDescription* content_desc =
747 GetContentDescription(content_info);
748 if (content_desc && content_info && !content_info->rejected &&
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000749 !SetLocalContent(content_desc, action, error_desc)) {
750 LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
751 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000752 }
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000753 return true;
754}
755
756bool BaseChannel::PushdownRemoteDescription(
757 const SessionDescription* remote_desc, ContentAction action,
758 std::string* error_desc) {
759 const ContentInfo* content_info = GetFirstContent(remote_desc);
760 const MediaContentDescription* content_desc =
761 GetContentDescription(content_info);
762 if (content_desc && content_info && !content_info->rejected &&
763 !SetRemoteContent(content_desc, action, error_desc)) {
764 LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
765 return false;
766 }
767 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000768}
769
770void BaseChannel::EnableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000771 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000772 if (enabled_)
773 return;
774
775 LOG(LS_INFO) << "Channel enabled";
776 enabled_ = true;
777 ChangeState();
778}
779
780void BaseChannel::DisableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000781 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000782 if (!enabled_)
783 return;
784
785 LOG(LS_INFO) << "Channel disabled";
786 enabled_ = false;
787 ChangeState();
788}
789
deadbeefcbecd352015-09-23 11:50:27 -0700790void BaseChannel::UpdateWritableState_w() {
791 if (transport_channel_ && transport_channel_->writable() &&
792 (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
793 ChannelWritable_w();
794 } else {
795 ChannelNotWritable_w();
796 }
797}
798
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000799void BaseChannel::ChannelWritable_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000800 ASSERT(worker_thread_ == rtc::Thread::Current());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800801 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000802 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800803 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000804
deadbeefcbecd352015-09-23 11:50:27 -0700805 LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000806 << (was_ever_writable_ ? "" : " for the first time");
807
808 std::vector<ConnectionInfo> infos;
809 transport_channel_->GetStats(&infos);
810 for (std::vector<ConnectionInfo>::const_iterator it = infos.begin();
811 it != infos.end(); ++it) {
812 if (it->best_connection) {
813 LOG(LS_INFO) << "Using " << it->local_candidate.ToSensitiveString()
814 << "->" << it->remote_candidate.ToSensitiveString();
815 break;
816 }
817 }
818
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000819 was_ever_writable_ = true;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800820 MaybeSetupDtlsSrtp_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000821 writable_ = true;
822 ChangeState();
823}
824
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000825void BaseChannel::SignalDtlsSetupFailure_w(bool rtcp) {
826 ASSERT(worker_thread() == rtc::Thread::Current());
827 signaling_thread()->Invoke<void>(Bind(
828 &BaseChannel::SignalDtlsSetupFailure_s, this, rtcp));
829}
830
831void BaseChannel::SignalDtlsSetupFailure_s(bool rtcp) {
832 ASSERT(signaling_thread() == rtc::Thread::Current());
833 SignalDtlsSetupFailure(this, rtcp);
834}
835
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800836bool BaseChannel::SetDtlsSrtpCryptoSuites(TransportChannel* tc, bool rtcp) {
837 std::vector<int> crypto_suites;
838 // We always use the default SRTP crypto suites for RTCP, but we may use
839 // different crypto suites for RTP depending on the media type.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000840 if (!rtcp) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800841 GetSrtpCryptoSuites(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000842 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800843 GetDefaultSrtpCryptoSuites(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000844 }
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800845 return tc->SetSrtpCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000846}
847
848bool BaseChannel::ShouldSetupDtlsSrtp() const {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800849 // Since DTLS is applied to all channels, checking RTP should be enough.
850 return transport_channel_ && transport_channel_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000851}
852
853// This function returns true if either DTLS-SRTP is not in use
854// *or* DTLS-SRTP is successfully set up.
855bool BaseChannel::SetupDtlsSrtp(bool rtcp_channel) {
856 bool ret = false;
857
deadbeefcbecd352015-09-23 11:50:27 -0700858 TransportChannel* channel =
859 rtcp_channel ? rtcp_transport_channel_ : transport_channel_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000860
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800861 RTC_DCHECK(channel->IsDtlsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000862
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800863 int selected_crypto_suite;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000864
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800865 if (!channel->GetSrtpCryptoSuite(&selected_crypto_suite)) {
866 LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000867 return false;
868 }
869
870 LOG(LS_INFO) << "Installing keys from DTLS-SRTP on "
871 << content_name() << " "
872 << PacketType(rtcp_channel);
873
874 // OK, we're now doing DTLS (RFC 5764)
875 std::vector<unsigned char> dtls_buffer(SRTP_MASTER_KEY_KEY_LEN * 2 +
876 SRTP_MASTER_KEY_SALT_LEN * 2);
877
878 // RFC 5705 exporter using the RFC 5764 parameters
879 if (!channel->ExportKeyingMaterial(
880 kDtlsSrtpExporterLabel,
881 NULL, 0, false,
882 &dtls_buffer[0], dtls_buffer.size())) {
883 LOG(LS_WARNING) << "DTLS-SRTP key export failed";
884 ASSERT(false); // This should never happen
885 return false;
886 }
887
888 // Sync up the keys with the DTLS-SRTP interface
889 std::vector<unsigned char> client_write_key(SRTP_MASTER_KEY_KEY_LEN +
890 SRTP_MASTER_KEY_SALT_LEN);
891 std::vector<unsigned char> server_write_key(SRTP_MASTER_KEY_KEY_LEN +
892 SRTP_MASTER_KEY_SALT_LEN);
893 size_t offset = 0;
894 memcpy(&client_write_key[0], &dtls_buffer[offset],
895 SRTP_MASTER_KEY_KEY_LEN);
896 offset += SRTP_MASTER_KEY_KEY_LEN;
897 memcpy(&server_write_key[0], &dtls_buffer[offset],
898 SRTP_MASTER_KEY_KEY_LEN);
899 offset += SRTP_MASTER_KEY_KEY_LEN;
900 memcpy(&client_write_key[SRTP_MASTER_KEY_KEY_LEN],
901 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
902 offset += SRTP_MASTER_KEY_SALT_LEN;
903 memcpy(&server_write_key[SRTP_MASTER_KEY_KEY_LEN],
904 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
905
906 std::vector<unsigned char> *send_key, *recv_key;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000907 rtc::SSLRole role;
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000908 if (!channel->GetSslRole(&role)) {
909 LOG(LS_WARNING) << "GetSslRole failed";
910 return false;
911 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000912
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000913 if (role == rtc::SSL_SERVER) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000914 send_key = &server_write_key;
915 recv_key = &client_write_key;
916 } else {
917 send_key = &client_write_key;
918 recv_key = &server_write_key;
919 }
920
921 if (rtcp_channel) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800922 ret = srtp_filter_.SetRtcpParams(selected_crypto_suite, &(*send_key)[0],
923 static_cast<int>(send_key->size()),
924 selected_crypto_suite, &(*recv_key)[0],
925 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800927 ret = srtp_filter_.SetRtpParams(selected_crypto_suite, &(*send_key)[0],
928 static_cast<int>(send_key->size()),
929 selected_crypto_suite, &(*recv_key)[0],
930 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000931 }
932
933 if (!ret)
934 LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
935 else
936 dtls_keyed_ = true;
937
938 return ret;
939}
940
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800941void BaseChannel::MaybeSetupDtlsSrtp_w() {
942 if (srtp_filter_.IsActive()) {
943 return;
944 }
945
946 if (!ShouldSetupDtlsSrtp()) {
947 return;
948 }
949
950 if (!SetupDtlsSrtp(false)) {
951 SignalDtlsSetupFailure_w(false);
952 return;
953 }
954
955 if (rtcp_transport_channel_) {
956 if (!SetupDtlsSrtp(true)) {
957 SignalDtlsSetupFailure_w(true);
958 return;
959 }
960 }
961}
962
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000963void BaseChannel::ChannelNotWritable_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000964 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000965 if (!writable_)
966 return;
967
deadbeefcbecd352015-09-23 11:50:27 -0700968 LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000969 writable_ = false;
970 ChangeState();
971}
972
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700973bool BaseChannel::SetRtpTransportParameters_w(
974 const MediaContentDescription* content,
975 ContentAction action,
976 ContentSource src,
977 std::string* error_desc) {
978 if (action == CA_UPDATE) {
979 // These parameters never get changed by a CA_UDPATE.
980 return true;
981 }
982
983 // Cache secure_required_ for belt and suspenders check on SendPacket
984 if (src == CS_LOCAL) {
985 set_secure_required(content->crypto_required() != CT_NONE);
986 }
987
988 if (!SetSrtp_w(content->cryptos(), action, src, error_desc)) {
989 return false;
990 }
991
992 if (!SetRtcpMux_w(content->rtcp_mux(), action, src, error_desc)) {
993 return false;
994 }
995
996 return true;
997}
998
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000999// |dtls| will be set to true if DTLS is active for transport channel and
1000// crypto is empty.
1001bool BaseChannel::CheckSrtpConfig(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001002 bool* dtls,
1003 std::string* error_desc) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001004 *dtls = transport_channel_->IsDtlsActive();
1005 if (*dtls && !cryptos.empty()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001006 SafeSetError("Cryptos must be empty when DTLS is active.",
1007 error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001008 return false;
1009 }
1010 return true;
1011}
1012
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001013bool BaseChannel::SetSrtp_w(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001014 ContentAction action,
1015 ContentSource src,
1016 std::string* error_desc) {
1017 if (action == CA_UPDATE) {
1018 // no crypto params.
1019 return true;
1020 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001021 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001022 bool dtls = false;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001023 ret = CheckSrtpConfig(cryptos, &dtls, error_desc);
1024 if (!ret) {
1025 return false;
1026 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001027 switch (action) {
1028 case CA_OFFER:
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001029 // If DTLS is already active on the channel, we could be renegotiating
1030 // here. We don't update the srtp filter.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001031 if (!dtls) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001032 ret = srtp_filter_.SetOffer(cryptos, src);
1033 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001034 break;
1035 case CA_PRANSWER:
1036 // If we're doing DTLS-SRTP, we don't want to update the filter
1037 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001038 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001039 ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
1040 }
1041 break;
1042 case CA_ANSWER:
1043 // If we're doing DTLS-SRTP, we don't want to update the filter
1044 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001045 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001046 ret = srtp_filter_.SetAnswer(cryptos, src);
1047 }
1048 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001049 default:
1050 break;
1051 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001052 if (!ret) {
1053 SafeSetError("Failed to setup SRTP filter.", error_desc);
1054 return false;
1055 }
1056 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001057}
1058
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001059void BaseChannel::ActivateRtcpMux() {
1060 worker_thread_->Invoke<void>(Bind(
1061 &BaseChannel::ActivateRtcpMux_w, this));
1062}
1063
1064void BaseChannel::ActivateRtcpMux_w() {
1065 if (!rtcp_mux_filter_.IsActive()) {
1066 rtcp_mux_filter_.SetActive();
guoweis46383312015-12-17 16:45:59 -08001067 set_rtcp_transport_channel(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001068 rtcp_transport_enabled_ = false;
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001069 }
1070}
1071
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001072bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001073 ContentSource src,
1074 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001075 bool ret = false;
1076 switch (action) {
1077 case CA_OFFER:
1078 ret = rtcp_mux_filter_.SetOffer(enable, src);
1079 break;
1080 case CA_PRANSWER:
1081 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
1082 break;
1083 case CA_ANSWER:
1084 ret = rtcp_mux_filter_.SetAnswer(enable, src);
1085 if (ret && rtcp_mux_filter_.IsActive()) {
1086 // We activated RTCP mux, close down the RTCP transport.
deadbeefcbecd352015-09-23 11:50:27 -07001087 LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
1088 << " by destroying RTCP transport channel for "
1089 << transport_name();
guoweis46383312015-12-17 16:45:59 -08001090 set_rtcp_transport_channel(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001091 rtcp_transport_enabled_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001092 }
1093 break;
1094 case CA_UPDATE:
1095 // No RTCP mux info.
1096 ret = true;
Henrik Kjellander7c027b62015-04-22 13:21:30 +02001097 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001098 default:
1099 break;
1100 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001101 if (!ret) {
1102 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
1103 return false;
1104 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001105 // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
1106 // CA_ANSWER, but we only want to tear down the RTCP transport channel if we
1107 // received a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001108 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001109 // If the RTP transport is already writable, then so are we.
1110 if (transport_channel_->writable()) {
1111 ChannelWritable_w();
1112 }
1113 }
1114
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001115 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001116}
1117
1118bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001119 ASSERT(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -08001120 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001121}
1122
Peter Boström0c4e06b2015-10-07 12:23:21 +02001123bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001124 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001125 return media_channel()->RemoveRecvStream(ssrc);
1126}
1127
1128bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001129 ContentAction action,
1130 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001131 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1132 action == CA_PRANSWER || action == CA_UPDATE))
1133 return false;
1134
1135 // If this is an update, streams only contain streams that have changed.
1136 if (action == CA_UPDATE) {
1137 for (StreamParamsVec::const_iterator it = streams.begin();
1138 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001139 const StreamParams* existing_stream =
1140 GetStreamByIds(local_streams_, it->groupid, it->id);
1141 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001142 if (media_channel()->AddSendStream(*it)) {
1143 local_streams_.push_back(*it);
1144 LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
1145 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001146 std::ostringstream desc;
1147 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1148 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001149 return false;
1150 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001151 } else if (existing_stream && !it->has_ssrcs()) {
1152 if (!media_channel()->RemoveSendStream(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001153 std::ostringstream desc;
1154 desc << "Failed to remove send stream with ssrc "
1155 << it->first_ssrc() << ".";
1156 SafeSetError(desc.str(), error_desc);
1157 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001158 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001159 RemoveStreamBySsrc(&local_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001160 } else {
1161 LOG(LS_WARNING) << "Ignore unsupported stream update";
1162 }
1163 }
1164 return true;
1165 }
1166 // Else streams are all the streams we want to send.
1167
1168 // Check for streams that have been removed.
1169 bool ret = true;
1170 for (StreamParamsVec::const_iterator it = local_streams_.begin();
1171 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001172 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001173 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001174 std::ostringstream desc;
1175 desc << "Failed to remove send stream with ssrc "
1176 << it->first_ssrc() << ".";
1177 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001178 ret = false;
1179 }
1180 }
1181 }
1182 // Check for new streams.
1183 for (StreamParamsVec::const_iterator it = streams.begin();
1184 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001185 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001186 if (media_channel()->AddSendStream(*it)) {
stefanc1aeaf02015-10-15 07:26:07 -07001187 LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001188 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001189 std::ostringstream desc;
1190 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1191 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001192 ret = false;
1193 }
1194 }
1195 }
1196 local_streams_ = streams;
1197 return ret;
1198}
1199
1200bool BaseChannel::UpdateRemoteStreams_w(
1201 const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001202 ContentAction action,
1203 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001204 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1205 action == CA_PRANSWER || action == CA_UPDATE))
1206 return false;
1207
1208 // If this is an update, streams only contain streams that have changed.
1209 if (action == CA_UPDATE) {
1210 for (StreamParamsVec::const_iterator it = streams.begin();
1211 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001212 const StreamParams* existing_stream =
1213 GetStreamByIds(remote_streams_, it->groupid, it->id);
1214 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001215 if (AddRecvStream_w(*it)) {
1216 remote_streams_.push_back(*it);
1217 LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
1218 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001219 std::ostringstream desc;
1220 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1221 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001222 return false;
1223 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001224 } else if (existing_stream && !it->has_ssrcs()) {
1225 if (!RemoveRecvStream_w(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001226 std::ostringstream desc;
1227 desc << "Failed to remove remote stream with ssrc "
1228 << it->first_ssrc() << ".";
1229 SafeSetError(desc.str(), error_desc);
1230 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001231 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001232 RemoveStreamBySsrc(&remote_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001233 } else {
1234 LOG(LS_WARNING) << "Ignore unsupported stream update."
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001235 << " Stream exists? " << (existing_stream != nullptr)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001236 << " new stream = " << it->ToString();
1237 }
1238 }
1239 return true;
1240 }
1241 // Else streams are all the streams we want to receive.
1242
1243 // Check for streams that have been removed.
1244 bool ret = true;
1245 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
1246 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001247 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001248 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001249 std::ostringstream desc;
1250 desc << "Failed to remove remote stream with ssrc "
1251 << it->first_ssrc() << ".";
1252 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001253 ret = false;
1254 }
1255 }
1256 }
1257 // Check for new streams.
1258 for (StreamParamsVec::const_iterator it = streams.begin();
1259 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001260 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001261 if (AddRecvStream_w(*it)) {
1262 LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
1263 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001264 std::ostringstream desc;
1265 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1266 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001267 ret = false;
1268 }
1269 }
1270 }
1271 remote_streams_ = streams;
1272 return ret;
1273}
1274
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001275void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension(
1276 const std::vector<RtpHeaderExtension>& extensions) {
1277 const RtpHeaderExtension* send_time_extension =
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001278 FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001279 rtp_abs_sendtime_extn_id_ =
1280 send_time_extension ? send_time_extension->id : -1;
1281}
1282
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001283void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001284 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001285 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001286 case MSG_RTPPACKET:
1287 case MSG_RTCPPACKET: {
1288 PacketMessageData* data = static_cast<PacketMessageData*>(pmsg->pdata);
stefanc1aeaf02015-10-15 07:26:07 -07001289 SendPacket(pmsg->message_id == MSG_RTCPPACKET, &data->packet,
1290 data->options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001291 delete data; // because it is Posted
1292 break;
1293 }
1294 case MSG_FIRSTPACKETRECEIVED: {
1295 SignalFirstPacketReceived(this);
1296 break;
1297 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001298 }
1299}
1300
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001301void BaseChannel::FlushRtcpMessages() {
1302 // Flush all remaining RTCP messages. This should only be called in
1303 // destructor.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001304 ASSERT(rtc::Thread::Current() == worker_thread_);
1305 rtc::MessageList rtcp_messages;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001306 worker_thread_->Clear(this, MSG_RTCPPACKET, &rtcp_messages);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001307 for (rtc::MessageList::iterator it = rtcp_messages.begin();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001308 it != rtcp_messages.end(); ++it) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001309 worker_thread_->Send(this, MSG_RTCPPACKET, it->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001310 }
1311}
1312
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001313VoiceChannel::VoiceChannel(rtc::Thread* thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001314 MediaEngineInterface* media_engine,
1315 VoiceMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001316 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001317 const std::string& content_name,
1318 bool rtcp)
deadbeefcbecd352015-09-23 11:50:27 -07001319 : BaseChannel(thread,
1320 media_channel,
1321 transport_controller,
1322 content_name,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001323 rtcp),
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001324 media_engine_(media_engine),
deadbeefcbecd352015-09-23 11:50:27 -07001325 received_media_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001326
1327VoiceChannel::~VoiceChannel() {
1328 StopAudioMonitor();
1329 StopMediaMonitor();
1330 // this can't be done in the base class, since it calls a virtual
1331 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001332 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001333}
1334
1335bool VoiceChannel::Init() {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +00001336 if (!BaseChannel::Init()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001337 return false;
1338 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001339 return true;
1340}
1341
Peter Boström0c4e06b2015-10-07 12:23:21 +02001342bool VoiceChannel::SetAudioSend(uint32_t ssrc,
solenbergdfc8f4f2015-10-01 02:31:10 -07001343 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001344 const AudioOptions* options,
1345 AudioRenderer* renderer) {
deadbeefcbecd352015-09-23 11:50:27 -07001346 return InvokeOnWorker(Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
solenbergdfc8f4f2015-10-01 02:31:10 -07001347 ssrc, enable, options, renderer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001348}
1349
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001350// TODO(juberti): Handle early media the right way. We should get an explicit
1351// ringing message telling us to start playing local ringback, which we cancel
1352// if any early media actually arrives. For now, we do the opposite, which is
1353// to wait 1 second for early media, and start playing local ringback if none
1354// arrives.
1355void VoiceChannel::SetEarlyMedia(bool enable) {
1356 if (enable) {
1357 // Start the early media timeout
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001358 worker_thread()->PostDelayed(kEarlyMediaTimeout, this,
1359 MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001360 } else {
1361 // Stop the timeout if currently going.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001362 worker_thread()->Clear(this, MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001363 }
1364}
1365
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001366bool VoiceChannel::CanInsertDtmf() {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001367 return InvokeOnWorker(Bind(&VoiceMediaChannel::CanInsertDtmf,
1368 media_channel()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001369}
1370
Peter Boström0c4e06b2015-10-07 12:23:21 +02001371bool VoiceChannel::InsertDtmf(uint32_t ssrc,
1372 int event_code,
solenberg1d63dd02015-12-02 12:35:09 -08001373 int duration) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001374 return InvokeOnWorker(Bind(&VoiceChannel::InsertDtmf_w, this,
solenberg1d63dd02015-12-02 12:35:09 -08001375 ssrc, event_code, duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001376}
1377
solenberg4bac9c52015-10-09 02:32:53 -07001378bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) {
1379 return InvokeOnWorker(Bind(&VoiceMediaChannel::SetOutputVolume,
1380 media_channel(), ssrc, volume));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001381}
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001382
Tommif888bb52015-12-12 01:37:01 +01001383void VoiceChannel::SetRawAudioSink(
1384 uint32_t ssrc,
deadbeef2d110be2016-01-13 12:00:26 -08001385 rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) {
1386 // We need to work around Bind's lack of support for scoped_ptr and ownership
1387 // passing. So we invoke to our own little routine that gets a pointer to
1388 // our local variable. This is OK since we're synchronously invoking.
1389 InvokeOnWorker(Bind(&SetRawAudioSink_w, media_channel(), ssrc, &sink));
Tommif888bb52015-12-12 01:37:01 +01001390}
1391
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001392bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001393 return InvokeOnWorker(Bind(&VoiceMediaChannel::GetStats,
1394 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001395}
1396
1397void VoiceChannel::StartMediaMonitor(int cms) {
1398 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001399 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001400 media_monitor_->SignalUpdate.connect(
1401 this, &VoiceChannel::OnMediaMonitorUpdate);
1402 media_monitor_->Start(cms);
1403}
1404
1405void VoiceChannel::StopMediaMonitor() {
1406 if (media_monitor_) {
1407 media_monitor_->Stop();
1408 media_monitor_->SignalUpdate.disconnect(this);
1409 media_monitor_.reset();
1410 }
1411}
1412
1413void VoiceChannel::StartAudioMonitor(int cms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001414 audio_monitor_.reset(new AudioMonitor(this, rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001415 audio_monitor_
1416 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1417 audio_monitor_->Start(cms);
1418}
1419
1420void VoiceChannel::StopAudioMonitor() {
1421 if (audio_monitor_) {
1422 audio_monitor_->Stop();
1423 audio_monitor_.reset();
1424 }
1425}
1426
1427bool VoiceChannel::IsAudioMonitorRunning() const {
1428 return (audio_monitor_.get() != NULL);
1429}
1430
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001431int VoiceChannel::GetInputLevel_w() {
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001432 return media_engine_->GetInputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001433}
1434
1435int VoiceChannel::GetOutputLevel_w() {
1436 return media_channel()->GetOutputLevel();
1437}
1438
1439void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1440 media_channel()->GetActiveStreams(actives);
1441}
1442
1443void VoiceChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001444 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001445 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001446 int flags) {
1447 BaseChannel::OnChannelRead(channel, data, len, packet_time, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001448
1449 // Set a flag when we've received an RTP packet. If we're waiting for early
1450 // media, this will disable the timeout.
1451 if (!received_media_ && !PacketIsRtcp(channel, data, len)) {
1452 received_media_ = true;
1453 }
1454}
1455
1456void VoiceChannel::ChangeState() {
1457 // Render incoming data if we're the active call, and we have the local
1458 // content. We receive data on the default channel and multiplexed streams.
1459 bool recv = IsReadyToReceive();
solenberg5b14b422015-10-01 04:10:31 -07001460 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001461
1462 // Send outgoing data if we're the active call, we have the remote content,
1463 // and we have had some form of connectivity.
1464 bool send = IsReadyToSend();
1465 SendFlags send_flag = send ? SEND_MICROPHONE : SEND_NOTHING;
1466 if (!media_channel()->SetSend(send_flag)) {
1467 LOG(LS_ERROR) << "Failed to SetSend " << send_flag << " on voice channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001468 }
1469
1470 LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
1471}
1472
1473const ContentInfo* VoiceChannel::GetFirstContent(
1474 const SessionDescription* sdesc) {
1475 return GetFirstAudioContent(sdesc);
1476}
1477
1478bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001479 ContentAction action,
1480 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001481 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001482 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001483 LOG(LS_INFO) << "Setting local voice description";
1484
1485 const AudioContentDescription* audio =
1486 static_cast<const AudioContentDescription*>(content);
1487 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001488 if (!audio) {
1489 SafeSetError("Can't find audio content in local description.", error_desc);
1490 return false;
1491 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001492
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001493 if (!SetRtpTransportParameters_w(content, action, CS_LOCAL, error_desc)) {
1494 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001495 }
1496
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001497 AudioRecvParameters recv_params = last_recv_params_;
1498 RtpParametersFromMediaDescription(audio, &recv_params);
1499 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001500 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001501 error_desc);
1502 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001503 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001504 for (const AudioCodec& codec : audio->codecs()) {
1505 bundle_filter()->AddPayloadType(codec.id);
1506 }
1507 last_recv_params_ = recv_params;
1508
1509 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1510 // only give it to the media channel once we have a remote
1511 // description too (without a remote description, we won't be able
1512 // to send them anyway).
1513 if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) {
1514 SafeSetError("Failed to set local audio description streams.", error_desc);
1515 return false;
1516 }
1517
1518 set_local_content_direction(content->direction());
1519 ChangeState();
1520 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001521}
1522
1523bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001524 ContentAction action,
1525 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001526 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001527 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528 LOG(LS_INFO) << "Setting remote voice description";
1529
1530 const AudioContentDescription* audio =
1531 static_cast<const AudioContentDescription*>(content);
1532 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001533 if (!audio) {
1534 SafeSetError("Can't find audio content in remote description.", error_desc);
1535 return false;
1536 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001537
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001538 if (!SetRtpTransportParameters_w(content, action, CS_REMOTE, error_desc)) {
1539 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001540 }
1541
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001542 AudioSendParameters send_params = last_send_params_;
1543 RtpSendParametersFromMediaDescription(audio, &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001544 if (audio->agc_minus_10db()) {
Karl Wibergbe579832015-11-10 22:34:18 +01001545 send_params.options.adjust_agc_delta = rtc::Optional<int>(kAgcMinus10db);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001546 }
1547 if (!media_channel()->SetSendParameters(send_params)) {
1548 SafeSetError("Failed to set remote audio description send parameters.",
1549 error_desc);
1550 return false;
1551 }
1552 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001553
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001554 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1555 // and only give it to the media channel once we have a local
1556 // description too (without a local description, we won't be able to
1557 // recv them anyway).
1558 if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) {
1559 SafeSetError("Failed to set remote audio description streams.", error_desc);
1560 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001561 }
1562
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001563 if (audio->rtp_header_extensions_set()) {
1564 MaybeCacheRtpAbsSendTimeHeaderExtension(audio->rtp_header_extensions());
1565 }
1566
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001567 set_remote_content_direction(content->direction());
1568 ChangeState();
1569 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001570}
1571
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001572void VoiceChannel::HandleEarlyMediaTimeout() {
1573 // This occurs on the main thread, not the worker thread.
1574 if (!received_media_) {
1575 LOG(LS_INFO) << "No early media received before timeout";
1576 SignalEarlyMediaTimeout(this);
1577 }
1578}
1579
Peter Boström0c4e06b2015-10-07 12:23:21 +02001580bool VoiceChannel::InsertDtmf_w(uint32_t ssrc,
1581 int event,
solenberg1d63dd02015-12-02 12:35:09 -08001582 int duration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001583 if (!enabled()) {
1584 return false;
1585 }
solenberg1d63dd02015-12-02 12:35:09 -08001586 return media_channel()->InsertDtmf(ssrc, event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001587}
1588
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001589void VoiceChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001590 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001591 case MSG_EARLYMEDIATIMEOUT:
1592 HandleEarlyMediaTimeout();
1593 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001594 case MSG_CHANNEL_ERROR: {
1595 VoiceChannelErrorMessageData* data =
1596 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001597 delete data;
1598 break;
1599 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001600 default:
1601 BaseChannel::OnMessage(pmsg);
1602 break;
1603 }
1604}
1605
1606void VoiceChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001607 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001608 SignalConnectionMonitor(this, infos);
1609}
1610
1611void VoiceChannel::OnMediaMonitorUpdate(
1612 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
1613 ASSERT(media_channel == this->media_channel());
1614 SignalMediaMonitor(this, info);
1615}
1616
1617void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1618 const AudioInfo& info) {
1619 SignalAudioMonitor(this, info);
1620}
1621
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001622void VoiceChannel::GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const {
1623 GetSupportedAudioCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001624}
1625
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001626VideoChannel::VideoChannel(rtc::Thread* thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001627 VideoMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001628 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001629 const std::string& content_name,
Fredrik Solenberg7fb711f2015-04-22 15:30:51 +02001630 bool rtcp)
deadbeefcbecd352015-09-23 11:50:27 -07001631 : BaseChannel(thread,
1632 media_channel,
1633 transport_controller,
1634 content_name,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001635 rtcp),
deadbeefcbecd352015-09-23 11:50:27 -07001636 previous_we_(rtc::WE_CLOSE) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001637
1638bool VideoChannel::Init() {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +00001639 if (!BaseChannel::Init()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001640 return false;
1641 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001642 return true;
1643}
1644
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001645VideoChannel::~VideoChannel() {
Peter Boström0c4e06b2015-10-07 12:23:21 +02001646 std::vector<uint32_t> screencast_ssrcs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001647 ScreencastMap::iterator iter;
1648 while (!screencast_capturers_.empty()) {
1649 if (!RemoveScreencast(screencast_capturers_.begin()->first)) {
1650 LOG(LS_ERROR) << "Unable to delete screencast with ssrc "
1651 << screencast_capturers_.begin()->first;
1652 ASSERT(false);
1653 break;
1654 }
1655 }
1656
1657 StopMediaMonitor();
1658 // this can't be done in the base class, since it calls a virtual
1659 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001660
1661 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001662}
1663
nisse08582ff2016-02-04 01:24:52 -08001664bool VideoChannel::SetSink(uint32_t ssrc,
1665 rtc::VideoSinkInterface<VideoFrame>* sink) {
1666 worker_thread()->Invoke<void>(
1667 Bind(&VideoMediaChannel::SetSink, media_channel(), ssrc, sink));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001668 return true;
1669}
1670
Peter Boström0c4e06b2015-10-07 12:23:21 +02001671bool VideoChannel::AddScreencast(uint32_t ssrc, VideoCapturer* capturer) {
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +00001672 return worker_thread()->Invoke<bool>(Bind(
1673 &VideoChannel::AddScreencast_w, this, ssrc, capturer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001674}
1675
Peter Boström0c4e06b2015-10-07 12:23:21 +02001676bool VideoChannel::SetCapturer(uint32_t ssrc, VideoCapturer* capturer) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001677 return InvokeOnWorker(Bind(&VideoMediaChannel::SetCapturer,
1678 media_channel(), ssrc, capturer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001679}
1680
Peter Boström0c4e06b2015-10-07 12:23:21 +02001681bool VideoChannel::RemoveScreencast(uint32_t ssrc) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001682 return InvokeOnWorker(Bind(&VideoChannel::RemoveScreencast_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001683}
1684
1685bool VideoChannel::IsScreencasting() {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001686 return InvokeOnWorker(Bind(&VideoChannel::IsScreencasting_w, this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001687}
1688
Peter Boström0c4e06b2015-10-07 12:23:21 +02001689bool VideoChannel::SetVideoSend(uint32_t ssrc,
deadbeefcbecd352015-09-23 11:50:27 -07001690 bool mute,
solenberg1dd98f32015-09-10 01:57:14 -07001691 const VideoOptions* options) {
deadbeefcbecd352015-09-23 11:50:27 -07001692 return InvokeOnWorker(Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
1693 ssrc, mute, options));
solenberg1dd98f32015-09-10 01:57:14 -07001694}
1695
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001696void VideoChannel::ChangeState() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001697 // Send outgoing data if we're the active call, we have the remote content,
1698 // and we have had some form of connectivity.
1699 bool send = IsReadyToSend();
1700 if (!media_channel()->SetSend(send)) {
1701 LOG(LS_ERROR) << "Failed to SetSend on video channel";
1702 // TODO(gangji): Report error back to server.
1703 }
1704
Peter Boström34fbfff2015-09-24 19:20:30 +02001705 LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001706}
1707
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00001708bool VideoChannel::GetStats(VideoMediaInfo* stats) {
1709 return InvokeOnWorker(
1710 Bind(&VideoMediaChannel::GetStats, media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001711}
1712
1713void VideoChannel::StartMediaMonitor(int cms) {
1714 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001715 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001716 media_monitor_->SignalUpdate.connect(
1717 this, &VideoChannel::OnMediaMonitorUpdate);
1718 media_monitor_->Start(cms);
1719}
1720
1721void VideoChannel::StopMediaMonitor() {
1722 if (media_monitor_) {
1723 media_monitor_->Stop();
1724 media_monitor_.reset();
1725 }
1726}
1727
1728const ContentInfo* VideoChannel::GetFirstContent(
1729 const SessionDescription* sdesc) {
1730 return GetFirstVideoContent(sdesc);
1731}
1732
1733bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001734 ContentAction action,
1735 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001736 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001737 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001738 LOG(LS_INFO) << "Setting local video description";
1739
1740 const VideoContentDescription* video =
1741 static_cast<const VideoContentDescription*>(content);
1742 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001743 if (!video) {
1744 SafeSetError("Can't find video content in local description.", error_desc);
1745 return false;
1746 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001747
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001748 if (!SetRtpTransportParameters_w(content, action, CS_LOCAL, error_desc)) {
1749 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001750 }
1751
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001752 VideoRecvParameters recv_params = last_recv_params_;
1753 RtpParametersFromMediaDescription(video, &recv_params);
1754 if (!media_channel()->SetRecvParameters(recv_params)) {
1755 SafeSetError("Failed to set local video description recv parameters.",
1756 error_desc);
1757 return false;
1758 }
1759 for (const VideoCodec& codec : video->codecs()) {
1760 bundle_filter()->AddPayloadType(codec.id);
1761 }
1762 last_recv_params_ = recv_params;
1763
1764 // TODO(pthatcher): Move local streams into VideoSendParameters, and
1765 // only give it to the media channel once we have a remote
1766 // description too (without a remote description, we won't be able
1767 // to send them anyway).
1768 if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) {
1769 SafeSetError("Failed to set local video description streams.", error_desc);
1770 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001771 }
1772
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001773 set_local_content_direction(content->direction());
1774 ChangeState();
1775 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001776}
1777
1778bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001779 ContentAction action,
1780 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001781 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001782 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001783 LOG(LS_INFO) << "Setting remote video description";
1784
1785 const VideoContentDescription* video =
1786 static_cast<const VideoContentDescription*>(content);
1787 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001788 if (!video) {
1789 SafeSetError("Can't find video content in remote description.", error_desc);
1790 return false;
1791 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001792
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001793
1794 if (!SetRtpTransportParameters_w(content, action, CS_REMOTE, error_desc)) {
1795 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001796 }
1797
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001798 VideoSendParameters send_params = last_send_params_;
1799 RtpSendParametersFromMediaDescription(video, &send_params);
1800 if (video->conference_mode()) {
Karl Wibergbe579832015-11-10 22:34:18 +01001801 send_params.options.conference_mode = rtc::Optional<bool>(true);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001802 }
1803 if (!media_channel()->SetSendParameters(send_params)) {
1804 SafeSetError("Failed to set remote video description send parameters.",
1805 error_desc);
1806 return false;
1807 }
1808 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001809
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001810 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
1811 // and only give it to the media channel once we have a local
1812 // description too (without a local description, we won't be able to
1813 // recv them anyway).
1814 if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) {
1815 SafeSetError("Failed to set remote video description streams.", error_desc);
1816 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001817 }
1818
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001819 if (video->rtp_header_extensions_set()) {
1820 MaybeCacheRtpAbsSendTimeHeaderExtension(video->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001821 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001822
1823 set_remote_content_direction(content->direction());
1824 ChangeState();
1825 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001826}
1827
Peter Boström0c4e06b2015-10-07 12:23:21 +02001828bool VideoChannel::AddScreencast_w(uint32_t ssrc, VideoCapturer* capturer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001829 if (screencast_capturers_.find(ssrc) != screencast_capturers_.end()) {
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +00001830 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001831 }
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +00001832 capturer->SignalStateChange.connect(this, &VideoChannel::OnStateChange);
1833 screencast_capturers_[ssrc] = capturer;
1834 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001835}
1836
Peter Boström0c4e06b2015-10-07 12:23:21 +02001837bool VideoChannel::RemoveScreencast_w(uint32_t ssrc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001838 ScreencastMap::iterator iter = screencast_capturers_.find(ssrc);
1839 if (iter == screencast_capturers_.end()) {
1840 return false;
1841 }
1842 // Clean up VideoCapturer.
1843 delete iter->second;
1844 screencast_capturers_.erase(iter);
1845 return true;
1846}
1847
1848bool VideoChannel::IsScreencasting_w() const {
1849 return !screencast_capturers_.empty();
1850}
1851
Peter Boström0c4e06b2015-10-07 12:23:21 +02001852void VideoChannel::OnScreencastWindowEvent_s(uint32_t ssrc,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001853 rtc::WindowEvent we) {
1854 ASSERT(signaling_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001855 SignalScreencastWindowEvent(ssrc, we);
1856}
1857
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001858void VideoChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001859 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001860 case MSG_SCREENCASTWINDOWEVENT: {
1861 const ScreencastEventMessageData* data =
1862 static_cast<ScreencastEventMessageData*>(pmsg->pdata);
1863 OnScreencastWindowEvent_s(data->ssrc, data->event);
1864 delete data;
1865 break;
1866 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001867 case MSG_CHANNEL_ERROR: {
1868 const VideoChannelErrorMessageData* data =
1869 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001870 delete data;
1871 break;
1872 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001873 default:
1874 BaseChannel::OnMessage(pmsg);
1875 break;
1876 }
1877}
1878
1879void VideoChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001880 ConnectionMonitor* monitor, const std::vector<ConnectionInfo> &infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001881 SignalConnectionMonitor(this, infos);
1882}
1883
1884// TODO(pthatcher): Look into removing duplicate code between
1885// audio, video, and data, perhaps by using templates.
1886void VideoChannel::OnMediaMonitorUpdate(
1887 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
1888 ASSERT(media_channel == this->media_channel());
1889 SignalMediaMonitor(this, info);
1890}
1891
Peter Boström0c4e06b2015-10-07 12:23:21 +02001892void VideoChannel::OnScreencastWindowEvent(uint32_t ssrc,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001893 rtc::WindowEvent event) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001894 ScreencastEventMessageData* pdata =
1895 new ScreencastEventMessageData(ssrc, event);
1896 signaling_thread()->Post(this, MSG_SCREENCASTWINDOWEVENT, pdata);
1897}
1898
1899void VideoChannel::OnStateChange(VideoCapturer* capturer, CaptureState ev) {
1900 // Map capturer events to window events. In the future we may want to simply
1901 // pass these events up directly.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001902 rtc::WindowEvent we;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001903 if (ev == CS_STOPPED) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001904 we = rtc::WE_CLOSE;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001905 } else if (ev == CS_PAUSED) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001906 we = rtc::WE_MINIMIZE;
1907 } else if (ev == CS_RUNNING && previous_we_ == rtc::WE_MINIMIZE) {
1908 we = rtc::WE_RESTORE;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001909 } else {
1910 return;
1911 }
1912 previous_we_ = we;
1913
Peter Boström0c4e06b2015-10-07 12:23:21 +02001914 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001915 if (!GetLocalSsrc(capturer, &ssrc)) {
1916 return;
1917 }
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001918
1919 OnScreencastWindowEvent(ssrc, we);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001920}
1921
Peter Boström0c4e06b2015-10-07 12:23:21 +02001922bool VideoChannel::GetLocalSsrc(const VideoCapturer* capturer, uint32_t* ssrc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001923 *ssrc = 0;
1924 for (ScreencastMap::iterator iter = screencast_capturers_.begin();
1925 iter != screencast_capturers_.end(); ++iter) {
1926 if (iter->second == capturer) {
1927 *ssrc = iter->first;
1928 return true;
1929 }
1930 }
1931 return false;
1932}
1933
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001934void VideoChannel::GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const {
1935 GetSupportedVideoCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001936}
1937
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001938DataChannel::DataChannel(rtc::Thread* thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001939 DataMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001940 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001941 const std::string& content_name,
1942 bool rtcp)
deadbeefcbecd352015-09-23 11:50:27 -07001943 : BaseChannel(thread,
1944 media_channel,
1945 transport_controller,
1946 content_name,
1947 rtcp),
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00001948 data_channel_type_(cricket::DCT_NONE),
deadbeefcbecd352015-09-23 11:50:27 -07001949 ready_to_send_data_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001950
1951DataChannel::~DataChannel() {
1952 StopMediaMonitor();
1953 // this can't be done in the base class, since it calls a virtual
1954 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001955
1956 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001957}
1958
1959bool DataChannel::Init() {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +00001960 if (!BaseChannel::Init()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001961 return false;
1962 }
1963 media_channel()->SignalDataReceived.connect(
1964 this, &DataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001965 media_channel()->SignalReadyToSend.connect(
1966 this, &DataChannel::OnDataChannelReadyToSend);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00001967 media_channel()->SignalStreamClosedRemotely.connect(
1968 this, &DataChannel::OnStreamClosedRemotely);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001969 return true;
1970}
1971
1972bool DataChannel::SendData(const SendDataParams& params,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001973 const rtc::Buffer& payload,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001974 SendDataResult* result) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001975 return InvokeOnWorker(Bind(&DataMediaChannel::SendData,
1976 media_channel(), params, payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001977}
1978
1979const ContentInfo* DataChannel::GetFirstContent(
1980 const SessionDescription* sdesc) {
1981 return GetFirstDataContent(sdesc);
1982}
1983
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001984bool DataChannel::WantsPacket(bool rtcp, rtc::Buffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001985 if (data_channel_type_ == DCT_SCTP) {
1986 // TODO(pthatcher): Do this in a more robust way by checking for
1987 // SCTP or DTLS.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +00001988 return !IsRtpPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001989 } else if (data_channel_type_ == DCT_RTP) {
1990 return BaseChannel::WantsPacket(rtcp, packet);
1991 }
1992 return false;
1993}
1994
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001995bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
1996 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001997 // It hasn't been set before, so set it now.
1998 if (data_channel_type_ == DCT_NONE) {
1999 data_channel_type_ = new_data_channel_type;
2000 return true;
2001 }
2002
2003 // It's been set before, but doesn't match. That's bad.
2004 if (data_channel_type_ != new_data_channel_type) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002005 std::ostringstream desc;
2006 desc << "Data channel type mismatch."
2007 << " Expected " << data_channel_type_
2008 << " Got " << new_data_channel_type;
2009 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002010 return false;
2011 }
2012
2013 // It's hasn't changed. Nothing to do.
2014 return true;
2015}
2016
2017bool DataChannel::SetDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002018 const DataContentDescription* content,
2019 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002020 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
2021 (content->protocol() == kMediaProtocolDtlsSctp));
2022 DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002023 return SetDataChannelType(data_channel_type, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002024}
2025
2026bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002027 ContentAction action,
2028 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002029 TRACE_EVENT0("webrtc", "DataChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002030 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002031 LOG(LS_INFO) << "Setting local data description";
2032
2033 const DataContentDescription* data =
2034 static_cast<const DataContentDescription*>(content);
2035 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002036 if (!data) {
2037 SafeSetError("Can't find data content in local description.", error_desc);
2038 return false;
2039 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002040
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002041 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002042 return false;
2043 }
2044
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002045 if (data_channel_type_ == DCT_RTP) {
2046 if (!SetRtpTransportParameters_w(content, action, CS_LOCAL, error_desc)) {
2047 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002048 }
2049 }
2050
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002051 // FYI: We send the SCTP port number (not to be confused with the
2052 // underlying UDP port number) as a codec parameter. So even SCTP
2053 // data channels need codecs.
2054 DataRecvParameters recv_params = last_recv_params_;
2055 RtpParametersFromMediaDescription(data, &recv_params);
2056 if (!media_channel()->SetRecvParameters(recv_params)) {
2057 SafeSetError("Failed to set remote data description recv parameters.",
2058 error_desc);
2059 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002060 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002061 if (data_channel_type_ == DCT_RTP) {
2062 for (const DataCodec& codec : data->codecs()) {
2063 bundle_filter()->AddPayloadType(codec.id);
2064 }
2065 }
2066 last_recv_params_ = recv_params;
2067
2068 // TODO(pthatcher): Move local streams into DataSendParameters, and
2069 // only give it to the media channel once we have a remote
2070 // description too (without a remote description, we won't be able
2071 // to send them anyway).
2072 if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) {
2073 SafeSetError("Failed to set local data description streams.", error_desc);
2074 return false;
2075 }
2076
2077 set_local_content_direction(content->direction());
2078 ChangeState();
2079 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002080}
2081
2082bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002083 ContentAction action,
2084 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01002085 TRACE_EVENT0("webrtc", "DataChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002086 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002087
2088 const DataContentDescription* data =
2089 static_cast<const DataContentDescription*>(content);
2090 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002091 if (!data) {
2092 SafeSetError("Can't find data content in remote description.", error_desc);
2093 return false;
2094 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002095
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002096 // If the remote data doesn't have codecs and isn't an update, it
2097 // must be empty, so ignore it.
2098 if (!data->has_codecs() && action != CA_UPDATE) {
2099 return true;
2100 }
2101
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002102 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002103 return false;
2104 }
2105
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002106 LOG(LS_INFO) << "Setting remote data description";
2107 if (data_channel_type_ == DCT_RTP &&
2108 !SetRtpTransportParameters_w(content, action, CS_REMOTE, error_desc)) {
2109 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002110 }
2111
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002112
2113 DataSendParameters send_params = last_send_params_;
2114 RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params);
2115 if (!media_channel()->SetSendParameters(send_params)) {
2116 SafeSetError("Failed to set remote data description send parameters.",
2117 error_desc);
2118 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002119 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002120 last_send_params_ = send_params;
2121
2122 // TODO(pthatcher): Move remote streams into DataRecvParameters,
2123 // and only give it to the media channel once we have a local
2124 // description too (without a local description, we won't be able to
2125 // recv them anyway).
2126 if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) {
2127 SafeSetError("Failed to set remote data description streams.",
2128 error_desc);
2129 return false;
2130 }
2131
2132 set_remote_content_direction(content->direction());
2133 ChangeState();
2134 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002135}
2136
2137void DataChannel::ChangeState() {
2138 // Render incoming data if we're the active call, and we have the local
2139 // content. We receive data on the default channel and multiplexed streams.
2140 bool recv = IsReadyToReceive();
2141 if (!media_channel()->SetReceive(recv)) {
2142 LOG(LS_ERROR) << "Failed to SetReceive on data channel";
2143 }
2144
2145 // Send outgoing data if we're the active call, we have the remote content,
2146 // and we have had some form of connectivity.
2147 bool send = IsReadyToSend();
2148 if (!media_channel()->SetSend(send)) {
2149 LOG(LS_ERROR) << "Failed to SetSend on data channel";
2150 }
2151
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002152 // Trigger SignalReadyToSendData asynchronously.
2153 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002154
2155 LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
2156}
2157
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002158void DataChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002159 switch (pmsg->message_id) {
2160 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002161 DataChannelReadyToSendMessageData* data =
2162 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002163 ready_to_send_data_ = data->data();
2164 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002165 delete data;
2166 break;
2167 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002168 case MSG_DATARECEIVED: {
2169 DataReceivedMessageData* data =
2170 static_cast<DataReceivedMessageData*>(pmsg->pdata);
2171 SignalDataReceived(this, data->params, data->payload);
2172 delete data;
2173 break;
2174 }
2175 case MSG_CHANNEL_ERROR: {
2176 const DataChannelErrorMessageData* data =
2177 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002178 delete data;
2179 break;
2180 }
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002181 case MSG_STREAMCLOSEDREMOTELY: {
Peter Boström0c4e06b2015-10-07 12:23:21 +02002182 rtc::TypedMessageData<uint32_t>* data =
2183 static_cast<rtc::TypedMessageData<uint32_t>*>(pmsg->pdata);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002184 SignalStreamClosedRemotely(data->data());
2185 delete data;
2186 break;
2187 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002188 default:
2189 BaseChannel::OnMessage(pmsg);
2190 break;
2191 }
2192}
2193
2194void DataChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002195 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002196 SignalConnectionMonitor(this, infos);
2197}
2198
2199void DataChannel::StartMediaMonitor(int cms) {
2200 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002201 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002202 media_monitor_->SignalUpdate.connect(
2203 this, &DataChannel::OnMediaMonitorUpdate);
2204 media_monitor_->Start(cms);
2205}
2206
2207void DataChannel::StopMediaMonitor() {
2208 if (media_monitor_) {
2209 media_monitor_->Stop();
2210 media_monitor_->SignalUpdate.disconnect(this);
2211 media_monitor_.reset();
2212 }
2213}
2214
2215void DataChannel::OnMediaMonitorUpdate(
2216 DataMediaChannel* media_channel, const DataMediaInfo& info) {
2217 ASSERT(media_channel == this->media_channel());
2218 SignalMediaMonitor(this, info);
2219}
2220
2221void DataChannel::OnDataReceived(
2222 const ReceiveDataParams& params, const char* data, size_t len) {
2223 DataReceivedMessageData* msg = new DataReceivedMessageData(
2224 params, data, len);
2225 signaling_thread()->Post(this, MSG_DATARECEIVED, msg);
2226}
2227
Peter Boström0c4e06b2015-10-07 12:23:21 +02002228void DataChannel::OnDataChannelError(uint32_t ssrc,
2229 DataMediaChannel::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002230 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2231 ssrc, err);
2232 signaling_thread()->Post(this, MSG_CHANNEL_ERROR, data);
2233}
2234
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002235void DataChannel::OnDataChannelReadyToSend(bool writable) {
2236 // This is usded for congestion control to indicate that the stream is ready
2237 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2238 // that the transport channel is ready.
2239 signaling_thread()->Post(this, MSG_READYTOSENDDATA,
2240 new DataChannelReadyToSendMessageData(writable));
2241}
2242
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002243void DataChannel::GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const {
2244 GetSupportedDataCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002245}
2246
2247bool DataChannel::ShouldSetupDtlsSrtp() const {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08002248 return (data_channel_type_ == DCT_RTP) && BaseChannel::ShouldSetupDtlsSrtp();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002249}
2250
Peter Boström0c4e06b2015-10-07 12:23:21 +02002251void DataChannel::OnStreamClosedRemotely(uint32_t sid) {
2252 rtc::TypedMessageData<uint32_t>* message =
2253 new rtc::TypedMessageData<uint32_t>(sid);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002254 signaling_thread()->Post(this, MSG_STREAMCLOSEDREMOTELY, message);
2255}
2256
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002257} // namespace cricket