blob: b63cea7cecf3021c362a7a72d7846c7e2132acfa [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
jbauch5869f502017-06-29 12:31:36 -070011#include <algorithm>
12#include <iterator>
kwiberg0eb15ed2015-12-17 03:04:15 -080013#include <utility>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "pc/channel.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000016
Karl Wiberg918f50c2018-07-05 11:40:33 +020017#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "api/call/audio_sink.h"
19#include "media/base/mediaconstants.h"
20#include "media/base/rtputils.h"
Zhi Huang365381f2018-04-13 16:44:34 -070021#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "rtc_base/bind.h"
23#include "rtc_base/byteorder.h"
24#include "rtc_base/checks.h"
25#include "rtc_base/copyonwritebuffer.h"
26#include "rtc_base/dscp.h"
27#include "rtc_base/logging.h"
28#include "rtc_base/networkroute.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020029#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "rtc_base/trace_event.h"
Patrik Höglund42805f32018-01-18 19:15:38 +000031// Adding 'nogncheck' to disable the gn include headers check to support modular
32// WebRTC build targets.
33#include "media/engine/webrtcvoiceengine.h" // nogncheck
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020034#include "p2p/base/packettransportinternal.h"
35#include "pc/channelmanager.h"
Steve Anton4e70a722017-11-28 14:57:10 -080036#include "pc/rtpmediautils.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037
38namespace cricket {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000039using rtc::Bind;
Steve Anton3828c062017-12-06 10:34:51 -080040using webrtc::SdpType;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000041
deadbeef2d110be2016-01-13 12:00:26 -080042namespace {
Danil Chapovalov33b01f22016-05-11 19:55:27 +020043
44struct SendPacketMessageData : public rtc::MessageData {
45 rtc::CopyOnWriteBuffer packet;
46 rtc::PacketOptions options;
47};
48
deadbeef2d110be2016-01-13 12:00:26 -080049} // namespace
50
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051enum {
Steve Anton0807d152018-03-05 11:23:09 -080052 MSG_SEND_RTP_PACKET = 1,
Danil Chapovalov33b01f22016-05-11 19:55:27 +020053 MSG_SEND_RTCP_PACKET,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000054 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000055 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000056 MSG_FIRSTPACKETRECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000057};
58
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000059static void SafeSetError(const std::string& message, std::string* error_desc) {
60 if (error_desc) {
61 *error_desc = message;
62 }
63}
64
jbaucheec21bd2016-03-20 06:15:43 -070065static bool ValidPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066 // Check the packet size. We could check the header too if needed.
zstein3dcf0e92017-06-01 13:22:42 -070067 return packet && IsValidRtpRtcpPacketSize(rtcp, packet->size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068}
69
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070070template <class Codec>
71void RtpParametersFromMediaDescription(
72 const MediaContentDescriptionImpl<Codec>* desc,
jbauch5869f502017-06-29 12:31:36 -070073 const RtpHeaderExtensions& extensions,
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070074 RtpParameters<Codec>* params) {
75 // TODO(pthatcher): Remove this once we're sure no one will give us
Zhi Huang801b8682017-11-15 11:36:43 -080076 // a description without codecs. Currently the ORTC implementation is relying
77 // on this.
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070078 if (desc->has_codecs()) {
79 params->codecs = desc->codecs();
80 }
81 // TODO(pthatcher): See if we really need
82 // rtp_header_extensions_set() and remove it if we don't.
83 if (desc->rtp_header_extensions_set()) {
jbauch5869f502017-06-29 12:31:36 -070084 params->extensions = extensions;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070085 }
deadbeef13871492015-12-09 12:37:51 -080086 params->rtcp.reduced_size = desc->rtcp_reduced_size();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070087}
88
nisse05103312016-03-16 02:22:50 -070089template <class Codec>
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070090void RtpSendParametersFromMediaDescription(
91 const MediaContentDescriptionImpl<Codec>* desc,
jbauch5869f502017-06-29 12:31:36 -070092 const RtpHeaderExtensions& extensions,
nisse05103312016-03-16 02:22:50 -070093 RtpSendParameters<Codec>* send_params) {
jbauch5869f502017-06-29 12:31:36 -070094 RtpParametersFromMediaDescription(desc, extensions, send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070095 send_params->max_bandwidth_bps = desc->bandwidth();
96}
97
Danil Chapovalov33b01f22016-05-11 19:55:27 +020098BaseChannel::BaseChannel(rtc::Thread* worker_thread,
99 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800100 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -0800101 std::unique_ptr<MediaChannel> media_channel,
deadbeefcbecd352015-09-23 11:50:27 -0700102 const std::string& content_name,
Zhi Huange830e682018-03-30 10:48:35 -0700103 bool srtp_required,
104 rtc::CryptoOptions crypto_options)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200105 : worker_thread_(worker_thread),
106 network_thread_(network_thread),
zhihuangf5b251b2017-01-12 19:37:48 -0800107 signaling_thread_(signaling_thread),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108 content_name_(content_name),
deadbeef7af91dd2016-12-13 11:29:11 -0800109 srtp_required_(srtp_required),
Zhi Huange830e682018-03-30 10:48:35 -0700110 crypto_options_(crypto_options),
Zhi Huang1d88d742017-11-15 15:58:49 -0800111 media_channel_(std::move(media_channel)) {
Steve Anton8699a322017-11-06 15:53:33 -0800112 RTC_DCHECK_RUN_ON(worker_thread_);
Zhi Huang365381f2018-04-13 16:44:34 -0700113 demuxer_criteria_.mid = content_name;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100114 RTC_LOG(LS_INFO) << "Created channel for " << content_name;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115}
116
117BaseChannel::~BaseChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800118 TRACE_EVENT0("webrtc", "BaseChannel::~BaseChannel");
Steve Anton8699a322017-11-06 15:53:33 -0800119 RTC_DCHECK_RUN_ON(worker_thread_);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200120 // Eats any outstanding messages or packets.
121 worker_thread_->Clear(&invoker_);
122 worker_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000123 // We must destroy the media channel before the transport channel, otherwise
124 // the media channel may try to send on the dead transport channel. NULLing
125 // is not an effective strategy since the sends will come on another thread.
Steve Anton8699a322017-11-06 15:53:33 -0800126 media_channel_.reset();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100127 RTC_LOG(LS_INFO) << "Destroyed channel: " << content_name_;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200128}
129
Zhi Huang365381f2018-04-13 16:44:34 -0700130bool BaseChannel::ConnectToRtpTransport() {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800131 RTC_DCHECK(rtp_transport_);
Zhi Huang365381f2018-04-13 16:44:34 -0700132 if (!RegisterRtpDemuxerSink()) {
133 return false;
134 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800135 rtp_transport_->SignalReadyToSend.connect(
136 this, &BaseChannel::OnTransportReadyToSend);
Zhi Huang365381f2018-04-13 16:44:34 -0700137 rtp_transport_->SignalRtcpPacketReceived.connect(
138 this, &BaseChannel::OnRtcpPacketReceived);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800139 rtp_transport_->SignalNetworkRouteChanged.connect(
140 this, &BaseChannel::OnNetworkRouteChanged);
141 rtp_transport_->SignalWritableState.connect(this,
142 &BaseChannel::OnWritableState);
143 rtp_transport_->SignalSentPacket.connect(this,
144 &BaseChannel::SignalSentPacket_n);
Zhi Huang365381f2018-04-13 16:44:34 -0700145 return true;
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800146}
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200147
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800148void BaseChannel::DisconnectFromRtpTransport() {
149 RTC_DCHECK(rtp_transport_);
Zhi Huang365381f2018-04-13 16:44:34 -0700150 rtp_transport_->UnregisterRtpDemuxerSink(this);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800151 rtp_transport_->SignalReadyToSend.disconnect(this);
Zhi Huang365381f2018-04-13 16:44:34 -0700152 rtp_transport_->SignalRtcpPacketReceived.disconnect(this);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800153 rtp_transport_->SignalNetworkRouteChanged.disconnect(this);
154 rtp_transport_->SignalWritableState.disconnect(this);
155 rtp_transport_->SignalSentPacket.disconnect(this);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200156}
157
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800158void BaseChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) {
159 RTC_DCHECK_RUN_ON(worker_thread_);
Zhi Huang365381f2018-04-13 16:44:34 -0700160 network_thread_->Invoke<void>(
161 RTC_FROM_HERE, [this, rtp_transport] { SetRtpTransport(rtp_transport); });
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800162
163 // Both RTP and RTCP channels should be set, we can call SetInterface on
164 // the media channel and it can set network options.
165 media_channel_->SetInterface(this);
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200166}
167
wu@webrtc.org78187522013-10-07 23:32:02 +0000168void BaseChannel::Deinit() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200169 RTC_DCHECK(worker_thread_->IsCurrent());
wu@webrtc.org78187522013-10-07 23:32:02 +0000170 media_channel_->SetInterface(NULL);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200171 // Packets arrive on the network thread, processing packets calls virtual
172 // functions, so need to stop this process in Deinit that is called in
173 // derived classes destructor.
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800174 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000175 FlushRtcpMessages_n();
Zhi Huang27f3bf52018-03-26 21:37:23 -0700176
Zhi Huange830e682018-03-30 10:48:35 -0700177 if (rtp_transport_) {
178 DisconnectFromRtpTransport();
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000179 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800180 // Clear pending read packets/messages.
181 network_thread_->Clear(&invoker_);
182 network_thread_->Clear(this);
183 });
wu@webrtc.org78187522013-10-07 23:32:02 +0000184}
185
Zhi Huang365381f2018-04-13 16:44:34 -0700186bool BaseChannel::SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) {
187 if (rtp_transport == rtp_transport_) {
188 return true;
189 }
190
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800191 if (!network_thread_->IsCurrent()) {
Zhi Huang365381f2018-04-13 16:44:34 -0700192 return network_thread_->Invoke<bool>(RTC_FROM_HERE, [this, rtp_transport] {
193 return SetRtpTransport(rtp_transport);
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800194 });
195 }
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000196
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800197 if (rtp_transport_) {
198 DisconnectFromRtpTransport();
199 }
Zhi Huange830e682018-03-30 10:48:35 -0700200
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800201 rtp_transport_ = rtp_transport;
Zhi Huange830e682018-03-30 10:48:35 -0700202 if (rtp_transport_) {
203 RTC_DCHECK(rtp_transport_->rtp_packet_transport());
204 transport_name_ = rtp_transport_->rtp_packet_transport()->transport_name();
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800205
Zhi Huang365381f2018-04-13 16:44:34 -0700206 if (!ConnectToRtpTransport()) {
207 RTC_LOG(LS_ERROR) << "Failed to connect to the new RtpTransport.";
208 return false;
209 }
Zhi Huange830e682018-03-30 10:48:35 -0700210 OnTransportReadyToSend(rtp_transport_->IsReadyToSend());
211 UpdateWritableState_n();
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800212
Zhi Huange830e682018-03-30 10:48:35 -0700213 // Set the cached socket options.
214 for (const auto& pair : socket_options_) {
215 rtp_transport_->rtp_packet_transport()->SetOption(pair.first,
216 pair.second);
217 }
218 if (rtp_transport_->rtcp_packet_transport()) {
219 for (const auto& pair : rtcp_socket_options_) {
220 rtp_transport_->rtp_packet_transport()->SetOption(pair.first,
221 pair.second);
222 }
223 }
guoweis46383312015-12-17 16:45:59 -0800224 }
Zhi Huang365381f2018-04-13 16:44:34 -0700225 return true;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000226}
227
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000228bool BaseChannel::Enable(bool enable) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700229 worker_thread_->Invoke<void>(
230 RTC_FROM_HERE,
231 Bind(enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
232 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000233 return true;
234}
235
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000236bool BaseChannel::AddRecvStream(const StreamParams& sp) {
Zhi Huang365381f2018-04-13 16:44:34 -0700237 demuxer_criteria_.ssrcs.insert(sp.first_ssrc());
238 if (!RegisterRtpDemuxerSink()) {
239 return false;
240 }
stefanf79ade12017-06-02 06:44:03 -0700241 return InvokeOnWorker<bool>(RTC_FROM_HERE,
242 Bind(&BaseChannel::AddRecvStream_w, this, sp));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000243}
244
Peter Boström0c4e06b2015-10-07 12:23:21 +0200245bool BaseChannel::RemoveRecvStream(uint32_t ssrc) {
Zhi Huang365381f2018-04-13 16:44:34 -0700246 demuxer_criteria_.ssrcs.erase(ssrc);
247 if (!RegisterRtpDemuxerSink()) {
248 return false;
249 }
stefanf79ade12017-06-02 06:44:03 -0700250 return InvokeOnWorker<bool>(
251 RTC_FROM_HERE, Bind(&BaseChannel::RemoveRecvStream_w, this, ssrc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000252}
253
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000254bool BaseChannel::AddSendStream(const StreamParams& sp) {
stefanf79ade12017-06-02 06:44:03 -0700255 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700256 RTC_FROM_HERE, Bind(&MediaChannel::AddSendStream, media_channel(), sp));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000257}
258
Peter Boström0c4e06b2015-10-07 12:23:21 +0200259bool BaseChannel::RemoveSendStream(uint32_t ssrc) {
stefanf79ade12017-06-02 06:44:03 -0700260 return InvokeOnWorker<bool>(
261 RTC_FROM_HERE,
262 Bind(&MediaChannel::RemoveSendStream, media_channel(), ssrc));
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000263}
264
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000265bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800266 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000267 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100268 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
stefanf79ade12017-06-02 06:44:03 -0700269 return InvokeOnWorker<bool>(
270 RTC_FROM_HERE,
Steve Anton3828c062017-12-06 10:34:51 -0800271 Bind(&BaseChannel::SetLocalContent_w, this, content, type, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000272}
273
274bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800275 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000276 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100277 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
stefanf79ade12017-06-02 06:44:03 -0700278 return InvokeOnWorker<bool>(
Steve Anton3828c062017-12-06 10:34:51 -0800279 RTC_FROM_HERE,
280 Bind(&BaseChannel::SetRemoteContent_w, this, content, type, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000281}
282
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700283bool BaseChannel::IsReadyToReceiveMedia_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000284 // Receive data if we are enabled and have local content,
Steve Anton4e70a722017-11-28 14:57:10 -0800285 return enabled() &&
286 webrtc::RtpTransceiverDirectionHasRecv(local_content_direction_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000287}
288
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700289bool BaseChannel::IsReadyToSendMedia_w() const {
290 // Need to access some state updated on the network thread.
291 return network_thread_->Invoke<bool>(
292 RTC_FROM_HERE, Bind(&BaseChannel::IsReadyToSendMedia_n, this));
293}
294
295bool BaseChannel::IsReadyToSendMedia_n() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000296 // Send outgoing data if we are enabled, have local and remote content,
297 // and we have had some form of connectivity.
Steve Anton4e70a722017-11-28 14:57:10 -0800298 return enabled() &&
299 webrtc::RtpTransceiverDirectionHasRecv(remote_content_direction_) &&
300 webrtc::RtpTransceiverDirectionHasSend(local_content_direction_) &&
Zhi Huang365381f2018-04-13 16:44:34 -0700301 was_ever_writable();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000302}
303
jbaucheec21bd2016-03-20 06:15:43 -0700304bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700305 const rtc::PacketOptions& options) {
306 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000307}
308
jbaucheec21bd2016-03-20 06:15:43 -0700309bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700310 const rtc::PacketOptions& options) {
311 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000312}
313
Yves Gerey665174f2018-06-19 15:03:05 +0200314int BaseChannel::SetOption(SocketType type,
315 rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000316 int value) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200317 return network_thread_->Invoke<int>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700318 RTC_FROM_HERE, Bind(&BaseChannel::SetOption_n, this, type, opt, value));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200319}
320
321int BaseChannel::SetOption_n(SocketType type,
322 rtc::Socket::Option opt,
323 int value) {
324 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huange830e682018-03-30 10:48:35 -0700325 RTC_DCHECK(rtp_transport_);
deadbeef5bd5ca32017-02-10 11:31:50 -0800326 rtc::PacketTransportInternal* transport = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000327 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000328 case ST_RTP:
zsteine8ab5432017-07-12 11:48:11 -0700329 transport = rtp_transport_->rtp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700330 socket_options_.push_back(
331 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000332 break;
333 case ST_RTCP:
zsteine8ab5432017-07-12 11:48:11 -0700334 transport = rtp_transport_->rtcp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700335 rtcp_socket_options_.push_back(
336 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000337 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000338 }
deadbeeff5346592017-01-24 21:51:21 -0800339 return transport ? transport->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000340}
341
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800342void BaseChannel::OnWritableState(bool writable) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200343 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800344 if (writable) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800345 ChannelWritable_n();
346 } else {
347 ChannelNotWritable_n();
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800348 }
349}
350
Zhi Huang942bc2e2017-11-13 13:26:07 -0800351void BaseChannel::OnNetworkRouteChanged(
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200352 absl::optional<rtc::NetworkRoute> network_route) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200353 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huang942bc2e2017-11-13 13:26:07 -0800354 rtc::NetworkRoute new_route;
355 if (network_route) {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800356 new_route = *(network_route);
Zhi Huang8c316c12017-11-13 21:13:45 +0000357 }
Zhi Huang942bc2e2017-11-13 13:26:07 -0800358 // Note: When the RTCP-muxing is not enabled, RTCP transport and RTP transport
359 // use the same transport name and MediaChannel::OnNetworkRouteChanged cannot
360 // work correctly. Intentionally leave it broken to simplify the code and
361 // encourage the users to stop using non-muxing RTCP.
Steve Anton8699a322017-11-06 15:53:33 -0800362 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_, [=] {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800363 media_channel_->OnNetworkRouteChanged(transport_name_, new_route);
Steve Anton8699a322017-11-06 15:53:33 -0800364 });
Honghai Zhangcc411c02016-03-29 17:27:21 -0700365}
366
zstein56162b92017-04-24 16:54:35 -0700367void BaseChannel::OnTransportReadyToSend(bool ready) {
Steve Anton8699a322017-11-06 15:53:33 -0800368 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
369 [=] { media_channel_->OnReadyToSend(ready); });
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000370}
371
stefanc1aeaf02015-10-15 07:26:07 -0700372bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700373 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700374 const rtc::PacketOptions& options) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200375 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
376 // If the thread is not our network thread, we will post to our network
377 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000378 // synchronize access to all the pieces of the send path, including
379 // SRTP and the inner workings of the transport channels.
380 // The only downside is that we can't return a proper failure code if
381 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200382 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000383 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200384 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
385 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800386 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700387 data->options = options;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700388 network_thread_->Post(RTC_FROM_HERE, this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000389 return true;
390 }
Zhi Huange830e682018-03-30 10:48:35 -0700391
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200392 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000393
394 // Now that we are on the correct thread, ensure we have a place to send this
395 // packet before doing anything. (We might get RTCP packets that we don't
396 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
397 // transport.
Zhi Huange830e682018-03-30 10:48:35 -0700398 if (!rtp_transport_ || !rtp_transport_->IsWritable(rtcp)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000399 return false;
400 }
401
402 // Protect ourselves against crazy data.
403 if (!ValidPacket(rtcp, packet)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100404 RTC_LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
405 << RtpRtcpStringLiteral(rtcp)
406 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000407 return false;
408 }
409
Zhi Huangcf990f52017-09-22 12:12:30 -0700410 if (!srtp_active()) {
411 if (srtp_required_) {
412 // The audio/video engines may attempt to send RTCP packets as soon as the
413 // streams are created, so don't treat this as an error for RTCP.
414 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6809
415 if (rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000416 return false;
417 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700418 // However, there shouldn't be any RTP packets sent before SRTP is set up
419 // (and SetSend(true) is called).
Mirko Bonadei675513b2017-11-09 11:09:25 +0100420 RTC_LOG(LS_ERROR)
421 << "Can't send outgoing RTP packet when SRTP is inactive"
422 << " and crypto is required";
Zhi Huangcf990f52017-09-22 12:12:30 -0700423 RTC_NOTREACHED();
deadbeef8f425f92016-12-01 12:26:27 -0800424 return false;
425 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800426
427 std::string packet_type = rtcp ? "RTCP" : "RTP";
428 RTC_LOG(LS_WARNING) << "Sending an " << packet_type
429 << " packet without encryption.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000430 }
Zhi Huange830e682018-03-30 10:48:35 -0700431
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000432 // Bon voyage.
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800433 return rtcp ? rtp_transport_->SendRtcpPacket(packet, options, PF_SRTP_BYPASS)
434 : rtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000435}
436
Zhi Huang365381f2018-04-13 16:44:34 -0700437void BaseChannel::OnRtpPacket(const webrtc::RtpPacketReceived& parsed_packet) {
438 // Reconstruct the PacketTime from the |parsed_packet|.
439 // RtpPacketReceived.arrival_time_ms = (PacketTime + 500) / 1000;
440 // Note: The |not_before| field is always 0 here. This field is not currently
441 // used, so it should be fine.
442 int64_t timestamp = -1;
443 if (parsed_packet.arrival_time_ms() > 0) {
444 timestamp = parsed_packet.arrival_time_ms() * 1000;
445 }
446 rtc::PacketTime packet_time(timestamp, /*not_before=*/0);
447
448 OnPacketReceived(/*rtcp=*/false, parsed_packet.Buffer(), packet_time);
449}
450
451void BaseChannel::UpdateRtpHeaderExtensionMap(
452 const RtpHeaderExtensions& header_extensions) {
453 RTC_DCHECK(rtp_transport_);
454 // Update the header extension map on network thread in case there is data
455 // race.
456 // TODO(zhihuang): Add an rtc::ThreadChecker make sure to RtpTransport won't
457 // be accessed from different threads.
458 //
459 // NOTE: This doesn't take the BUNDLE case in account meaning the RTP header
460 // extension maps are not merged when BUNDLE is enabled. This is fine because
461 // the ID for MID should be consistent among all the RTP transports.
462 network_thread_->Invoke<void>(RTC_FROM_HERE, [this, &header_extensions] {
463 rtp_transport_->UpdateRtpHeaderExtensionMap(header_extensions);
464 });
465}
466
467bool BaseChannel::RegisterRtpDemuxerSink() {
468 RTC_DCHECK(rtp_transport_);
469 return network_thread_->Invoke<bool>(RTC_FROM_HERE, [this] {
470 return rtp_transport_->RegisterRtpDemuxerSink(demuxer_criteria_, this);
471 });
472}
473
474void BaseChannel::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
475 const rtc::PacketTime& packet_time) {
476 OnPacketReceived(/*rtcp=*/true, *packet, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000477}
478
zstein3dcf0e92017-06-01 13:22:42 -0700479void BaseChannel::OnPacketReceived(bool rtcp,
Zhi Huang365381f2018-04-13 16:44:34 -0700480 const rtc::CopyOnWriteBuffer& packet,
zstein3dcf0e92017-06-01 13:22:42 -0700481 const rtc::PacketTime& packet_time) {
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000482 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000483 has_received_packet_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700484 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000485 }
486
Zhi Huangcf990f52017-09-22 12:12:30 -0700487 if (!srtp_active() && srtp_required_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488 // Our session description indicates that SRTP is required, but we got a
489 // packet before our SRTP filter is active. This means either that
490 // a) we got SRTP packets before we received the SDES keys, in which case
491 // we can't decrypt it anyway, or
492 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
zhihuangb2cdd932017-01-19 16:54:25 -0800493 // transports, so we haven't yet extracted keys, even if DTLS did
494 // complete on the transport that the packets are being sent on. It's
495 // really good practice to wait for both RTP and RTCP to be good to go
496 // before sending media, to prevent weird failure modes, so it's fine
497 // for us to just eat packets here. This is all sidestepped if RTCP mux
498 // is used anyway.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100499 RTC_LOG(LS_WARNING)
500 << "Can't process incoming " << RtpRtcpStringLiteral(rtcp)
501 << " packet when SRTP is inactive and crypto is required";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000502 return;
503 }
504
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200505 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700506 RTC_FROM_HERE, worker_thread_,
Zhi Huang365381f2018-04-13 16:44:34 -0700507 Bind(&BaseChannel::ProcessPacket, this, rtcp, packet, packet_time));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200508}
509
zstein3dcf0e92017-06-01 13:22:42 -0700510void BaseChannel::ProcessPacket(bool rtcp,
511 const rtc::CopyOnWriteBuffer& packet,
512 const rtc::PacketTime& packet_time) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200513 RTC_DCHECK(worker_thread_->IsCurrent());
zstein3dcf0e92017-06-01 13:22:42 -0700514
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200515 // Need to copy variable because OnRtcpReceived/OnPacketReceived
516 // requires non-const pointer to buffer. This doesn't memcpy the actual data.
517 rtc::CopyOnWriteBuffer data(packet);
518 if (rtcp) {
519 media_channel_->OnRtcpReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000520 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200521 media_channel_->OnPacketReceived(&data, packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000522 }
523}
524
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000525void BaseChannel::EnableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700526 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000527 if (enabled_)
528 return;
529
Mirko Bonadei675513b2017-11-09 11:09:25 +0100530 RTC_LOG(LS_INFO) << "Channel enabled";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000531 enabled_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700532 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000533}
534
535void BaseChannel::DisableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700536 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000537 if (!enabled_)
538 return;
539
Mirko Bonadei675513b2017-11-09 11:09:25 +0100540 RTC_LOG(LS_INFO) << "Channel disabled";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000541 enabled_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700542 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000543}
544
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200545void BaseChannel::UpdateWritableState_n() {
Zhi Huange830e682018-03-30 10:48:35 -0700546 if (rtp_transport_->IsWritable(/*rtcp=*/true) &&
547 rtp_transport_->IsWritable(/*rtcp=*/false)) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200548 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700549 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200550 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700551 }
552}
553
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200554void BaseChannel::ChannelWritable_n() {
555 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800556 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000557 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800558 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000559
Mirko Bonadei675513b2017-11-09 11:09:25 +0100560 RTC_LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
561 << (was_ever_writable_ ? "" : " for the first time");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000562
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000563 was_ever_writable_ = true;
564 writable_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700565 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000566}
567
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200568void BaseChannel::ChannelNotWritable_n() {
569 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000570 if (!writable_)
571 return;
572
Mirko Bonadei675513b2017-11-09 11:09:25 +0100573 RTC_LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000574 writable_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700575 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000576}
577
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000578bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700579 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -0800580 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000581}
582
Peter Boström0c4e06b2015-10-07 12:23:21 +0200583bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700584 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000585 return media_channel()->RemoveRecvStream(ssrc);
586}
587
588bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
Steve Anton3828c062017-12-06 10:34:51 -0800589 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000590 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000591 // Check for streams that have been removed.
592 bool ret = true;
593 for (StreamParamsVec::const_iterator it = local_streams_.begin();
594 it != local_streams_.end(); ++it) {
Seth Hampson5897a6e2018-04-03 11:16:33 -0700595 if (it->has_ssrcs() && !GetStreamBySsrc(streams, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000596 if (!media_channel()->RemoveSendStream(it->first_ssrc())) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200597 rtc::StringBuilder desc;
Yves Gerey665174f2018-06-19 15:03:05 +0200598 desc << "Failed to remove send stream with ssrc " << it->first_ssrc()
599 << ".";
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000600 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000601 ret = false;
602 }
603 }
604 }
605 // Check for new streams.
606 for (StreamParamsVec::const_iterator it = streams.begin();
607 it != streams.end(); ++it) {
Seth Hampson5897a6e2018-04-03 11:16:33 -0700608 if (it->has_ssrcs() && !GetStreamBySsrc(local_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000609 if (media_channel()->AddSendStream(*it)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100610 RTC_LOG(LS_INFO) << "Add send stream ssrc: " << it->ssrcs[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000611 } else {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200612 rtc::StringBuilder desc;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000613 desc << "Failed to add send stream ssrc: " << it->first_ssrc();
614 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000615 ret = false;
616 }
617 }
618 }
619 local_streams_ = streams;
620 return ret;
621}
622
623bool BaseChannel::UpdateRemoteStreams_w(
624 const std::vector<StreamParams>& streams,
Steve Anton3828c062017-12-06 10:34:51 -0800625 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000626 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000627 // Check for streams that have been removed.
628 bool ret = true;
629 for (StreamParamsVec::const_iterator it = remote_streams_.begin();
630 it != remote_streams_.end(); ++it) {
Seth Hampson5897a6e2018-04-03 11:16:33 -0700631 // If we no longer have an unsignaled stream, we would like to remove
632 // the unsignaled stream params that are cached.
633 if ((!it->has_ssrcs() && !HasStreamWithNoSsrcs(streams)) ||
634 !GetStreamBySsrc(streams, it->first_ssrc())) {
Zhi Huang365381f2018-04-13 16:44:34 -0700635 if (RemoveRecvStream_w(it->first_ssrc())) {
636 RTC_LOG(LS_INFO) << "Remove remote ssrc: " << it->first_ssrc();
637 } else {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200638 rtc::StringBuilder desc;
Yves Gerey665174f2018-06-19 15:03:05 +0200639 desc << "Failed to remove remote stream with ssrc " << it->first_ssrc()
640 << ".";
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000641 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000642 ret = false;
643 }
644 }
645 }
Zhi Huang365381f2018-04-13 16:44:34 -0700646 demuxer_criteria_.ssrcs.clear();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000647 // Check for new streams.
648 for (StreamParamsVec::const_iterator it = streams.begin();
Yves Gerey665174f2018-06-19 15:03:05 +0200649 it != streams.end(); ++it) {
Seth Hampson5897a6e2018-04-03 11:16:33 -0700650 // We allow a StreamParams with an empty list of SSRCs, in which case the
651 // MediaChannel will cache the parameters and use them for any unsignaled
652 // stream received later.
653 if ((!it->has_ssrcs() && !HasStreamWithNoSsrcs(remote_streams_)) ||
654 !GetStreamBySsrc(remote_streams_, it->first_ssrc())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000655 if (AddRecvStream_w(*it)) {
Seth Hampson5897a6e2018-04-03 11:16:33 -0700656 RTC_LOG(LS_INFO) << "Add remote ssrc: " << it->first_ssrc();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000657 } else {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200658 rtc::StringBuilder desc;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000659 desc << "Failed to add remote stream ssrc: " << it->first_ssrc();
660 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000661 ret = false;
662 }
663 }
Zhi Huang365381f2018-04-13 16:44:34 -0700664 // Update the receiving SSRCs.
665 demuxer_criteria_.ssrcs.insert(it->ssrcs.begin(), it->ssrcs.end());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666 }
Zhi Huang365381f2018-04-13 16:44:34 -0700667 // Re-register the sink to update the receiving ssrcs.
668 RegisterRtpDemuxerSink();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669 remote_streams_ = streams;
670 return ret;
671}
672
jbauch5869f502017-06-29 12:31:36 -0700673RtpHeaderExtensions BaseChannel::GetFilteredRtpHeaderExtensions(
674 const RtpHeaderExtensions& extensions) {
Zhi Huange830e682018-03-30 10:48:35 -0700675 RTC_DCHECK(rtp_transport_);
676 if (crypto_options_.enable_encrypted_rtp_header_extensions) {
jbauch5869f502017-06-29 12:31:36 -0700677 RtpHeaderExtensions filtered;
678 auto pred = [](const webrtc::RtpExtension& extension) {
Yves Gerey665174f2018-06-19 15:03:05 +0200679 return !extension.encrypt;
jbauch5869f502017-06-29 12:31:36 -0700680 };
681 std::copy_if(extensions.begin(), extensions.end(),
Yves Gerey665174f2018-06-19 15:03:05 +0200682 std::back_inserter(filtered), pred);
jbauch5869f502017-06-29 12:31:36 -0700683 return filtered;
684 }
685
686 return webrtc::RtpExtension::FilterDuplicateNonEncrypted(extensions);
687}
688
Yves Gerey665174f2018-06-19 15:03:05 +0200689void BaseChannel::OnMessage(rtc::Message* pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +0100690 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000691 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200692 case MSG_SEND_RTP_PACKET:
693 case MSG_SEND_RTCP_PACKET: {
694 RTC_DCHECK(network_thread_->IsCurrent());
695 SendPacketMessageData* data =
696 static_cast<SendPacketMessageData*>(pmsg->pdata);
697 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
698 SendPacket(rtcp, &data->packet, data->options);
699 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000700 break;
701 }
702 case MSG_FIRSTPACKETRECEIVED: {
703 SignalFirstPacketReceived(this);
704 break;
705 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000706 }
707}
708
zstein3dcf0e92017-06-01 13:22:42 -0700709void BaseChannel::AddHandledPayloadType(int payload_type) {
Zhi Huang365381f2018-04-13 16:44:34 -0700710 demuxer_criteria_.payload_types.insert(static_cast<uint8_t>(payload_type));
zstein3dcf0e92017-06-01 13:22:42 -0700711}
712
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200713void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000714 // Flush all remaining RTCP messages. This should only be called in
715 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200716 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000717 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200718 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
719 for (const auto& message : rtcp_messages) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700720 network_thread_->Send(RTC_FROM_HERE, this, MSG_SEND_RTCP_PACKET,
721 message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000722 }
723}
724
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800725void BaseChannel::SignalSentPacket_n(const rtc::SentPacket& sent_packet) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200726 RTC_DCHECK(network_thread_->IsCurrent());
727 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700728 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200729 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
730}
731
732void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
733 RTC_DCHECK(worker_thread_->IsCurrent());
734 SignalSentPacket(sent_packet);
735}
736
737VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
738 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800739 rtc::Thread* signaling_thread,
Niels Möllerf120cba2018-01-30 09:33:03 +0100740 // TODO(nisse): Delete unused argument.
741 MediaEngineInterface* /* media_engine */,
Steve Anton8699a322017-11-06 15:53:33 -0800742 std::unique_ptr<VoiceMediaChannel> media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000743 const std::string& content_name,
Zhi Huange830e682018-03-30 10:48:35 -0700744 bool srtp_required,
745 rtc::CryptoOptions crypto_options)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200746 : BaseChannel(worker_thread,
747 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800748 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -0800749 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -0700750 content_name,
Zhi Huange830e682018-03-30 10:48:35 -0700751 srtp_required,
752 crypto_options) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000753
754VoiceChannel::~VoiceChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800755 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000756 // this can't be done in the base class, since it calls a virtual
757 DisableMedia_w();
Zhi Huang0ffe03d2018-03-30 13:17:42 -0700758 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000759}
760
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700761void BaseChannel::UpdateMediaSendRecvState() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200762 RTC_DCHECK(network_thread_->IsCurrent());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700763 invoker_.AsyncInvoke<void>(
764 RTC_FROM_HERE, worker_thread_,
765 Bind(&BaseChannel::UpdateMediaSendRecvState_w, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200766}
767
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700768void VoiceChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000769 // Render incoming data if we're the active call, and we have the local
770 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700771 bool recv = IsReadyToReceiveMedia_w();
solenberg5b14b422015-10-01 04:10:31 -0700772 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000773
774 // Send outgoing data if we're the active call, we have the remote content,
775 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700776 bool send = IsReadyToSendMedia_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800777 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000778
Mirko Bonadei675513b2017-11-09 11:09:25 +0100779 RTC_LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000780}
781
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000782bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800783 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000784 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100785 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -0800786 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +0100787 RTC_LOG(LS_INFO) << "Setting local voice description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000788
Steve Antonb1c1de12017-12-21 15:14:30 -0800789 RTC_DCHECK(content);
790 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000791 SafeSetError("Can't find audio content in local description.", error_desc);
792 return false;
793 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000794
Steve Antonb1c1de12017-12-21 15:14:30 -0800795 const AudioContentDescription* audio = content->as_audio();
796
jbauch5869f502017-06-29 12:31:36 -0700797 RtpHeaderExtensions rtp_header_extensions =
798 GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
Zhi Huang365381f2018-04-13 16:44:34 -0700799 UpdateRtpHeaderExtensionMap(rtp_header_extensions);
jbauch5869f502017-06-29 12:31:36 -0700800
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700801 AudioRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -0700802 RtpParametersFromMediaDescription(audio, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700803 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -0700804 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700805 error_desc);
806 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000807 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700808 for (const AudioCodec& codec : audio->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -0700809 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700810 }
Zhi Huang365381f2018-04-13 16:44:34 -0700811 // Need to re-register the sink to update the handled payload.
812 if (!RegisterRtpDemuxerSink()) {
813 RTC_LOG(LS_ERROR) << "Failed to set up audio demuxing.";
814 return false;
815 }
816
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700817 last_recv_params_ = recv_params;
818
819 // TODO(pthatcher): Move local streams into AudioSendParameters, and
820 // only give it to the media channel once we have a remote
821 // description too (without a remote description, we won't be able
822 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -0800823 if (!UpdateLocalStreams_w(audio->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700824 SafeSetError("Failed to set local audio description streams.", error_desc);
825 return false;
826 }
827
828 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700829 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700830 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000831}
832
833bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800834 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000835 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100836 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -0800837 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +0100838 RTC_LOG(LS_INFO) << "Setting remote voice description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000839
Steve Antonb1c1de12017-12-21 15:14:30 -0800840 RTC_DCHECK(content);
841 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000842 SafeSetError("Can't find audio content in remote description.", error_desc);
843 return false;
844 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000845
Steve Antonb1c1de12017-12-21 15:14:30 -0800846 const AudioContentDescription* audio = content->as_audio();
847
jbauch5869f502017-06-29 12:31:36 -0700848 RtpHeaderExtensions rtp_header_extensions =
849 GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
850
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700851 AudioSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -0700852 RtpSendParametersFromMediaDescription(audio, rtp_header_extensions,
Yves Gerey665174f2018-06-19 15:03:05 +0200853 &send_params);
Steve Antonbb50ce52018-03-26 10:24:32 -0700854 send_params.mid = content_name();
skvladdc1c62c2016-03-16 19:07:43 -0700855
856 bool parameters_applied = media_channel()->SetSendParameters(send_params);
857 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700858 SafeSetError("Failed to set remote audio description send parameters.",
859 error_desc);
860 return false;
861 }
862 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000863
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700864 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
865 // and only give it to the media channel once we have a local
866 // description too (without a local description, we won't be able to
867 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -0800868 if (!UpdateRemoteStreams_w(audio->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700869 SafeSetError("Failed to set remote audio description streams.", error_desc);
870 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000871 }
872
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700873 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700874 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700875 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000876}
877
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200878VideoChannel::VideoChannel(rtc::Thread* worker_thread,
879 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800880 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -0800881 std::unique_ptr<VideoMediaChannel> media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000882 const std::string& content_name,
Zhi Huange830e682018-03-30 10:48:35 -0700883 bool srtp_required,
884 rtc::CryptoOptions crypto_options)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200885 : BaseChannel(worker_thread,
886 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800887 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -0800888 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -0700889 content_name,
Zhi Huange830e682018-03-30 10:48:35 -0700890 srtp_required,
891 crypto_options) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000892
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000893VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800894 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000895 // this can't be done in the base class, since it calls a virtual
896 DisableMedia_w();
Zhi Huang0ffe03d2018-03-30 13:17:42 -0700897 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000898}
899
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700900void VideoChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000901 // Send outgoing data if we're the active call, we have the remote content,
902 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700903 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000904 if (!media_channel()->SetSend(send)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100905 RTC_LOG(LS_ERROR) << "Failed to SetSend on video channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000906 // TODO(gangji): Report error back to server.
907 }
908
Mirko Bonadei675513b2017-11-09 11:09:25 +0100909 RTC_LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000910}
911
stefanf79ade12017-06-02 06:44:03 -0700912void VideoChannel::FillBitrateInfo(BandwidthEstimationInfo* bwe_info) {
913 InvokeOnWorker<void>(RTC_FROM_HERE, Bind(&VideoMediaChannel::FillBitrateInfo,
914 media_channel(), bwe_info));
915}
916
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000917bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800918 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000919 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100920 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -0800921 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +0100922 RTC_LOG(LS_INFO) << "Setting local video description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000923
Steve Antonb1c1de12017-12-21 15:14:30 -0800924 RTC_DCHECK(content);
925 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000926 SafeSetError("Can't find video content in local description.", error_desc);
927 return false;
928 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000929
Steve Antonb1c1de12017-12-21 15:14:30 -0800930 const VideoContentDescription* video = content->as_video();
931
jbauch5869f502017-06-29 12:31:36 -0700932 RtpHeaderExtensions rtp_header_extensions =
933 GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
Zhi Huang365381f2018-04-13 16:44:34 -0700934 UpdateRtpHeaderExtensionMap(rtp_header_extensions);
jbauch5869f502017-06-29 12:31:36 -0700935
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700936 VideoRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -0700937 RtpParametersFromMediaDescription(video, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700938 if (!media_channel()->SetRecvParameters(recv_params)) {
939 SafeSetError("Failed to set local video description recv parameters.",
940 error_desc);
941 return false;
942 }
943 for (const VideoCodec& codec : video->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -0700944 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700945 }
Zhi Huang365381f2018-04-13 16:44:34 -0700946 // Need to re-register the sink to update the handled payload.
947 if (!RegisterRtpDemuxerSink()) {
948 RTC_LOG(LS_ERROR) << "Failed to set up video demuxing.";
949 return false;
950 }
951
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700952 last_recv_params_ = recv_params;
953
954 // TODO(pthatcher): Move local streams into VideoSendParameters, and
955 // only give it to the media channel once we have a remote
956 // description too (without a remote description, we won't be able
957 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -0800958 if (!UpdateLocalStreams_w(video->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700959 SafeSetError("Failed to set local video description streams.", error_desc);
960 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000961 }
962
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700963 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700964 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700965 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000966}
967
968bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800969 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000970 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100971 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -0800972 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +0100973 RTC_LOG(LS_INFO) << "Setting remote video description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000974
Steve Antonb1c1de12017-12-21 15:14:30 -0800975 RTC_DCHECK(content);
976 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000977 SafeSetError("Can't find video content in remote description.", error_desc);
978 return false;
979 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000980
Steve Antonb1c1de12017-12-21 15:14:30 -0800981 const VideoContentDescription* video = content->as_video();
982
jbauch5869f502017-06-29 12:31:36 -0700983 RtpHeaderExtensions rtp_header_extensions =
984 GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
985
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700986 VideoSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -0700987 RtpSendParametersFromMediaDescription(video, rtp_header_extensions,
Yves Gerey665174f2018-06-19 15:03:05 +0200988 &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700989 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -0800990 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700991 }
Steve Antonbb50ce52018-03-26 10:24:32 -0700992 send_params.mid = content_name();
skvladdc1c62c2016-03-16 19:07:43 -0700993
994 bool parameters_applied = media_channel()->SetSendParameters(send_params);
995
996 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700997 SafeSetError("Failed to set remote video description send parameters.",
998 error_desc);
999 return false;
1000 }
1001 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001002
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001003 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
1004 // and only give it to the media channel once we have a local
1005 // description too (without a local description, we won't be able to
1006 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001007 if (!UpdateRemoteStreams_w(video->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001008 SafeSetError("Failed to set remote video description streams.", error_desc);
1009 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001010 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001011 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001012 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001013 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001014}
1015
deadbeef953c2ce2017-01-09 14:53:41 -08001016RtpDataChannel::RtpDataChannel(rtc::Thread* worker_thread,
1017 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001018 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001019 std::unique_ptr<DataMediaChannel> media_channel,
deadbeef953c2ce2017-01-09 14:53:41 -08001020 const std::string& content_name,
Zhi Huange830e682018-03-30 10:48:35 -07001021 bool srtp_required,
1022 rtc::CryptoOptions crypto_options)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001023 : BaseChannel(worker_thread,
1024 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001025 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001026 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -07001027 content_name,
Zhi Huange830e682018-03-30 10:48:35 -07001028 srtp_required,
1029 crypto_options) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001030
deadbeef953c2ce2017-01-09 14:53:41 -08001031RtpDataChannel::~RtpDataChannel() {
1032 TRACE_EVENT0("webrtc", "RtpDataChannel::~RtpDataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001033 // this can't be done in the base class, since it calls a virtual
1034 DisableMedia_w();
Zhi Huang0ffe03d2018-03-30 13:17:42 -07001035 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001036}
1037
Zhi Huang2dfc42d2017-12-04 13:38:48 -08001038void RtpDataChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) {
1039 BaseChannel::Init_w(rtp_transport);
1040 media_channel()->SignalDataReceived.connect(this,
1041 &RtpDataChannel::OnDataReceived);
1042 media_channel()->SignalReadyToSend.connect(
1043 this, &RtpDataChannel::OnDataChannelReadyToSend);
1044}
1045
deadbeef953c2ce2017-01-09 14:53:41 -08001046bool RtpDataChannel::SendData(const SendDataParams& params,
1047 const rtc::CopyOnWriteBuffer& payload,
1048 SendDataResult* result) {
stefanf79ade12017-06-02 06:44:03 -07001049 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001050 RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params,
1051 payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001052}
1053
deadbeef953c2ce2017-01-09 14:53:41 -08001054bool RtpDataChannel::CheckDataChannelTypeFromContent(
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001055 const DataContentDescription* content,
1056 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001057 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
1058 (content->protocol() == kMediaProtocolDtlsSctp));
deadbeef953c2ce2017-01-09 14:53:41 -08001059 // It's been set before, but doesn't match. That's bad.
1060 if (is_sctp) {
1061 SafeSetError("Data channel type mismatch. Expected RTP, got SCTP.",
1062 error_desc);
1063 return false;
1064 }
1065 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001066}
1067
deadbeef953c2ce2017-01-09 14:53:41 -08001068bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001069 SdpType type,
deadbeef953c2ce2017-01-09 14:53:41 -08001070 std::string* error_desc) {
1071 TRACE_EVENT0("webrtc", "RtpDataChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001072 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001073 RTC_LOG(LS_INFO) << "Setting local data description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001074
Steve Antonb1c1de12017-12-21 15:14:30 -08001075 RTC_DCHECK(content);
1076 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001077 SafeSetError("Can't find data content in local description.", error_desc);
1078 return false;
1079 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001080
Steve Antonb1c1de12017-12-21 15:14:30 -08001081 const DataContentDescription* data = content->as_data();
1082
deadbeef953c2ce2017-01-09 14:53:41 -08001083 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001084 return false;
1085 }
1086
jbauch5869f502017-06-29 12:31:36 -07001087 RtpHeaderExtensions rtp_header_extensions =
1088 GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
1089
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001090 DataRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07001091 RtpParametersFromMediaDescription(data, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001092 if (!media_channel()->SetRecvParameters(recv_params)) {
1093 SafeSetError("Failed to set remote data description recv parameters.",
1094 error_desc);
1095 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001096 }
deadbeef953c2ce2017-01-09 14:53:41 -08001097 for (const DataCodec& codec : data->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07001098 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001099 }
Zhi Huang365381f2018-04-13 16:44:34 -07001100 // Need to re-register the sink to update the handled payload.
1101 if (!RegisterRtpDemuxerSink()) {
1102 RTC_LOG(LS_ERROR) << "Failed to set up data demuxing.";
1103 return false;
1104 }
1105
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001106 last_recv_params_ = recv_params;
1107
1108 // TODO(pthatcher): Move local streams into DataSendParameters, and
1109 // only give it to the media channel once we have a remote
1110 // description too (without a remote description, we won't be able
1111 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001112 if (!UpdateLocalStreams_w(data->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001113 SafeSetError("Failed to set local data description streams.", error_desc);
1114 return false;
1115 }
1116
1117 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001118 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001119 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001120}
1121
deadbeef953c2ce2017-01-09 14:53:41 -08001122bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001123 SdpType type,
deadbeef953c2ce2017-01-09 14:53:41 -08001124 std::string* error_desc) {
1125 TRACE_EVENT0("webrtc", "RtpDataChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001126 RTC_DCHECK_RUN_ON(worker_thread());
1127 RTC_LOG(LS_INFO) << "Setting remote data description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001128
Steve Antonb1c1de12017-12-21 15:14:30 -08001129 RTC_DCHECK(content);
1130 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001131 SafeSetError("Can't find data content in remote description.", error_desc);
1132 return false;
1133 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001134
Steve Antonb1c1de12017-12-21 15:14:30 -08001135 const DataContentDescription* data = content->as_data();
1136
Zhi Huang801b8682017-11-15 11:36:43 -08001137 // If the remote data doesn't have codecs, it must be empty, so ignore it.
1138 if (!data->has_codecs()) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001139 return true;
1140 }
1141
deadbeef953c2ce2017-01-09 14:53:41 -08001142 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001143 return false;
1144 }
1145
jbauch5869f502017-06-29 12:31:36 -07001146 RtpHeaderExtensions rtp_header_extensions =
1147 GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
1148
Mirko Bonadei675513b2017-11-09 11:09:25 +01001149 RTC_LOG(LS_INFO) << "Setting remote data description";
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001150 DataSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07001151 RtpSendParametersFromMediaDescription<DataCodec>(data, rtp_header_extensions,
Yves Gerey665174f2018-06-19 15:03:05 +02001152 &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001153 if (!media_channel()->SetSendParameters(send_params)) {
1154 SafeSetError("Failed to set remote data description send parameters.",
1155 error_desc);
1156 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001157 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001158 last_send_params_ = send_params;
1159
1160 // TODO(pthatcher): Move remote streams into DataRecvParameters,
1161 // and only give it to the media channel once we have a local
1162 // description too (without a local description, we won't be able to
1163 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001164 if (!UpdateRemoteStreams_w(data->streams(), type, error_desc)) {
Yves Gerey665174f2018-06-19 15:03:05 +02001165 SafeSetError("Failed to set remote data description streams.", error_desc);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001166 return false;
1167 }
1168
1169 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001170 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001171 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001172}
1173
deadbeef953c2ce2017-01-09 14:53:41 -08001174void RtpDataChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001175 // Render incoming data if we're the active call, and we have the local
1176 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001177 bool recv = IsReadyToReceiveMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001178 if (!media_channel()->SetReceive(recv)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001179 RTC_LOG(LS_ERROR) << "Failed to SetReceive on data channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001180 }
1181
1182 // Send outgoing data if we're the active call, we have the remote content,
1183 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001184 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001185 if (!media_channel()->SetSend(send)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001186 RTC_LOG(LS_ERROR) << "Failed to SetSend on data channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001187 }
1188
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001189 // Trigger SignalReadyToSendData asynchronously.
1190 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001191
Mirko Bonadei675513b2017-11-09 11:09:25 +01001192 RTC_LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001193}
1194
deadbeef953c2ce2017-01-09 14:53:41 -08001195void RtpDataChannel::OnMessage(rtc::Message* pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001196 switch (pmsg->message_id) {
1197 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001198 DataChannelReadyToSendMessageData* data =
1199 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00001200 ready_to_send_data_ = data->data();
1201 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001202 delete data;
1203 break;
1204 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001205 case MSG_DATARECEIVED: {
1206 DataReceivedMessageData* data =
1207 static_cast<DataReceivedMessageData*>(pmsg->pdata);
deadbeef953c2ce2017-01-09 14:53:41 -08001208 SignalDataReceived(data->params, data->payload);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001209 delete data;
1210 break;
1211 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001212 default:
1213 BaseChannel::OnMessage(pmsg);
1214 break;
1215 }
1216}
1217
deadbeef953c2ce2017-01-09 14:53:41 -08001218void RtpDataChannel::OnDataReceived(const ReceiveDataParams& params,
1219 const char* data,
1220 size_t len) {
Yves Gerey665174f2018-06-19 15:03:05 +02001221 DataReceivedMessageData* msg = new DataReceivedMessageData(params, data, len);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001222 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001223}
1224
deadbeef953c2ce2017-01-09 14:53:41 -08001225void RtpDataChannel::OnDataChannelReadyToSend(bool writable) {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001226 // This is usded for congestion control to indicate that the stream is ready
1227 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
1228 // that the transport channel is ready.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001229 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001230 new DataChannelReadyToSendMessageData(writable));
1231}
1232
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001233} // namespace cricket