blob: b05c0bc5024919d3b69e0955e58b22f0a7573958 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander65c7f672016-02-12 00:05:01 -08002 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander65c7f672016-02-12 00:05:01 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
kwiberg0eb15ed2015-12-17 03:04:15 -080011#include <utility>
12
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010013#include "webrtc/pc/channel.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014
kjellander@webrtc.org7ffeab52016-02-26 22:46:09 +010015#include "webrtc/audio_sink.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000016#include "webrtc/base/bind.h"
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"
kjellanderf4752772016-03-02 05:42:30 -080023#include "webrtc/media/base/mediaconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080024#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) {
kwiberg686a8ef2016-02-26 03:00:35 -080036 channel->SetRawAudioSink(ssrc, rtc::ScopedToUnique(std::move(*sink)));
deadbeef2d110be2016-01-13 12:00:26 -080037 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_RTPPACKET,
44 MSG_RTCPPACKET,
45 MSG_CHANNEL_ERROR,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000047 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000048 MSG_FIRSTPACKETRECEIVED,
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +000049 MSG_STREAMCLOSEDREMOTELY,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000050};
51
52// Value specified in RFC 5764.
53static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
54
55static const int kAgcMinus10db = -10;
56
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000057static void SafeSetError(const std::string& message, std::string* error_desc) {
58 if (error_desc) {
59 *error_desc = message;
60 }
61}
62
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000063struct PacketMessageData : public rtc::MessageData {
64 rtc::Buffer packet;
stefanc1aeaf02015-10-15 07:26:07 -070065 rtc::PacketOptions options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066};
67
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000068struct VoiceChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020069 VoiceChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000070 VoiceMediaChannel::Error in_error)
Peter Boström0c4e06b2015-10-07 12:23:21 +020071 : ssrc(in_ssrc), error(in_error) {}
72 uint32_t ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000073 VoiceMediaChannel::Error error;
74};
75
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000076struct VideoChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020077 VideoChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000078 VideoMediaChannel::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 VideoMediaChannel::Error error;
82};
83
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000084struct DataChannelErrorMessageData : public rtc::MessageData {
Peter Boström0c4e06b2015-10-07 12:23:21 +020085 DataChannelErrorMessageData(uint32_t in_ssrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086 DataMediaChannel::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 DataMediaChannel::Error error;
90};
91
henrike@webrtc.org28e20752013-07-10 00:45:36 +000092static const char* PacketType(bool rtcp) {
93 return (!rtcp) ? "RTP" : "RTCP";
94}
95
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000096static bool ValidPacket(bool rtcp, const rtc::Buffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097 // Check the packet size. We could check the header too if needed.
98 return (packet &&
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +000099 packet->size() >= (!rtcp ? kMinRtpPacketLen : kMinRtcpPacketLen) &&
100 packet->size() <= kMaxRtpPacketLen);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000101}
102
103static bool IsReceiveContentDirection(MediaContentDirection direction) {
104 return direction == MD_SENDRECV || direction == MD_RECVONLY;
105}
106
107static bool IsSendContentDirection(MediaContentDirection direction) {
108 return direction == MD_SENDRECV || direction == MD_SENDONLY;
109}
110
111static const MediaContentDescription* GetContentDescription(
112 const ContentInfo* cinfo) {
113 if (cinfo == NULL)
114 return NULL;
115 return static_cast<const MediaContentDescription*>(cinfo->description);
116}
117
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700118template <class Codec>
119void RtpParametersFromMediaDescription(
120 const MediaContentDescriptionImpl<Codec>* desc,
121 RtpParameters<Codec>* params) {
122 // TODO(pthatcher): Remove this once we're sure no one will give us
123 // a description without codecs (currently a CA_UPDATE with just
124 // streams can).
125 if (desc->has_codecs()) {
126 params->codecs = desc->codecs();
127 }
128 // TODO(pthatcher): See if we really need
129 // rtp_header_extensions_set() and remove it if we don't.
130 if (desc->rtp_header_extensions_set()) {
131 params->extensions = desc->rtp_header_extensions();
132 }
deadbeef13871492015-12-09 12:37:51 -0800133 params->rtcp.reduced_size = desc->rtcp_reduced_size();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700134}
135
136template <class Codec, class Options>
137void RtpSendParametersFromMediaDescription(
138 const MediaContentDescriptionImpl<Codec>* desc,
139 RtpSendParameters<Codec, Options>* send_params) {
140 RtpParametersFromMediaDescription(desc, send_params);
141 send_params->max_bandwidth_bps = desc->bandwidth();
142}
143
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000144BaseChannel::BaseChannel(rtc::Thread* thread,
deadbeefcbecd352015-09-23 11:50:27 -0700145 MediaChannel* media_channel,
146 TransportController* transport_controller,
147 const std::string& content_name,
148 bool rtcp)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000149 : worker_thread_(thread),
deadbeefcbecd352015-09-23 11:50:27 -0700150 transport_controller_(transport_controller),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000151 media_channel_(media_channel),
152 content_name_(content_name),
deadbeefcbecd352015-09-23 11:50:27 -0700153 rtcp_transport_enabled_(rtcp),
154 transport_channel_(nullptr),
155 rtcp_transport_channel_(nullptr),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000156 enabled_(false),
157 writable_(false),
158 rtp_ready_to_send_(false),
159 rtcp_ready_to_send_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000160 was_ever_writable_(false),
161 local_content_direction_(MD_INACTIVE),
162 remote_content_direction_(MD_INACTIVE),
163 has_received_packet_(false),
164 dtls_keyed_(false),
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000165 secure_required_(false),
166 rtp_abs_sendtime_extn_id_(-1) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000167 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000168 LOG(LS_INFO) << "Created channel for " << content_name;
169}
170
171BaseChannel::~BaseChannel() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000172 ASSERT(worker_thread_ == rtc::Thread::Current());
wu@webrtc.org78187522013-10-07 23:32:02 +0000173 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000174 StopConnectionMonitor();
175 FlushRtcpMessages(); // Send any outstanding RTCP packets.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000176 worker_thread_->Clear(this); // eats any outstanding messages or packets
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000177 // We must destroy the media channel before the transport channel, otherwise
178 // the media channel may try to send on the dead transport channel. NULLing
179 // is not an effective strategy since the sends will come on another thread.
180 delete media_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700181 // Note that we don't just call set_transport_channel(nullptr) because that
182 // would call a pure virtual method which we can't do from a destructor.
183 if (transport_channel_) {
184 DisconnectFromTransportChannel(transport_channel_);
185 transport_controller_->DestroyTransportChannel_w(
186 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
187 }
188 if (rtcp_transport_channel_) {
189 DisconnectFromTransportChannel(rtcp_transport_channel_);
190 transport_controller_->DestroyTransportChannel_w(
191 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
192 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000193 LOG(LS_INFO) << "Destroyed channel";
194}
195
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000196bool BaseChannel::Init() {
deadbeefcbecd352015-09-23 11:50:27 -0700197 if (!SetTransport(content_name())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000198 return false;
199 }
200
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800201 if (!SetDtlsSrtpCryptoSuites(transport_channel(), false)) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000202 return false;
203 }
deadbeefcbecd352015-09-23 11:50:27 -0700204 if (rtcp_transport_enabled() &&
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800205 !SetDtlsSrtpCryptoSuites(rtcp_transport_channel(), true)) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000206 return false;
207 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000208
wu@webrtc.orgde305012013-10-31 15:40:38 +0000209 // Both RTP and RTCP channels are set, we can call SetInterface on
210 // media channel and it can set network options.
211 media_channel_->SetInterface(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000212 return true;
213}
214
wu@webrtc.org78187522013-10-07 23:32:02 +0000215void BaseChannel::Deinit() {
216 media_channel_->SetInterface(NULL);
217}
218
deadbeefcbecd352015-09-23 11:50:27 -0700219bool BaseChannel::SetTransport(const std::string& transport_name) {
220 return worker_thread_->Invoke<bool>(
221 Bind(&BaseChannel::SetTransport_w, this, transport_name));
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000222}
223
deadbeefcbecd352015-09-23 11:50:27 -0700224bool BaseChannel::SetTransport_w(const std::string& transport_name) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000225 ASSERT(worker_thread_ == rtc::Thread::Current());
226
deadbeefcbecd352015-09-23 11:50:27 -0700227 if (transport_name == transport_name_) {
228 // Nothing to do if transport name isn't changing
229 return true;
230 }
231
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800232 // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport
233 // changes and wait until the DTLS handshake is complete to set the newly
234 // negotiated parameters.
235 if (ShouldSetupDtlsSrtp()) {
guoweis46383312015-12-17 16:45:59 -0800236 // Set |writable_| to false such that UpdateWritableState_w can set up
237 // DTLS-SRTP when the writable_ becomes true again.
238 writable_ = false;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800239 srtp_filter_.ResetParams();
240 }
241
guoweis46383312015-12-17 16:45:59 -0800242 // TODO(guoweis): Remove this grossness when we remove non-muxed RTCP.
deadbeefcbecd352015-09-23 11:50:27 -0700243 if (rtcp_transport_enabled()) {
244 LOG(LS_INFO) << "Create RTCP TransportChannel for " << content_name()
245 << " on " << transport_name << " transport ";
guoweis46383312015-12-17 16:45:59 -0800246 set_rtcp_transport_channel(
247 transport_controller_->CreateTransportChannel_w(
248 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP),
249 false /* update_writablity */);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000250 if (!rtcp_transport_channel()) {
251 return false;
252 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000253 }
254
guoweis46383312015-12-17 16:45:59 -0800255 // We're not updating the writablity during the transition state.
256 set_transport_channel(transport_controller_->CreateTransportChannel_w(
257 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP));
258 if (!transport_channel()) {
259 return false;
260 }
261
262 // TODO(guoweis): Remove this grossness when we remove non-muxed RTCP.
263 if (rtcp_transport_enabled()) {
264 // We can only update the RTCP ready to send after set_transport_channel has
265 // handled channel writability.
266 SetReadyToSend(
267 true, rtcp_transport_channel() && rtcp_transport_channel()->writable());
268 }
deadbeefcbecd352015-09-23 11:50:27 -0700269 transport_name_ = transport_name;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000270 return true;
271}
272
273void BaseChannel::set_transport_channel(TransportChannel* new_tc) {
274 ASSERT(worker_thread_ == rtc::Thread::Current());
275
276 TransportChannel* old_tc = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700277 if (!old_tc && !new_tc) {
278 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000279 return;
280 }
deadbeefcbecd352015-09-23 11:50:27 -0700281 ASSERT(old_tc != new_tc);
282
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000283 if (old_tc) {
284 DisconnectFromTransportChannel(old_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700285 transport_controller_->DestroyTransportChannel_w(
286 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000287 }
288
289 transport_channel_ = new_tc;
290
291 if (new_tc) {
292 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700293 for (const auto& pair : socket_options_) {
294 new_tc->SetOption(pair.first, pair.second);
295 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000296 }
deadbeefcbecd352015-09-23 11:50:27 -0700297
298 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
299 // setting new channel
300 UpdateWritableState_w();
301 SetReadyToSend(false, new_tc && new_tc->writable());
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000302}
303
guoweis46383312015-12-17 16:45:59 -0800304void BaseChannel::set_rtcp_transport_channel(TransportChannel* new_tc,
305 bool update_writablity) {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000306 ASSERT(worker_thread_ == rtc::Thread::Current());
307
308 TransportChannel* old_tc = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700309 if (!old_tc && !new_tc) {
310 // Nothing to do
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000311 return;
312 }
deadbeefcbecd352015-09-23 11:50:27 -0700313 ASSERT(old_tc != new_tc);
314
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000315 if (old_tc) {
316 DisconnectFromTransportChannel(old_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700317 transport_controller_->DestroyTransportChannel_w(
318 transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000319 }
320
321 rtcp_transport_channel_ = new_tc;
322
323 if (new_tc) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800324 RTC_CHECK(!(ShouldSetupDtlsSrtp() && srtp_filter_.IsActive()))
325 << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
326 << "should never happen.";
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000327 ConnectToTransportChannel(new_tc);
deadbeefcbecd352015-09-23 11:50:27 -0700328 for (const auto& pair : rtcp_socket_options_) {
329 new_tc->SetOption(pair.first, pair.second);
330 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000331 }
deadbeefcbecd352015-09-23 11:50:27 -0700332
guoweis46383312015-12-17 16:45:59 -0800333 if (update_writablity) {
334 // Update aggregate writable/ready-to-send state between RTP and RTCP upon
335 // setting new channel
336 UpdateWritableState_w();
337 SetReadyToSend(true, new_tc && new_tc->writable());
338 }
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000339}
340
341void BaseChannel::ConnectToTransportChannel(TransportChannel* tc) {
342 ASSERT(worker_thread_ == rtc::Thread::Current());
343
344 tc->SignalWritableState.connect(this, &BaseChannel::OnWritableState);
345 tc->SignalReadPacket.connect(this, &BaseChannel::OnChannelRead);
346 tc->SignalReadyToSend.connect(this, &BaseChannel::OnReadyToSend);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800347 tc->SignalDtlsState.connect(this, &BaseChannel::OnDtlsState);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000348}
349
350void BaseChannel::DisconnectFromTransportChannel(TransportChannel* tc) {
351 ASSERT(worker_thread_ == rtc::Thread::Current());
352
353 tc->SignalWritableState.disconnect(this);
354 tc->SignalReadPacket.disconnect(this);
355 tc->SignalReadyToSend.disconnect(this);
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800356 tc->SignalDtlsState.disconnect(this);
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000357}
358
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359bool BaseChannel::Enable(bool enable) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000360 worker_thread_->Invoke<void>(Bind(
361 enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
362 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000363 return true;
364}
365
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000366bool BaseChannel::AddRecvStream(const StreamParams& sp) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000367 return InvokeOnWorker(Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368}
369
Peter Boström0c4e06b2015-10-07 12:23:21 +0200370bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000371 return InvokeOnWorker(Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000372}
373
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000374bool BaseChannel::AddSendStream(const StreamParams& sp) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000375 return InvokeOnWorker(
376 Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000377}
378
Peter Boström0c4e06b2015-10-07 12:23:21 +0200379bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000380 return InvokeOnWorker(
381 Bind(&MediaChannel::RemoveSendStream, media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000382}
383
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000384bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000385 ContentAction action,
386 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100387 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000388 return InvokeOnWorker(Bind(&BaseChannel::SetLocalContent_w,
389 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000390}
391
392bool BaseChannel::SetRemoteContent(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::SetRemoteContent");
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +0000396 return InvokeOnWorker(Bind(&BaseChannel::SetRemoteContent_w,
397 this, content, action, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000398}
399
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000400void BaseChannel::StartConnectionMonitor(int cms) {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000401 // We pass in the BaseChannel instead of the transport_channel_
402 // because if the transport_channel_ changes, the ConnectionMonitor
403 // would be pointing to the wrong TransportChannel.
404 connection_monitor_.reset(new ConnectionMonitor(
405 this, worker_thread(), rtc::Thread::Current()));
406 connection_monitor_->SignalUpdate.connect(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000407 this, &BaseChannel::OnConnectionMonitorUpdate);
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000408 connection_monitor_->Start(cms);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000409}
410
411void BaseChannel::StopConnectionMonitor() {
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000412 if (connection_monitor_) {
413 connection_monitor_->Stop();
414 connection_monitor_.reset();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000415 }
416}
417
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +0000418bool BaseChannel::GetConnectionStats(ConnectionInfos* infos) {
419 ASSERT(worker_thread_ == rtc::Thread::Current());
420 return transport_channel_->GetStats(infos);
421}
422
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000423bool BaseChannel::IsReadyToReceive() const {
424 // Receive data if we are enabled and have local content,
425 return enabled() && IsReceiveContentDirection(local_content_direction_);
426}
427
428bool BaseChannel::IsReadyToSend() const {
429 // Send outgoing data if we are enabled, have local and remote content,
430 // and we have had some form of connectivity.
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800431 return enabled() && IsReceiveContentDirection(remote_content_direction_) &&
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000432 IsSendContentDirection(local_content_direction_) &&
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800433 was_ever_writable() &&
434 (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000435}
436
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000437bool BaseChannel::SendPacket(rtc::Buffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700438 const rtc::PacketOptions& options) {
439 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440}
441
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000442bool BaseChannel::SendRtcp(rtc::Buffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700443 const rtc::PacketOptions& options) {
444 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000445}
446
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000447int BaseChannel::SetOption(SocketType type, rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000448 int value) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000449 TransportChannel* channel = NULL;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000450 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000451 case ST_RTP:
452 channel = transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700453 socket_options_.push_back(
454 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000455 break;
456 case ST_RTCP:
457 channel = rtcp_transport_channel_;
deadbeefcbecd352015-09-23 11:50:27 -0700458 rtcp_socket_options_.push_back(
459 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000460 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000461 }
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000462 return channel ? channel->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000463}
464
465void BaseChannel::OnWritableState(TransportChannel* channel) {
466 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
deadbeefcbecd352015-09-23 11:50:27 -0700467 UpdateWritableState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000468}
469
470void BaseChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000471 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000472 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +0000473 int flags) {
Peter Boström6f28cf02015-12-07 23:17:15 +0100474 TRACE_EVENT0("webrtc", "BaseChannel::OnChannelRead");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000475 // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000476 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000477
478 // When using RTCP multiplexing we might get RTCP packets on the RTP
479 // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
480 bool rtcp = PacketIsRtcp(channel, data, len);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000481 rtc::Buffer packet(data, len);
wu@webrtc.orga9890802013-12-13 00:21:03 +0000482 HandlePacket(rtcp, &packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000483}
484
485void BaseChannel::OnReadyToSend(TransportChannel* channel) {
deadbeefcbecd352015-09-23 11:50:27 -0700486 ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
487 SetReadyToSend(channel == rtcp_transport_channel_, true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488}
489
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800490void BaseChannel::OnDtlsState(TransportChannel* channel,
491 DtlsTransportState state) {
492 if (!ShouldSetupDtlsSrtp()) {
493 return;
494 }
495
496 // Reset the srtp filter if it's not the CONNECTED state. For the CONNECTED
497 // state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to
498 // cover other scenarios like the whole channel is writable (not just this
499 // TransportChannel) or when TransportChannel is attached after DTLS is
500 // negotiated.
501 if (state != DTLS_TRANSPORT_CONNECTED) {
502 srtp_filter_.ResetParams();
503 }
504}
505
deadbeefcbecd352015-09-23 11:50:27 -0700506void BaseChannel::SetReadyToSend(bool rtcp, bool ready) {
507 if (rtcp) {
508 rtcp_ready_to_send_ = ready;
509 } else {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000510 rtp_ready_to_send_ = ready;
511 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000512
deadbeefcbecd352015-09-23 11:50:27 -0700513 if (rtp_ready_to_send_ &&
514 // In the case of rtcp mux |rtcp_transport_channel_| will be null.
515 (rtcp_ready_to_send_ || !rtcp_transport_channel_)) {
torbjornga81a42f2015-09-23 02:16:58 -0700516 // Notify the MediaChannel when both rtp and rtcp channel can send.
517 media_channel_->OnReadyToSend(true);
deadbeefcbecd352015-09-23 11:50:27 -0700518 } else {
519 // Notify the MediaChannel when either rtp or rtcp channel can't send.
520 media_channel_->OnReadyToSend(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000521 }
522}
523
524bool BaseChannel::PacketIsRtcp(const TransportChannel* channel,
525 const char* data, size_t len) {
526 return (channel == rtcp_transport_channel_ ||
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000527 rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528}
529
stefanc1aeaf02015-10-15 07:26:07 -0700530bool BaseChannel::SendPacket(bool rtcp,
531 rtc::Buffer* packet,
532 const rtc::PacketOptions& options) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000533 // SendPacket gets called from MediaEngine, typically on an encoder thread.
534 // If the thread is not our worker thread, we will post to our worker
535 // so that the real work happens on our worker. This avoids us having to
536 // synchronize access to all the pieces of the send path, including
537 // SRTP and the inner workings of the transport channels.
538 // The only downside is that we can't return a proper failure code if
539 // needed. Since UDP is unreliable anyway, this should be a non-issue.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000540 if (rtc::Thread::Current() != worker_thread_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000541 // Avoid a copy by transferring the ownership of the packet data.
542 int message_id = (!rtcp) ? MSG_RTPPACKET : MSG_RTCPPACKET;
543 PacketMessageData* data = new PacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800544 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700545 data->options = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000546 worker_thread_->Post(this, message_id, data);
547 return true;
548 }
549
550 // Now that we are on the correct thread, ensure we have a place to send this
551 // packet before doing anything. (We might get RTCP packets that we don't
552 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
553 // transport.
554 TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
555 transport_channel_ : rtcp_transport_channel_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000556 if (!channel || !channel->writable()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000557 return false;
558 }
559
560 // Protect ourselves against crazy data.
561 if (!ValidPacket(rtcp, packet)) {
562 LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000563 << PacketType(rtcp)
564 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000565 return false;
566 }
567
stefanc1aeaf02015-10-15 07:26:07 -0700568 rtc::PacketOptions updated_options;
569 updated_options = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000570 // Protect if needed.
571 if (srtp_filter_.IsActive()) {
572 bool res;
Karl Wibergc56ac1e2015-05-04 14:54:55 +0200573 uint8_t* data = packet->data();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000574 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000575 if (!rtcp) {
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000576 // If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
577 // inside libsrtp for a RTP packet. A external HMAC module will be writing
578 // a fake HMAC value. This is ONLY done for a RTP packet.
579 // Socket layer will update rtp sendtime extension header if present in
580 // packet with current time before updating the HMAC.
581#if !defined(ENABLE_EXTERNAL_AUTH)
582 res = srtp_filter_.ProtectRtp(
583 data, len, static_cast<int>(packet->capacity()), &len);
584#else
stefanc1aeaf02015-10-15 07:26:07 -0700585 updated_options.packet_time_params.rtp_sendtime_extension_id =
henrike@webrtc.org05376342014-03-10 15:53:12 +0000586 rtp_abs_sendtime_extn_id_;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000587 res = srtp_filter_.ProtectRtp(
588 data, len, static_cast<int>(packet->capacity()), &len,
stefanc1aeaf02015-10-15 07:26:07 -0700589 &updated_options.packet_time_params.srtp_packet_index);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000590 // If protection succeeds, let's get auth params from srtp.
591 if (res) {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200592 uint8_t* auth_key = NULL;
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000593 int key_len;
594 res = srtp_filter_.GetRtpAuthParams(
stefanc1aeaf02015-10-15 07:26:07 -0700595 &auth_key, &key_len,
596 &updated_options.packet_time_params.srtp_auth_tag_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000597 if (res) {
stefanc1aeaf02015-10-15 07:26:07 -0700598 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
599 updated_options.packet_time_params.srtp_auth_key.assign(
600 auth_key, auth_key + key_len);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +0000601 }
602 }
603#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000604 if (!res) {
605 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200606 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000607 GetRtpSeqNum(data, len, &seq_num);
608 GetRtpSsrc(data, len, &ssrc);
609 LOG(LS_ERROR) << "Failed to protect " << content_name_
610 << " RTP packet: size=" << len
611 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
612 return false;
613 }
614 } else {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000615 res = srtp_filter_.ProtectRtcp(data, len,
616 static_cast<int>(packet->capacity()),
617 &len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000618 if (!res) {
619 int type = -1;
620 GetRtcpType(data, len, &type);
621 LOG(LS_ERROR) << "Failed to protect " << content_name_
622 << " RTCP packet: size=" << len << ", type=" << type;
623 return false;
624 }
625 }
626
627 // Update the length of the packet now that we've added the auth tag.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000628 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000629 } else if (secure_required_) {
630 // This is a double check for something that supposedly can't happen.
631 LOG(LS_ERROR) << "Can't send outgoing " << PacketType(rtcp)
632 << " packet when SRTP is inactive and crypto is required";
633
634 ASSERT(false);
635 return false;
636 }
637
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000638 // Bon voyage.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000639 int ret =
stefanc1aeaf02015-10-15 07:26:07 -0700640 channel->SendPacket(packet->data<char>(), packet->size(), updated_options,
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000641 (secure() && secure_dtls()) ? PF_SRTP_BYPASS : 0);
642 if (ret != static_cast<int>(packet->size())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000643 if (channel->GetError() == EWOULDBLOCK) {
644 LOG(LS_WARNING) << "Got EWOULDBLOCK from socket.";
deadbeefcbecd352015-09-23 11:50:27 -0700645 SetReadyToSend(rtcp, false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000646 }
647 return false;
648 }
649 return true;
650}
651
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000652bool BaseChannel::WantsPacket(bool rtcp, rtc::Buffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000653 // Protect ourselves against crazy data.
654 if (!ValidPacket(rtcp, packet)) {
655 LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000656 << PacketType(rtcp)
657 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000658 return false;
659 }
pbos482b12e2015-11-16 10:19:58 -0800660 if (rtcp) {
661 // Permit all (seemingly valid) RTCP packets.
662 return true;
663 }
664 // Check whether we handle this payload.
665 return bundle_filter_.DemuxPacket(packet->data<uint8_t>(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666}
667
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000668void BaseChannel::HandlePacket(bool rtcp, rtc::Buffer* packet,
669 const rtc::PacketTime& packet_time) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000670 if (!WantsPacket(rtcp, packet)) {
671 return;
672 }
673
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000674 // We are only interested in the first rtp packet because that
675 // indicates the media has started flowing.
676 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000677 has_received_packet_ = true;
678 signaling_thread()->Post(this, MSG_FIRSTPACKETRECEIVED);
679 }
680
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681 // Unprotect the packet, if needed.
682 if (srtp_filter_.IsActive()) {
Karl Wiberg94784372015-04-20 14:03:07 +0200683 char* data = packet->data<char>();
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000684 int len = static_cast<int>(packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000685 bool res;
686 if (!rtcp) {
687 res = srtp_filter_.UnprotectRtp(data, len, &len);
688 if (!res) {
689 int seq_num = -1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200690 uint32_t ssrc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000691 GetRtpSeqNum(data, len, &seq_num);
692 GetRtpSsrc(data, len, &ssrc);
693 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
694 << " RTP packet: size=" << len
695 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
696 return;
697 }
698 } else {
699 res = srtp_filter_.UnprotectRtcp(data, len, &len);
700 if (!res) {
701 int type = -1;
702 GetRtcpType(data, len, &type);
703 LOG(LS_ERROR) << "Failed to unprotect " << content_name_
704 << " RTCP packet: size=" << len << ", type=" << type;
705 return;
706 }
707 }
708
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000709 packet->SetSize(len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000710 } else if (secure_required_) {
711 // Our session description indicates that SRTP is required, but we got a
712 // packet before our SRTP filter is active. This means either that
713 // a) we got SRTP packets before we received the SDES keys, in which case
714 // we can't decrypt it anyway, or
715 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
716 // channels, so we haven't yet extracted keys, even if DTLS did complete
717 // on the channel that the packets are being sent on. It's really good
718 // practice to wait for both RTP and RTCP to be good to go before sending
719 // media, to prevent weird failure modes, so it's fine for us to just eat
720 // packets here. This is all sidestepped if RTCP mux is used anyway.
721 LOG(LS_WARNING) << "Can't process incoming " << PacketType(rtcp)
722 << " packet when SRTP is inactive and crypto is required";
723 return;
724 }
725
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000726 // Push it down to the media channel.
727 if (!rtcp) {
wu@webrtc.orga9890802013-12-13 00:21:03 +0000728 media_channel_->OnPacketReceived(packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000729 } else {
wu@webrtc.orga9890802013-12-13 00:21:03 +0000730 media_channel_->OnRtcpReceived(packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000731 }
732}
733
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000734bool BaseChannel::PushdownLocalDescription(
735 const SessionDescription* local_desc, ContentAction action,
736 std::string* error_desc) {
737 const ContentInfo* content_info = GetFirstContent(local_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000738 const MediaContentDescription* content_desc =
739 GetContentDescription(content_info);
740 if (content_desc && content_info && !content_info->rejected &&
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000741 !SetLocalContent(content_desc, action, error_desc)) {
742 LOG(LS_ERROR) << "Failure in SetLocalContent with action " << action;
743 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000744 }
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000745 return true;
746}
747
748bool BaseChannel::PushdownRemoteDescription(
749 const SessionDescription* remote_desc, ContentAction action,
750 std::string* error_desc) {
751 const ContentInfo* content_info = GetFirstContent(remote_desc);
752 const MediaContentDescription* content_desc =
753 GetContentDescription(content_info);
754 if (content_desc && content_info && !content_info->rejected &&
755 !SetRemoteContent(content_desc, action, error_desc)) {
756 LOG(LS_ERROR) << "Failure in SetRemoteContent with action " << action;
757 return false;
758 }
759 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000760}
761
762void BaseChannel::EnableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000763 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000764 if (enabled_)
765 return;
766
767 LOG(LS_INFO) << "Channel enabled";
768 enabled_ = true;
769 ChangeState();
770}
771
772void BaseChannel::DisableMedia_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000773 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000774 if (!enabled_)
775 return;
776
777 LOG(LS_INFO) << "Channel disabled";
778 enabled_ = false;
779 ChangeState();
780}
781
deadbeefcbecd352015-09-23 11:50:27 -0700782void BaseChannel::UpdateWritableState_w() {
783 if (transport_channel_ && transport_channel_->writable() &&
784 (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
785 ChannelWritable_w();
786 } else {
787 ChannelNotWritable_w();
788 }
789}
790
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000791void BaseChannel::ChannelWritable_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000792 ASSERT(worker_thread_ == rtc::Thread::Current());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800793 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000794 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800795 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000796
deadbeefcbecd352015-09-23 11:50:27 -0700797 LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000798 << (was_ever_writable_ ? "" : " for the first time");
799
800 std::vector<ConnectionInfo> infos;
801 transport_channel_->GetStats(&infos);
802 for (std::vector<ConnectionInfo>::const_iterator it = infos.begin();
803 it != infos.end(); ++it) {
804 if (it->best_connection) {
805 LOG(LS_INFO) << "Using " << it->local_candidate.ToSensitiveString()
806 << "->" << it->remote_candidate.ToSensitiveString();
807 break;
808 }
809 }
810
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000811 was_ever_writable_ = true;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800812 MaybeSetupDtlsSrtp_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000813 writable_ = true;
814 ChangeState();
815}
816
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +0000817void BaseChannel::SignalDtlsSetupFailure_w(bool rtcp) {
818 ASSERT(worker_thread() == rtc::Thread::Current());
819 signaling_thread()->Invoke<void>(Bind(
820 &BaseChannel::SignalDtlsSetupFailure_s, this, rtcp));
821}
822
823void BaseChannel::SignalDtlsSetupFailure_s(bool rtcp) {
824 ASSERT(signaling_thread() == rtc::Thread::Current());
825 SignalDtlsSetupFailure(this, rtcp);
826}
827
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800828bool BaseChannel::SetDtlsSrtpCryptoSuites(TransportChannel* tc, bool rtcp) {
829 std::vector<int> crypto_suites;
830 // We always use the default SRTP crypto suites for RTCP, but we may use
831 // different crypto suites for RTP depending on the media type.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000832 if (!rtcp) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800833 GetSrtpCryptoSuites(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000834 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800835 GetDefaultSrtpCryptoSuites(&crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000836 }
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800837 return tc->SetSrtpCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000838}
839
840bool BaseChannel::ShouldSetupDtlsSrtp() const {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800841 // Since DTLS is applied to all channels, checking RTP should be enough.
842 return transport_channel_ && transport_channel_->IsDtlsActive();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000843}
844
845// This function returns true if either DTLS-SRTP is not in use
846// *or* DTLS-SRTP is successfully set up.
847bool BaseChannel::SetupDtlsSrtp(bool rtcp_channel) {
848 bool ret = false;
849
deadbeefcbecd352015-09-23 11:50:27 -0700850 TransportChannel* channel =
851 rtcp_channel ? rtcp_transport_channel_ : transport_channel_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000852
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800853 RTC_DCHECK(channel->IsDtlsActive());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000854
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800855 int selected_crypto_suite;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000856
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800857 if (!channel->GetSrtpCryptoSuite(&selected_crypto_suite)) {
858 LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000859 return false;
860 }
861
862 LOG(LS_INFO) << "Installing keys from DTLS-SRTP on "
863 << content_name() << " "
864 << PacketType(rtcp_channel);
865
866 // OK, we're now doing DTLS (RFC 5764)
867 std::vector<unsigned char> dtls_buffer(SRTP_MASTER_KEY_KEY_LEN * 2 +
868 SRTP_MASTER_KEY_SALT_LEN * 2);
869
870 // RFC 5705 exporter using the RFC 5764 parameters
871 if (!channel->ExportKeyingMaterial(
872 kDtlsSrtpExporterLabel,
873 NULL, 0, false,
874 &dtls_buffer[0], dtls_buffer.size())) {
875 LOG(LS_WARNING) << "DTLS-SRTP key export failed";
876 ASSERT(false); // This should never happen
877 return false;
878 }
879
880 // Sync up the keys with the DTLS-SRTP interface
881 std::vector<unsigned char> client_write_key(SRTP_MASTER_KEY_KEY_LEN +
882 SRTP_MASTER_KEY_SALT_LEN);
883 std::vector<unsigned char> server_write_key(SRTP_MASTER_KEY_KEY_LEN +
884 SRTP_MASTER_KEY_SALT_LEN);
885 size_t offset = 0;
886 memcpy(&client_write_key[0], &dtls_buffer[offset],
887 SRTP_MASTER_KEY_KEY_LEN);
888 offset += SRTP_MASTER_KEY_KEY_LEN;
889 memcpy(&server_write_key[0], &dtls_buffer[offset],
890 SRTP_MASTER_KEY_KEY_LEN);
891 offset += SRTP_MASTER_KEY_KEY_LEN;
892 memcpy(&client_write_key[SRTP_MASTER_KEY_KEY_LEN],
893 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
894 offset += SRTP_MASTER_KEY_SALT_LEN;
895 memcpy(&server_write_key[SRTP_MASTER_KEY_KEY_LEN],
896 &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
897
898 std::vector<unsigned char> *send_key, *recv_key;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000899 rtc::SSLRole role;
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000900 if (!channel->GetSslRole(&role)) {
901 LOG(LS_WARNING) << "GetSslRole failed";
902 return false;
903 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000904
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000905 if (role == rtc::SSL_SERVER) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000906 send_key = &server_write_key;
907 recv_key = &client_write_key;
908 } else {
909 send_key = &client_write_key;
910 recv_key = &server_write_key;
911 }
912
913 if (rtcp_channel) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800914 ret = srtp_filter_.SetRtcpParams(selected_crypto_suite, &(*send_key)[0],
915 static_cast<int>(send_key->size()),
916 selected_crypto_suite, &(*recv_key)[0],
917 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000918 } else {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800919 ret = srtp_filter_.SetRtpParams(selected_crypto_suite, &(*send_key)[0],
920 static_cast<int>(send_key->size()),
921 selected_crypto_suite, &(*recv_key)[0],
922 static_cast<int>(recv_key->size()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000923 }
924
925 if (!ret)
926 LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
927 else
928 dtls_keyed_ = true;
929
930 return ret;
931}
932
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800933void BaseChannel::MaybeSetupDtlsSrtp_w() {
934 if (srtp_filter_.IsActive()) {
935 return;
936 }
937
938 if (!ShouldSetupDtlsSrtp()) {
939 return;
940 }
941
942 if (!SetupDtlsSrtp(false)) {
943 SignalDtlsSetupFailure_w(false);
944 return;
945 }
946
947 if (rtcp_transport_channel_) {
948 if (!SetupDtlsSrtp(true)) {
949 SignalDtlsSetupFailure_w(true);
950 return;
951 }
952 }
953}
954
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000955void BaseChannel::ChannelNotWritable_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000956 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000957 if (!writable_)
958 return;
959
deadbeefcbecd352015-09-23 11:50:27 -0700960 LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000961 writable_ = false;
962 ChangeState();
963}
964
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700965bool BaseChannel::SetRtpTransportParameters_w(
966 const MediaContentDescription* content,
967 ContentAction action,
968 ContentSource src,
969 std::string* error_desc) {
970 if (action == CA_UPDATE) {
971 // These parameters never get changed by a CA_UDPATE.
972 return true;
973 }
974
975 // Cache secure_required_ for belt and suspenders check on SendPacket
976 if (src == CS_LOCAL) {
977 set_secure_required(content->crypto_required() != CT_NONE);
978 }
979
980 if (!SetSrtp_w(content->cryptos(), action, src, error_desc)) {
981 return false;
982 }
983
984 if (!SetRtcpMux_w(content->rtcp_mux(), action, src, error_desc)) {
985 return false;
986 }
987
988 return true;
989}
990
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000991// |dtls| will be set to true if DTLS is active for transport channel and
992// crypto is empty.
993bool BaseChannel::CheckSrtpConfig(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000994 bool* dtls,
995 std::string* error_desc) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000996 *dtls = transport_channel_->IsDtlsActive();
997 if (*dtls && !cryptos.empty()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000998 SafeSetError("Cryptos must be empty when DTLS is active.",
999 error_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001000 return false;
1001 }
1002 return true;
1003}
1004
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001005bool BaseChannel::SetSrtp_w(const std::vector<CryptoParams>& cryptos,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001006 ContentAction action,
1007 ContentSource src,
1008 std::string* error_desc) {
1009 if (action == CA_UPDATE) {
1010 // no crypto params.
1011 return true;
1012 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001013 bool ret = false;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001014 bool dtls = false;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001015 ret = CheckSrtpConfig(cryptos, &dtls, error_desc);
1016 if (!ret) {
1017 return false;
1018 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001019 switch (action) {
1020 case CA_OFFER:
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001021 // If DTLS is already active on the channel, we could be renegotiating
1022 // here. We don't update the srtp filter.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001023 if (!dtls) {
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001024 ret = srtp_filter_.SetOffer(cryptos, src);
1025 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001026 break;
1027 case CA_PRANSWER:
1028 // If we're doing DTLS-SRTP, we don't want to update the filter
1029 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001030 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001031 ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
1032 }
1033 break;
1034 case CA_ANSWER:
1035 // If we're doing DTLS-SRTP, we don't want to update the filter
1036 // with an answer, because we already have SRTP parameters.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001037 if (!dtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001038 ret = srtp_filter_.SetAnswer(cryptos, src);
1039 }
1040 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001041 default:
1042 break;
1043 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001044 if (!ret) {
1045 SafeSetError("Failed to setup SRTP filter.", error_desc);
1046 return false;
1047 }
1048 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001049}
1050
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001051void BaseChannel::ActivateRtcpMux() {
1052 worker_thread_->Invoke<void>(Bind(
1053 &BaseChannel::ActivateRtcpMux_w, this));
1054}
1055
1056void BaseChannel::ActivateRtcpMux_w() {
1057 if (!rtcp_mux_filter_.IsActive()) {
1058 rtcp_mux_filter_.SetActive();
guoweis46383312015-12-17 16:45:59 -08001059 set_rtcp_transport_channel(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001060 rtcp_transport_enabled_ = false;
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07001061 }
1062}
1063
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001064bool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001065 ContentSource src,
1066 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001067 bool ret = false;
1068 switch (action) {
1069 case CA_OFFER:
1070 ret = rtcp_mux_filter_.SetOffer(enable, src);
1071 break;
1072 case CA_PRANSWER:
1073 ret = rtcp_mux_filter_.SetProvisionalAnswer(enable, src);
1074 break;
1075 case CA_ANSWER:
1076 ret = rtcp_mux_filter_.SetAnswer(enable, src);
1077 if (ret && rtcp_mux_filter_.IsActive()) {
1078 // We activated RTCP mux, close down the RTCP transport.
deadbeefcbecd352015-09-23 11:50:27 -07001079 LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
1080 << " by destroying RTCP transport channel for "
1081 << transport_name();
guoweis46383312015-12-17 16:45:59 -08001082 set_rtcp_transport_channel(nullptr, true);
deadbeefcbecd352015-09-23 11:50:27 -07001083 rtcp_transport_enabled_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001084 }
1085 break;
1086 case CA_UPDATE:
1087 // No RTCP mux info.
1088 ret = true;
Henrik Kjellander7c027b62015-04-22 13:21:30 +02001089 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001090 default:
1091 break;
1092 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001093 if (!ret) {
1094 SafeSetError("Failed to setup RTCP mux filter.", error_desc);
1095 return false;
1096 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001097 // |rtcp_mux_filter_| can be active if |action| is CA_PRANSWER or
1098 // CA_ANSWER, but we only want to tear down the RTCP transport channel if we
1099 // received a final answer.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001100 if (rtcp_mux_filter_.IsActive()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001101 // If the RTP transport is already writable, then so are we.
1102 if (transport_channel_->writable()) {
1103 ChannelWritable_w();
1104 }
1105 }
1106
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001107 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001108}
1109
1110bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001111 ASSERT(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -08001112 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001113}
1114
Peter Boström0c4e06b2015-10-07 12:23:21 +02001115bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001116 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001117 return media_channel()->RemoveRecvStream(ssrc);
1118}
1119
1120bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001121 ContentAction action,
1122 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001123 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1124 action == CA_PRANSWER || action == CA_UPDATE))
1125 return false;
1126
1127 // If this is an update, streams only contain streams that have changed.
1128 if (action == CA_UPDATE) {
1129 for (StreamParamsVec::const_iterator it = streams.begin();
1130 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001131 const StreamParams* existing_stream =
1132 GetStreamByIds(local_streams_, it->groupid, it->id);
1133 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001134 if (media_channel()->AddSendStream(*it)) {
1135 local_streams_.push_back(*it);
1136 LOG(LS_INFO) << "Add send stream ssrc: " << it->first_ssrc();
1137 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001138 std::ostringstream desc;
1139 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1140 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001141 return false;
1142 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001143 } else if (existing_stream && !it->has_ssrcs()) {
1144 if (!media_channel()->RemoveSendStream(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001145 std::ostringstream desc;
1146 desc << "Failed to remove send stream with ssrc "
1147 << it->first_ssrc() << ".";
1148 SafeSetError(desc.str(), error_desc);
1149 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001150 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001151 RemoveStreamBySsrc(&local_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001152 } else {
1153 LOG(LS_WARNING) << "Ignore unsupported stream update";
1154 }
1155 }
1156 return true;
1157 }
1158 // Else streams are all the streams we want to send.
1159
1160 // Check for streams that have been removed.
1161 bool ret = true;
1162 for (StreamParamsVec::const_iterator it = local_streams_.begin();
1163 it != local_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001164 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001165 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001166 std::ostringstream desc;
1167 desc << "Failed to remove send stream with ssrc "
1168 << it->first_ssrc() << ".";
1169 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001170 ret = false;
1171 }
1172 }
1173 }
1174 // Check for new streams.
1175 for (StreamParamsVec::const_iterator it = streams.begin();
1176 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001177 if (!GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001178 if (media_channel()->AddSendStream(*it)) {
stefanc1aeaf02015-10-15 07:26:07 -07001179 LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001180 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001181 std::ostringstream desc;
1182 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
1183 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001184 ret = false;
1185 }
1186 }
1187 }
1188 local_streams_ = streams;
1189 return ret;
1190}
1191
1192bool BaseChannel::UpdateRemoteStreams_w(
1193 const std::vector<StreamParams>& streams,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001194 ContentAction action,
1195 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001196 if (!VERIFY(action == CA_OFFER || action == CA_ANSWER ||
1197 action == CA_PRANSWER || action == CA_UPDATE))
1198 return false;
1199
1200 // If this is an update, streams only contain streams that have changed.
1201 if (action == CA_UPDATE) {
1202 for (StreamParamsVec::const_iterator it = streams.begin();
1203 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001204 const StreamParams* existing_stream =
1205 GetStreamByIds(remote_streams_, it->groupid, it->id);
1206 if (!existing_stream && it->has_ssrcs()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001207 if (AddRecvStream_w(*it)) {
1208 remote_streams_.push_back(*it);
1209 LOG(LS_INFO) << "Add remote stream ssrc: " << it->first_ssrc();
1210 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001211 std::ostringstream desc;
1212 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1213 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001214 return false;
1215 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001216 } else if (existing_stream && !it->has_ssrcs()) {
1217 if (!RemoveRecvStream_w(existing_stream->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001218 std::ostringstream desc;
1219 desc << "Failed to remove remote stream with ssrc "
1220 << it->first_ssrc() << ".";
1221 SafeSetError(desc.str(), error_desc);
1222 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001223 }
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001224 RemoveStreamBySsrc(&remote_streams_, existing_stream->first_ssrc());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001225 } else {
1226 LOG(LS_WARNING) << "Ignore unsupported stream update."
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001227 << " Stream exists? " << (existing_stream != nullptr)
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001228 << " new stream = " << it->ToString();
1229 }
1230 }
1231 return true;
1232 }
1233 // Else streams are all the streams we want to receive.
1234
1235 // Check for streams that have been removed.
1236 bool ret = true;
1237 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
1238 it != remote_streams_.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001239 if (!GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001240 if (!RemoveRecvStream_w(it->first_ssrc())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001241 std::ostringstream desc;
1242 desc << "Failed to remove remote stream with ssrc "
1243 << it->first_ssrc() << ".";
1244 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001245 ret = false;
1246 }
1247 }
1248 }
1249 // Check for new streams.
1250 for (StreamParamsVec::const_iterator it = streams.begin();
1251 it != streams.end(); ++it) {
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +00001252 if (!GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001253 if (AddRecvStream_w(*it)) {
1254 LOG(LS_INFO) << "Add remote ssrc: " << it->ssrcs[0];
1255 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001256 std::ostringstream desc;
1257 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
1258 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001259 ret = false;
1260 }
1261 }
1262 }
1263 remote_streams_ = streams;
1264 return ret;
1265}
1266
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001267void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension(
1268 const std::vector<RtpHeaderExtension>& extensions) {
1269 const RtpHeaderExtension* send_time_extension =
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001270 FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
henrike@webrtc.orgd43aa9d2014-02-21 23:43:24 +00001271 rtp_abs_sendtime_extn_id_ =
1272 send_time_extension ? send_time_extension->id : -1;
1273}
1274
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001275void BaseChannel::OnMessage(rtc::Message *pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +01001276 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001277 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001278 case MSG_RTPPACKET:
1279 case MSG_RTCPPACKET: {
1280 PacketMessageData* data = static_cast<PacketMessageData*>(pmsg->pdata);
stefanc1aeaf02015-10-15 07:26:07 -07001281 SendPacket(pmsg->message_id == MSG_RTCPPACKET, &data->packet,
1282 data->options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001283 delete data; // because it is Posted
1284 break;
1285 }
1286 case MSG_FIRSTPACKETRECEIVED: {
1287 SignalFirstPacketReceived(this);
1288 break;
1289 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001290 }
1291}
1292
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001293void BaseChannel::FlushRtcpMessages() {
1294 // Flush all remaining RTCP messages. This should only be called in
1295 // destructor.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001296 ASSERT(rtc::Thread::Current() == worker_thread_);
1297 rtc::MessageList rtcp_messages;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001298 worker_thread_->Clear(this, MSG_RTCPPACKET, &rtcp_messages);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001299 for (rtc::MessageList::iterator it = rtcp_messages.begin();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001300 it != rtcp_messages.end(); ++it) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001301 worker_thread_->Send(this, MSG_RTCPPACKET, it->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001302 }
1303}
1304
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001305VoiceChannel::VoiceChannel(rtc::Thread* thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306 MediaEngineInterface* media_engine,
1307 VoiceMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001308 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001309 const std::string& content_name,
1310 bool rtcp)
deadbeefcbecd352015-09-23 11:50:27 -07001311 : BaseChannel(thread,
1312 media_channel,
1313 transport_controller,
1314 content_name,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001315 rtcp),
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001316 media_engine_(media_engine),
deadbeefcbecd352015-09-23 11:50:27 -07001317 received_media_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001318
1319VoiceChannel::~VoiceChannel() {
1320 StopAudioMonitor();
1321 StopMediaMonitor();
1322 // this can't be done in the base class, since it calls a virtual
1323 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001324 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001325}
1326
1327bool VoiceChannel::Init() {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +00001328 if (!BaseChannel::Init()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001329 return false;
1330 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001331 return true;
1332}
1333
Peter Boström0c4e06b2015-10-07 12:23:21 +02001334bool VoiceChannel::SetAudioSend(uint32_t ssrc,
solenbergdfc8f4f2015-10-01 02:31:10 -07001335 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001336 const AudioOptions* options,
1337 AudioRenderer* renderer) {
deadbeefcbecd352015-09-23 11:50:27 -07001338 return InvokeOnWorker(Bind(&VoiceMediaChannel::SetAudioSend, media_channel(),
solenbergdfc8f4f2015-10-01 02:31:10 -07001339 ssrc, enable, options, renderer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001340}
1341
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001342// TODO(juberti): Handle early media the right way. We should get an explicit
1343// ringing message telling us to start playing local ringback, which we cancel
1344// if any early media actually arrives. For now, we do the opposite, which is
1345// to wait 1 second for early media, and start playing local ringback if none
1346// arrives.
1347void VoiceChannel::SetEarlyMedia(bool enable) {
1348 if (enable) {
1349 // Start the early media timeout
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001350 worker_thread()->PostDelayed(kEarlyMediaTimeout, this,
1351 MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001352 } else {
1353 // Stop the timeout if currently going.
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001354 worker_thread()->Clear(this, MSG_EARLYMEDIATIMEOUT);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001355 }
1356}
1357
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001358bool VoiceChannel::CanInsertDtmf() {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001359 return InvokeOnWorker(Bind(&VoiceMediaChannel::CanInsertDtmf,
1360 media_channel()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001361}
1362
Peter Boström0c4e06b2015-10-07 12:23:21 +02001363bool VoiceChannel::InsertDtmf(uint32_t ssrc,
1364 int event_code,
solenberg1d63dd02015-12-02 12:35:09 -08001365 int duration) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001366 return InvokeOnWorker(Bind(&VoiceChannel::InsertDtmf_w, this,
solenberg1d63dd02015-12-02 12:35:09 -08001367 ssrc, event_code, duration));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001368}
1369
solenberg4bac9c52015-10-09 02:32:53 -07001370bool VoiceChannel::SetOutputVolume(uint32_t ssrc, double volume) {
1371 return InvokeOnWorker(Bind(&VoiceMediaChannel::SetOutputVolume,
1372 media_channel(), ssrc, volume));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001373}
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001374
Tommif888bb52015-12-12 01:37:01 +01001375void VoiceChannel::SetRawAudioSink(
1376 uint32_t ssrc,
deadbeef2d110be2016-01-13 12:00:26 -08001377 rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) {
1378 // We need to work around Bind's lack of support for scoped_ptr and ownership
1379 // passing. So we invoke to our own little routine that gets a pointer to
1380 // our local variable. This is OK since we're synchronously invoking.
1381 InvokeOnWorker(Bind(&SetRawAudioSink_w, media_channel(), ssrc, &sink));
Tommif888bb52015-12-12 01:37:01 +01001382}
1383
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001384bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001385 return InvokeOnWorker(Bind(&VoiceMediaChannel::GetStats,
1386 media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001387}
1388
1389void VoiceChannel::StartMediaMonitor(int cms) {
1390 media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001391 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001392 media_monitor_->SignalUpdate.connect(
1393 this, &VoiceChannel::OnMediaMonitorUpdate);
1394 media_monitor_->Start(cms);
1395}
1396
1397void VoiceChannel::StopMediaMonitor() {
1398 if (media_monitor_) {
1399 media_monitor_->Stop();
1400 media_monitor_->SignalUpdate.disconnect(this);
1401 media_monitor_.reset();
1402 }
1403}
1404
1405void VoiceChannel::StartAudioMonitor(int cms) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001406 audio_monitor_.reset(new AudioMonitor(this, rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001407 audio_monitor_
1408 ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
1409 audio_monitor_->Start(cms);
1410}
1411
1412void VoiceChannel::StopAudioMonitor() {
1413 if (audio_monitor_) {
1414 audio_monitor_->Stop();
1415 audio_monitor_.reset();
1416 }
1417}
1418
1419bool VoiceChannel::IsAudioMonitorRunning() const {
1420 return (audio_monitor_.get() != NULL);
1421}
1422
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001423int VoiceChannel::GetInputLevel_w() {
Fredrik Solenberg0c022642015-08-05 12:25:22 +02001424 return media_engine_->GetInputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001425}
1426
1427int VoiceChannel::GetOutputLevel_w() {
1428 return media_channel()->GetOutputLevel();
1429}
1430
1431void VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
1432 media_channel()->GetActiveStreams(actives);
1433}
1434
1435void VoiceChannel::OnChannelRead(TransportChannel* channel,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001436 const char* data, size_t len,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001437 const rtc::PacketTime& packet_time,
wu@webrtc.orga9890802013-12-13 00:21:03 +00001438 int flags) {
1439 BaseChannel::OnChannelRead(channel, data, len, packet_time, flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001440
1441 // Set a flag when we've received an RTP packet. If we're waiting for early
1442 // media, this will disable the timeout.
1443 if (!received_media_ && !PacketIsRtcp(channel, data, len)) {
1444 received_media_ = true;
1445 }
1446}
1447
1448void VoiceChannel::ChangeState() {
1449 // Render incoming data if we're the active call, and we have the local
1450 // content. We receive data on the default channel and multiplexed streams.
1451 bool recv = IsReadyToReceive();
solenberg5b14b422015-10-01 04:10:31 -07001452 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001453
1454 // Send outgoing data if we're the active call, we have the remote content,
1455 // and we have had some form of connectivity.
1456 bool send = IsReadyToSend();
1457 SendFlags send_flag = send ? SEND_MICROPHONE : SEND_NOTHING;
1458 if (!media_channel()->SetSend(send_flag)) {
1459 LOG(LS_ERROR) << "Failed to SetSend " << send_flag << " on voice channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001460 }
1461
1462 LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
1463}
1464
1465const ContentInfo* VoiceChannel::GetFirstContent(
1466 const SessionDescription* sdesc) {
1467 return GetFirstAudioContent(sdesc);
1468}
1469
1470bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001471 ContentAction action,
1472 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001473 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001474 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001475 LOG(LS_INFO) << "Setting local voice description";
1476
1477 const AudioContentDescription* audio =
1478 static_cast<const AudioContentDescription*>(content);
1479 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001480 if (!audio) {
1481 SafeSetError("Can't find audio content in local description.", error_desc);
1482 return false;
1483 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001484
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001485 if (!SetRtpTransportParameters_w(content, action, CS_LOCAL, error_desc)) {
1486 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001487 }
1488
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001489 AudioRecvParameters recv_params = last_recv_params_;
1490 RtpParametersFromMediaDescription(audio, &recv_params);
1491 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001492 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001493 error_desc);
1494 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001495 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001496 for (const AudioCodec& codec : audio->codecs()) {
1497 bundle_filter()->AddPayloadType(codec.id);
1498 }
1499 last_recv_params_ = recv_params;
1500
1501 // TODO(pthatcher): Move local streams into AudioSendParameters, and
1502 // only give it to the media channel once we have a remote
1503 // description too (without a remote description, we won't be able
1504 // to send them anyway).
1505 if (!UpdateLocalStreams_w(audio->streams(), action, error_desc)) {
1506 SafeSetError("Failed to set local audio description streams.", error_desc);
1507 return false;
1508 }
1509
1510 set_local_content_direction(content->direction());
1511 ChangeState();
1512 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001513}
1514
1515bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001516 ContentAction action,
1517 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001518 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001519 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001520 LOG(LS_INFO) << "Setting remote voice description";
1521
1522 const AudioContentDescription* audio =
1523 static_cast<const AudioContentDescription*>(content);
1524 ASSERT(audio != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001525 if (!audio) {
1526 SafeSetError("Can't find audio content in remote description.", error_desc);
1527 return false;
1528 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001529
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001530 if (!SetRtpTransportParameters_w(content, action, CS_REMOTE, error_desc)) {
1531 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001532 }
1533
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001534 AudioSendParameters send_params = last_send_params_;
1535 RtpSendParametersFromMediaDescription(audio, &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001536 if (audio->agc_minus_10db()) {
Karl Wibergbe579832015-11-10 22:34:18 +01001537 send_params.options.adjust_agc_delta = rtc::Optional<int>(kAgcMinus10db);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001538 }
1539 if (!media_channel()->SetSendParameters(send_params)) {
1540 SafeSetError("Failed to set remote audio description send parameters.",
1541 error_desc);
1542 return false;
1543 }
1544 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001545
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001546 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
1547 // and only give it to the media channel once we have a local
1548 // description too (without a local description, we won't be able to
1549 // recv them anyway).
1550 if (!UpdateRemoteStreams_w(audio->streams(), action, error_desc)) {
1551 SafeSetError("Failed to set remote audio description streams.", error_desc);
1552 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001553 }
1554
Peter Thatcherbfab5cb2015-08-20 17:40:24 -07001555 if (audio->rtp_header_extensions_set()) {
1556 MaybeCacheRtpAbsSendTimeHeaderExtension(audio->rtp_header_extensions());
1557 }
1558
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001559 set_remote_content_direction(content->direction());
1560 ChangeState();
1561 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001562}
1563
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001564void VoiceChannel::HandleEarlyMediaTimeout() {
1565 // This occurs on the main thread, not the worker thread.
1566 if (!received_media_) {
1567 LOG(LS_INFO) << "No early media received before timeout";
1568 SignalEarlyMediaTimeout(this);
1569 }
1570}
1571
Peter Boström0c4e06b2015-10-07 12:23:21 +02001572bool VoiceChannel::InsertDtmf_w(uint32_t ssrc,
1573 int event,
solenberg1d63dd02015-12-02 12:35:09 -08001574 int duration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001575 if (!enabled()) {
1576 return false;
1577 }
solenberg1d63dd02015-12-02 12:35:09 -08001578 return media_channel()->InsertDtmf(ssrc, event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001579}
1580
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001581void VoiceChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001582 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001583 case MSG_EARLYMEDIATIMEOUT:
1584 HandleEarlyMediaTimeout();
1585 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001586 case MSG_CHANNEL_ERROR: {
1587 VoiceChannelErrorMessageData* data =
1588 static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001589 delete data;
1590 break;
1591 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001592 default:
1593 BaseChannel::OnMessage(pmsg);
1594 break;
1595 }
1596}
1597
1598void VoiceChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001599 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001600 SignalConnectionMonitor(this, infos);
1601}
1602
1603void VoiceChannel::OnMediaMonitorUpdate(
1604 VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
1605 ASSERT(media_channel == this->media_channel());
1606 SignalMediaMonitor(this, info);
1607}
1608
1609void VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
1610 const AudioInfo& info) {
1611 SignalAudioMonitor(this, info);
1612}
1613
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001614void VoiceChannel::GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const {
1615 GetSupportedAudioCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001616}
1617
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001618VideoChannel::VideoChannel(rtc::Thread* thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001619 VideoMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001620 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001621 const std::string& content_name,
Fredrik Solenberg7fb711f2015-04-22 15:30:51 +02001622 bool rtcp)
deadbeefcbecd352015-09-23 11:50:27 -07001623 : BaseChannel(thread,
1624 media_channel,
1625 transport_controller,
1626 content_name,
perkjc11b1842016-03-07 17:34:13 -08001627 rtcp) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001628
1629bool VideoChannel::Init() {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +00001630 if (!BaseChannel::Init()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001631 return false;
1632 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001633 return true;
1634}
1635
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001636VideoChannel::~VideoChannel() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001637 StopMediaMonitor();
1638 // this can't be done in the base class, since it calls a virtual
1639 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001640
1641 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001642}
1643
nisse08582ff2016-02-04 01:24:52 -08001644bool VideoChannel::SetSink(uint32_t ssrc,
1645 rtc::VideoSinkInterface<VideoFrame>* sink) {
1646 worker_thread()->Invoke<void>(
1647 Bind(&VideoMediaChannel::SetSink, media_channel(), ssrc, sink));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001648 return true;
1649}
1650
Peter Boström0c4e06b2015-10-07 12:23:21 +02001651bool VideoChannel::SetCapturer(uint32_t ssrc, VideoCapturer* capturer) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001652 return InvokeOnWorker(Bind(&VideoMediaChannel::SetCapturer,
1653 media_channel(), ssrc, capturer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001654}
1655
Peter Boström0c4e06b2015-10-07 12:23:21 +02001656bool VideoChannel::SetVideoSend(uint32_t ssrc,
deadbeefcbecd352015-09-23 11:50:27 -07001657 bool mute,
solenberg1dd98f32015-09-10 01:57:14 -07001658 const VideoOptions* options) {
deadbeefcbecd352015-09-23 11:50:27 -07001659 return InvokeOnWorker(Bind(&VideoMediaChannel::SetVideoSend, media_channel(),
1660 ssrc, mute, options));
solenberg1dd98f32015-09-10 01:57:14 -07001661}
1662
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001663void VideoChannel::ChangeState() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001664 // Send outgoing data if we're the active call, we have the remote content,
1665 // and we have had some form of connectivity.
1666 bool send = IsReadyToSend();
1667 if (!media_channel()->SetSend(send)) {
1668 LOG(LS_ERROR) << "Failed to SetSend on video channel";
1669 // TODO(gangji): Report error back to server.
1670 }
1671
Peter Boström34fbfff2015-09-24 19:20:30 +02001672 LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001673}
1674
pbos@webrtc.org058b1f12015-03-04 08:54:32 +00001675bool VideoChannel::GetStats(VideoMediaInfo* stats) {
1676 return InvokeOnWorker(
1677 Bind(&VideoMediaChannel::GetStats, media_channel(), stats));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001678}
1679
1680void VideoChannel::StartMediaMonitor(int cms) {
1681 media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001682 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001683 media_monitor_->SignalUpdate.connect(
1684 this, &VideoChannel::OnMediaMonitorUpdate);
1685 media_monitor_->Start(cms);
1686}
1687
1688void VideoChannel::StopMediaMonitor() {
1689 if (media_monitor_) {
1690 media_monitor_->Stop();
1691 media_monitor_.reset();
1692 }
1693}
1694
1695const ContentInfo* VideoChannel::GetFirstContent(
1696 const SessionDescription* sdesc) {
1697 return GetFirstVideoContent(sdesc);
1698}
1699
1700bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001701 ContentAction action,
1702 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001703 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001704 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001705 LOG(LS_INFO) << "Setting local video description";
1706
1707 const VideoContentDescription* video =
1708 static_cast<const VideoContentDescription*>(content);
1709 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001710 if (!video) {
1711 SafeSetError("Can't find video content in local description.", error_desc);
1712 return false;
1713 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001714
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001715 if (!SetRtpTransportParameters_w(content, action, CS_LOCAL, error_desc)) {
1716 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001717 }
1718
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001719 VideoRecvParameters recv_params = last_recv_params_;
1720 RtpParametersFromMediaDescription(video, &recv_params);
1721 if (!media_channel()->SetRecvParameters(recv_params)) {
1722 SafeSetError("Failed to set local video description recv parameters.",
1723 error_desc);
1724 return false;
1725 }
1726 for (const VideoCodec& codec : video->codecs()) {
1727 bundle_filter()->AddPayloadType(codec.id);
1728 }
1729 last_recv_params_ = recv_params;
1730
1731 // TODO(pthatcher): Move local streams into VideoSendParameters, and
1732 // only give it to the media channel once we have a remote
1733 // description too (without a remote description, we won't be able
1734 // to send them anyway).
1735 if (!UpdateLocalStreams_w(video->streams(), action, error_desc)) {
1736 SafeSetError("Failed to set local video description streams.", error_desc);
1737 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001738 }
1739
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001740 set_local_content_direction(content->direction());
1741 ChangeState();
1742 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001743}
1744
1745bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001746 ContentAction action,
1747 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001748 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001749 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001750 LOG(LS_INFO) << "Setting remote video description";
1751
1752 const VideoContentDescription* video =
1753 static_cast<const VideoContentDescription*>(content);
1754 ASSERT(video != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001755 if (!video) {
1756 SafeSetError("Can't find video content in remote description.", error_desc);
1757 return false;
1758 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001759
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001760
1761 if (!SetRtpTransportParameters_w(content, action, CS_REMOTE, error_desc)) {
1762 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001763 }
1764
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001765 VideoSendParameters send_params = last_send_params_;
1766 RtpSendParametersFromMediaDescription(video, &send_params);
1767 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08001768 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001769 }
1770 if (!media_channel()->SetSendParameters(send_params)) {
1771 SafeSetError("Failed to set remote video description send parameters.",
1772 error_desc);
1773 return false;
1774 }
1775 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001776
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001777 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
1778 // and only give it to the media channel once we have a local
1779 // description too (without a local description, we won't be able to
1780 // recv them anyway).
1781 if (!UpdateRemoteStreams_w(video->streams(), action, error_desc)) {
1782 SafeSetError("Failed to set remote video description streams.", error_desc);
1783 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001784 }
1785
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001786 if (video->rtp_header_extensions_set()) {
1787 MaybeCacheRtpAbsSendTimeHeaderExtension(video->rtp_header_extensions());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001788 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001789
1790 set_remote_content_direction(content->direction());
1791 ChangeState();
1792 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001793}
1794
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001795void VideoChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001796 switch (pmsg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001797 case MSG_CHANNEL_ERROR: {
1798 const VideoChannelErrorMessageData* data =
1799 static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001800 delete data;
1801 break;
1802 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001803 default:
1804 BaseChannel::OnMessage(pmsg);
1805 break;
1806 }
1807}
1808
1809void VideoChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00001810 ConnectionMonitor* monitor, const std::vector<ConnectionInfo> &infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001811 SignalConnectionMonitor(this, infos);
1812}
1813
1814// TODO(pthatcher): Look into removing duplicate code between
1815// audio, video, and data, perhaps by using templates.
1816void VideoChannel::OnMediaMonitorUpdate(
1817 VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
1818 ASSERT(media_channel == this->media_channel());
1819 SignalMediaMonitor(this, info);
1820}
1821
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08001822void VideoChannel::GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const {
1823 GetSupportedVideoCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001824}
1825
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001826DataChannel::DataChannel(rtc::Thread* thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001827 DataMediaChannel* media_channel,
deadbeefcbecd352015-09-23 11:50:27 -07001828 TransportController* transport_controller,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001829 const std::string& content_name,
1830 bool rtcp)
deadbeefcbecd352015-09-23 11:50:27 -07001831 : BaseChannel(thread,
1832 media_channel,
1833 transport_controller,
1834 content_name,
1835 rtcp),
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00001836 data_channel_type_(cricket::DCT_NONE),
deadbeefcbecd352015-09-23 11:50:27 -07001837 ready_to_send_data_(false) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001838
1839DataChannel::~DataChannel() {
1840 StopMediaMonitor();
1841 // this can't be done in the base class, since it calls a virtual
1842 DisableMedia_w();
wu@webrtc.org78187522013-10-07 23:32:02 +00001843
1844 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001845}
1846
1847bool DataChannel::Init() {
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +00001848 if (!BaseChannel::Init()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001849 return false;
1850 }
1851 media_channel()->SignalDataReceived.connect(
1852 this, &DataChannel::OnDataReceived);
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001853 media_channel()->SignalReadyToSend.connect(
1854 this, &DataChannel::OnDataChannelReadyToSend);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00001855 media_channel()->SignalStreamClosedRemotely.connect(
1856 this, &DataChannel::OnStreamClosedRemotely);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001857 return true;
1858}
1859
1860bool DataChannel::SendData(const SendDataParams& params,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001861 const rtc::Buffer& payload,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001862 SendDataResult* result) {
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001863 return InvokeOnWorker(Bind(&DataMediaChannel::SendData,
1864 media_channel(), params, payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001865}
1866
1867const ContentInfo* DataChannel::GetFirstContent(
1868 const SessionDescription* sdesc) {
1869 return GetFirstDataContent(sdesc);
1870}
1871
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001872bool DataChannel::WantsPacket(bool rtcp, rtc::Buffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001873 if (data_channel_type_ == DCT_SCTP) {
1874 // TODO(pthatcher): Do this in a more robust way by checking for
1875 // SCTP or DTLS.
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +00001876 return !IsRtpPacket(packet->data(), packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001877 } else if (data_channel_type_ == DCT_RTP) {
1878 return BaseChannel::WantsPacket(rtcp, packet);
1879 }
1880 return false;
1881}
1882
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001883bool DataChannel::SetDataChannelType(DataChannelType new_data_channel_type,
1884 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001885 // It hasn't been set before, so set it now.
1886 if (data_channel_type_ == DCT_NONE) {
1887 data_channel_type_ = new_data_channel_type;
1888 return true;
1889 }
1890
1891 // It's been set before, but doesn't match. That's bad.
1892 if (data_channel_type_ != new_data_channel_type) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001893 std::ostringstream desc;
1894 desc << "Data channel type mismatch."
1895 << " Expected " << data_channel_type_
1896 << " Got " << new_data_channel_type;
1897 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001898 return false;
1899 }
1900
1901 // It's hasn't changed. Nothing to do.
1902 return true;
1903}
1904
1905bool DataChannel::SetDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001906 const DataContentDescription* content,
1907 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001908 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
1909 (content->protocol() == kMediaProtocolDtlsSctp));
1910 DataChannelType data_channel_type = is_sctp ? DCT_SCTP : DCT_RTP;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001911 return SetDataChannelType(data_channel_type, error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001912}
1913
1914bool DataChannel::SetLocalContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001915 ContentAction action,
1916 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001917 TRACE_EVENT0("webrtc", "DataChannel::SetLocalContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001918 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001919 LOG(LS_INFO) << "Setting local data description";
1920
1921 const DataContentDescription* data =
1922 static_cast<const DataContentDescription*>(content);
1923 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001924 if (!data) {
1925 SafeSetError("Can't find data content in local description.", error_desc);
1926 return false;
1927 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001928
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001929 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001930 return false;
1931 }
1932
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001933 if (data_channel_type_ == DCT_RTP) {
1934 if (!SetRtpTransportParameters_w(content, action, CS_LOCAL, error_desc)) {
1935 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001936 }
1937 }
1938
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001939 // FYI: We send the SCTP port number (not to be confused with the
1940 // underlying UDP port number) as a codec parameter. So even SCTP
1941 // data channels need codecs.
1942 DataRecvParameters recv_params = last_recv_params_;
1943 RtpParametersFromMediaDescription(data, &recv_params);
1944 if (!media_channel()->SetRecvParameters(recv_params)) {
1945 SafeSetError("Failed to set remote data description recv parameters.",
1946 error_desc);
1947 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001948 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001949 if (data_channel_type_ == DCT_RTP) {
1950 for (const DataCodec& codec : data->codecs()) {
1951 bundle_filter()->AddPayloadType(codec.id);
1952 }
1953 }
1954 last_recv_params_ = recv_params;
1955
1956 // TODO(pthatcher): Move local streams into DataSendParameters, and
1957 // only give it to the media channel once we have a remote
1958 // description too (without a remote description, we won't be able
1959 // to send them anyway).
1960 if (!UpdateLocalStreams_w(data->streams(), action, error_desc)) {
1961 SafeSetError("Failed to set local data description streams.", error_desc);
1962 return false;
1963 }
1964
1965 set_local_content_direction(content->direction());
1966 ChangeState();
1967 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001968}
1969
1970bool DataChannel::SetRemoteContent_w(const MediaContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001971 ContentAction action,
1972 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001973 TRACE_EVENT0("webrtc", "DataChannel::SetRemoteContent_w");
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001974 ASSERT(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001975
1976 const DataContentDescription* data =
1977 static_cast<const DataContentDescription*>(content);
1978 ASSERT(data != NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001979 if (!data) {
1980 SafeSetError("Can't find data content in remote description.", error_desc);
1981 return false;
1982 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001983
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001984 // If the remote data doesn't have codecs and isn't an update, it
1985 // must be empty, so ignore it.
1986 if (!data->has_codecs() && action != CA_UPDATE) {
1987 return true;
1988 }
1989
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001990 if (!SetDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001991 return false;
1992 }
1993
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001994 LOG(LS_INFO) << "Setting remote data description";
1995 if (data_channel_type_ == DCT_RTP &&
1996 !SetRtpTransportParameters_w(content, action, CS_REMOTE, error_desc)) {
1997 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001998 }
1999
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002000
2001 DataSendParameters send_params = last_send_params_;
2002 RtpSendParametersFromMediaDescription<DataCodec>(data, &send_params);
2003 if (!media_channel()->SetSendParameters(send_params)) {
2004 SafeSetError("Failed to set remote data description send parameters.",
2005 error_desc);
2006 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002007 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07002008 last_send_params_ = send_params;
2009
2010 // TODO(pthatcher): Move remote streams into DataRecvParameters,
2011 // and only give it to the media channel once we have a local
2012 // description too (without a local description, we won't be able to
2013 // recv them anyway).
2014 if (!UpdateRemoteStreams_w(data->streams(), action, error_desc)) {
2015 SafeSetError("Failed to set remote data description streams.",
2016 error_desc);
2017 return false;
2018 }
2019
2020 set_remote_content_direction(content->direction());
2021 ChangeState();
2022 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002023}
2024
2025void DataChannel::ChangeState() {
2026 // Render incoming data if we're the active call, and we have the local
2027 // content. We receive data on the default channel and multiplexed streams.
2028 bool recv = IsReadyToReceive();
2029 if (!media_channel()->SetReceive(recv)) {
2030 LOG(LS_ERROR) << "Failed to SetReceive on data channel";
2031 }
2032
2033 // Send outgoing data if we're the active call, we have the remote content,
2034 // and we have had some form of connectivity.
2035 bool send = IsReadyToSend();
2036 if (!media_channel()->SetSend(send)) {
2037 LOG(LS_ERROR) << "Failed to SetSend on data channel";
2038 }
2039
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00002040 // Trigger SignalReadyToSendData asynchronously.
2041 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002042
2043 LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
2044}
2045
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002046void DataChannel::OnMessage(rtc::Message *pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002047 switch (pmsg->message_id) {
2048 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002049 DataChannelReadyToSendMessageData* data =
2050 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00002051 ready_to_send_data_ = data->data();
2052 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002053 delete data;
2054 break;
2055 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002056 case MSG_DATARECEIVED: {
2057 DataReceivedMessageData* data =
2058 static_cast<DataReceivedMessageData*>(pmsg->pdata);
2059 SignalDataReceived(this, data->params, data->payload);
2060 delete data;
2061 break;
2062 }
2063 case MSG_CHANNEL_ERROR: {
2064 const DataChannelErrorMessageData* data =
2065 static_cast<DataChannelErrorMessageData*>(pmsg->pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002066 delete data;
2067 break;
2068 }
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002069 case MSG_STREAMCLOSEDREMOTELY: {
Peter Boström0c4e06b2015-10-07 12:23:21 +02002070 rtc::TypedMessageData<uint32_t>* data =
2071 static_cast<rtc::TypedMessageData<uint32_t>*>(pmsg->pdata);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002072 SignalStreamClosedRemotely(data->data());
2073 delete data;
2074 break;
2075 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002076 default:
2077 BaseChannel::OnMessage(pmsg);
2078 break;
2079 }
2080}
2081
2082void DataChannel::OnConnectionMonitorUpdate(
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +00002083 ConnectionMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002084 SignalConnectionMonitor(this, infos);
2085}
2086
2087void DataChannel::StartMediaMonitor(int cms) {
2088 media_monitor_.reset(new DataMediaMonitor(media_channel(), worker_thread(),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002089 rtc::Thread::Current()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002090 media_monitor_->SignalUpdate.connect(
2091 this, &DataChannel::OnMediaMonitorUpdate);
2092 media_monitor_->Start(cms);
2093}
2094
2095void DataChannel::StopMediaMonitor() {
2096 if (media_monitor_) {
2097 media_monitor_->Stop();
2098 media_monitor_->SignalUpdate.disconnect(this);
2099 media_monitor_.reset();
2100 }
2101}
2102
2103void DataChannel::OnMediaMonitorUpdate(
2104 DataMediaChannel* media_channel, const DataMediaInfo& info) {
2105 ASSERT(media_channel == this->media_channel());
2106 SignalMediaMonitor(this, info);
2107}
2108
2109void DataChannel::OnDataReceived(
2110 const ReceiveDataParams& params, const char* data, size_t len) {
2111 DataReceivedMessageData* msg = new DataReceivedMessageData(
2112 params, data, len);
2113 signaling_thread()->Post(this, MSG_DATARECEIVED, msg);
2114}
2115
Peter Boström0c4e06b2015-10-07 12:23:21 +02002116void DataChannel::OnDataChannelError(uint32_t ssrc,
2117 DataMediaChannel::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002118 DataChannelErrorMessageData* data = new DataChannelErrorMessageData(
2119 ssrc, err);
2120 signaling_thread()->Post(this, MSG_CHANNEL_ERROR, data);
2121}
2122
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00002123void DataChannel::OnDataChannelReadyToSend(bool writable) {
2124 // This is usded for congestion control to indicate that the stream is ready
2125 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
2126 // that the transport channel is ready.
2127 signaling_thread()->Post(this, MSG_READYTOSENDDATA,
2128 new DataChannelReadyToSendMessageData(writable));
2129}
2130
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002131void DataChannel::GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const {
2132 GetSupportedDataCryptoSuites(crypto_suites);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002133}
2134
2135bool DataChannel::ShouldSetupDtlsSrtp() const {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -08002136 return (data_channel_type_ == DCT_RTP) && BaseChannel::ShouldSetupDtlsSrtp();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002137}
2138
Peter Boström0c4e06b2015-10-07 12:23:21 +02002139void DataChannel::OnStreamClosedRemotely(uint32_t sid) {
2140 rtc::TypedMessageData<uint32_t>* message =
2141 new rtc::TypedMessageData<uint32_t>(sid);
buildbot@webrtc.org1d66be22014-05-29 22:54:24 +00002142 signaling_thread()->Post(this, MSG_STREAMCLOSEDREMOTELY, message);
2143}
2144
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002145} // namespace cricket