blob: 506a21582f7ae0ce6f4dffa34497ac72b4dc14ee [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -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
Henrik Kjellander15583c12016-02-10 10:53:12 +010011#include "webrtc/api/peerconnection.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
deadbeefeb459812015-12-15 19:24:43 -080013#include <algorithm>
deadbeef0a6c4ca2015-10-06 11:38:28 -070014#include <cctype> // for isdigit
kwiberg0eb15ed2015-12-17 03:04:15 -080015#include <utility>
16#include <vector>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000017
Henrik Kjellander15583c12016-02-10 10:53:12 +010018#include "webrtc/api/audiotrack.h"
19#include "webrtc/api/dtmfsender.h"
20#include "webrtc/api/jsepicecandidate.h"
21#include "webrtc/api/jsepsessiondescription.h"
22#include "webrtc/api/mediaconstraintsinterface.h"
23#include "webrtc/api/mediastream.h"
24#include "webrtc/api/mediastreamobserver.h"
25#include "webrtc/api/mediastreamproxy.h"
26#include "webrtc/api/mediastreamtrackproxy.h"
27#include "webrtc/api/remoteaudiosource.h"
Henrik Kjellander15583c12016-02-10 10:53:12 +010028#include "webrtc/api/rtpreceiver.h"
29#include "webrtc/api/rtpsender.h"
30#include "webrtc/api/streamcollection.h"
perkja3ede6c2016-03-08 01:27:48 +010031#include "webrtc/api/videocapturertracksource.h"
Henrik Kjellander15583c12016-02-10 10:53:12 +010032#include "webrtc/api/videotrack.h"
tfarina5237aaf2015-11-10 23:44:30 -080033#include "webrtc/base/arraysize.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000034#include "webrtc/base/logging.h"
35#include "webrtc/base/stringencode.h"
deadbeefab9b2d12015-10-14 11:33:11 -070036#include "webrtc/base/stringutils.h"
Peter Boström1a9d6152015-12-08 22:15:17 +010037#include "webrtc/base/trace_event.h"
kjellandera96e2d72016-02-04 23:52:28 -080038#include "webrtc/media/sctp/sctpdataengine.h"
tfarina5237aaf2015-11-10 23:44:30 -080039#include "webrtc/p2p/client/basicportallocator.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010040#include "webrtc/pc/channelmanager.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010041#include "webrtc/system_wrappers/include/field_trial.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042
43namespace {
44
deadbeefab9b2d12015-10-14 11:33:11 -070045using webrtc::DataChannel;
46using webrtc::MediaConstraintsInterface;
47using webrtc::MediaStreamInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000048using webrtc::PeerConnectionInterface;
deadbeeffac06552015-11-25 11:26:01 -080049using webrtc::RtpSenderInterface;
deadbeefab9b2d12015-10-14 11:33:11 -070050using webrtc::StreamCollection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051
deadbeefab9b2d12015-10-14 11:33:11 -070052static const char kDefaultStreamLabel[] = "default";
53static const char kDefaultAudioTrackLabel[] = "defaulta0";
54static const char kDefaultVideoTrackLabel[] = "defaultv0";
55
henrike@webrtc.org28e20752013-07-10 00:45:36 +000056// The min number of tokens must present in Turn host uri.
57// e.g. user@turn.example.org
58static const size_t kTurnHostTokensNum = 2;
59// Number of tokens must be preset when TURN uri has transport param.
60static const size_t kTurnTransportTokensNum = 2;
61// The default stun port.
wu@webrtc.org91053e72013-08-10 07:18:04 +000062static const int kDefaultStunPort = 3478;
63static const int kDefaultStunTlsPort = 5349;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064static const char kTransport[] = "transport";
henrike@webrtc.org28e20752013-07-10 00:45:36 +000065
66// NOTE: Must be in the same order as the ServiceType enum.
deadbeef0a6c4ca2015-10-06 11:38:28 -070067static const char* kValidIceServiceTypes[] = {"stun", "stuns", "turn", "turns"};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068
zhihuang8f65cdf2016-05-06 18:40:30 -070069// The length of RTCP CNAMEs.
70static const int kRtcpCnameLength = 16;
71
deadbeef0a6c4ca2015-10-06 11:38:28 -070072// NOTE: A loop below assumes that the first value of this enum is 0 and all
73// other values are incremental.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000074enum ServiceType {
deadbeef0a6c4ca2015-10-06 11:38:28 -070075 STUN = 0, // Indicates a STUN server.
76 STUNS, // Indicates a STUN server used with a TLS session.
77 TURN, // Indicates a TURN server
78 TURNS, // Indicates a TURN server used with a TLS session.
79 INVALID, // Unknown.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000080};
tfarina5237aaf2015-11-10 23:44:30 -080081static_assert(INVALID == arraysize(kValidIceServiceTypes),
deadbeef0a6c4ca2015-10-06 11:38:28 -070082 "kValidIceServiceTypes must have as many strings as ServiceType "
83 "has values.");
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084
85enum {
wu@webrtc.org91053e72013-08-10 07:18:04 +000086 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087 MSG_SET_SESSIONDESCRIPTION_FAILED,
deadbeefab9b2d12015-10-14 11:33:11 -070088 MSG_CREATE_SESSIONDESCRIPTION_FAILED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089 MSG_GETSTATS,
deadbeefbd292462015-12-14 18:15:29 -080090 MSG_FREE_DATACHANNELS,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000091};
92
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000093struct SetSessionDescriptionMsg : public rtc::MessageData {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094 explicit SetSessionDescriptionMsg(
95 webrtc::SetSessionDescriptionObserver* observer)
96 : observer(observer) {
97 }
98
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000099 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserver> observer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100 std::string error;
101};
102
deadbeefab9b2d12015-10-14 11:33:11 -0700103struct CreateSessionDescriptionMsg : public rtc::MessageData {
104 explicit CreateSessionDescriptionMsg(
105 webrtc::CreateSessionDescriptionObserver* observer)
106 : observer(observer) {}
107
108 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer;
109 std::string error;
110};
111
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000112struct GetStatsMsg : public rtc::MessageData {
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000113 GetStatsMsg(webrtc::StatsObserver* observer,
114 webrtc::MediaStreamTrackInterface* track)
115 : observer(observer), track(track) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000116 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000117 rtc::scoped_refptr<webrtc::StatsObserver> observer;
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000118 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119};
120
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000121// |in_str| should be of format
122// stunURI = scheme ":" stun-host [ ":" stun-port ]
123// scheme = "stun" / "stuns"
124// stun-host = IP-literal / IPv4address / reg-name
125// stun-port = *DIGIT
deadbeef0a6c4ca2015-10-06 11:38:28 -0700126//
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000127// draft-petithuguenin-behave-turn-uris-01
128// turnURI = scheme ":" turn-host [ ":" turn-port ]
129// turn-host = username@IP-literal / IPv4address / reg-name
130bool GetServiceTypeAndHostnameFromUri(const std::string& in_str,
131 ServiceType* service_type,
132 std::string* hostname) {
Tommi77d444a2015-04-24 15:38:38 +0200133 const std::string::size_type colonpos = in_str.find(':');
deadbeef0a6c4ca2015-10-06 11:38:28 -0700134 if (colonpos == std::string::npos) {
135 LOG(LS_WARNING) << "Missing ':' in ICE URI: " << in_str;
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000136 return false;
137 }
deadbeef0a6c4ca2015-10-06 11:38:28 -0700138 if ((colonpos + 1) == in_str.length()) {
139 LOG(LS_WARNING) << "Empty hostname in ICE URI: " << in_str;
140 return false;
141 }
142 *service_type = INVALID;
tfarina5237aaf2015-11-10 23:44:30 -0800143 for (size_t i = 0; i < arraysize(kValidIceServiceTypes); ++i) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700144 if (in_str.compare(0, colonpos, kValidIceServiceTypes[i]) == 0) {
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000145 *service_type = static_cast<ServiceType>(i);
146 break;
147 }
148 }
149 if (*service_type == INVALID) {
150 return false;
151 }
152 *hostname = in_str.substr(colonpos + 1, std::string::npos);
153 return true;
154}
155
deadbeef0a6c4ca2015-10-06 11:38:28 -0700156bool ParsePort(const std::string& in_str, int* port) {
157 // Make sure port only contains digits. FromString doesn't check this.
158 for (const char& c : in_str) {
159 if (!std::isdigit(c)) {
160 return false;
161 }
162 }
163 return rtc::FromString(in_str, port);
164}
165
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000166// This method parses IPv6 and IPv4 literal strings, along with hostnames in
167// standard hostname:port format.
168// Consider following formats as correct.
169// |hostname:port|, |[IPV6 address]:port|, |IPv4 address|:port,
deadbeef0a6c4ca2015-10-06 11:38:28 -0700170// |hostname|, |[IPv6 address]|, |IPv4 address|.
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000171bool ParseHostnameAndPortFromString(const std::string& in_str,
172 std::string* host,
173 int* port) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700174 RTC_DCHECK(host->empty());
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000175 if (in_str.at(0) == '[') {
176 std::string::size_type closebracket = in_str.rfind(']');
177 if (closebracket != std::string::npos) {
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000178 std::string::size_type colonpos = in_str.find(':', closebracket);
179 if (std::string::npos != colonpos) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700180 if (!ParsePort(in_str.substr(closebracket + 2, std::string::npos),
181 port)) {
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000182 return false;
183 }
184 }
deadbeef0a6c4ca2015-10-06 11:38:28 -0700185 *host = in_str.substr(1, closebracket - 1);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000186 } else {
187 return false;
188 }
189 } else {
190 std::string::size_type colonpos = in_str.find(':');
191 if (std::string::npos != colonpos) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700192 if (!ParsePort(in_str.substr(colonpos + 1, std::string::npos), port)) {
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000193 return false;
194 }
deadbeef0a6c4ca2015-10-06 11:38:28 -0700195 *host = in_str.substr(0, colonpos);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000196 } else {
197 *host = in_str;
198 }
199 }
deadbeef0a6c4ca2015-10-06 11:38:28 -0700200 return !host->empty();
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000201}
202
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800203// Adds a STUN or TURN server to the appropriate list,
deadbeef0a6c4ca2015-10-06 11:38:28 -0700204// by parsing |url| and using the username/password in |server|.
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200205bool ParseIceServerUrl(const PeerConnectionInterface::IceServer& server,
206 const std::string& url,
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800207 cricket::ServerAddresses* stun_servers,
208 std::vector<cricket::RelayServerConfig>* turn_servers) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000209 // draft-nandakumar-rtcweb-stun-uri-01
210 // stunURI = scheme ":" stun-host [ ":" stun-port ]
211 // scheme = "stun" / "stuns"
212 // stun-host = IP-literal / IPv4address / reg-name
213 // stun-port = *DIGIT
214
215 // draft-petithuguenin-behave-turn-uris-01
216 // turnURI = scheme ":" turn-host [ ":" turn-port ]
217 // [ "?transport=" transport ]
218 // scheme = "turn" / "turns"
219 // transport = "udp" / "tcp" / transport-ext
220 // transport-ext = 1*unreserved
221 // turn-host = IP-literal / IPv4address / reg-name
222 // turn-port = *DIGIT
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800223 RTC_DCHECK(stun_servers != nullptr);
224 RTC_DCHECK(turn_servers != nullptr);
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200225 std::vector<std::string> tokens;
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800226 cricket::ProtocolType turn_transport_type = cricket::PROTO_UDP;
deadbeef0a6c4ca2015-10-06 11:38:28 -0700227 RTC_DCHECK(!url.empty());
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200228 rtc::tokenize(url, '?', &tokens);
229 std::string uri_without_transport = tokens[0];
230 // Let's look into transport= param, if it exists.
231 if (tokens.size() == kTurnTransportTokensNum) { // ?transport= is present.
232 std::string uri_transport_param = tokens[1];
233 rtc::tokenize(uri_transport_param, '=', &tokens);
234 if (tokens[0] == kTransport) {
235 // As per above grammar transport param will be consist of lower case
236 // letters.
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800237 if (!cricket::StringToProto(tokens[1].c_str(), &turn_transport_type) ||
238 (turn_transport_type != cricket::PROTO_UDP &&
239 turn_transport_type != cricket::PROTO_TCP)) {
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200240 LOG(LS_WARNING) << "Transport param should always be udp or tcp.";
deadbeef0a6c4ca2015-10-06 11:38:28 -0700241 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000242 }
243 }
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200244 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000245
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200246 std::string hoststring;
deadbeef0a6c4ca2015-10-06 11:38:28 -0700247 ServiceType service_type;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200248 if (!GetServiceTypeAndHostnameFromUri(uri_without_transport,
249 &service_type,
250 &hoststring)) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700251 LOG(LS_WARNING) << "Invalid transport parameter in ICE URI: " << url;
252 return false;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200253 }
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000254
deadbeef0a6c4ca2015-10-06 11:38:28 -0700255 // GetServiceTypeAndHostnameFromUri should never give an empty hoststring
256 RTC_DCHECK(!hoststring.empty());
Tommi77d444a2015-04-24 15:38:38 +0200257
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200258 // Let's break hostname.
259 tokens.clear();
deadbeef0a6c4ca2015-10-06 11:38:28 -0700260 rtc::tokenize_with_empty_tokens(hoststring, '@', &tokens);
261
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200262 std::string username(server.username);
deadbeef0a6c4ca2015-10-06 11:38:28 -0700263 if (tokens.size() > kTurnHostTokensNum) {
264 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring;
265 return false;
266 }
267 if (tokens.size() == kTurnHostTokensNum) {
268 if (tokens[0].empty() || tokens[1].empty()) {
269 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring;
270 return false;
271 }
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200272 username.assign(rtc::s_url_decode(tokens[0]));
273 hoststring = tokens[1];
274 } else {
275 hoststring = tokens[0];
276 }
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000277
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200278 int port = kDefaultStunPort;
279 if (service_type == TURNS) {
280 port = kDefaultStunTlsPort;
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800281 turn_transport_type = cricket::PROTO_TCP;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200282 }
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000283
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200284 std::string address;
285 if (!ParseHostnameAndPortFromString(hoststring, &address, &port)) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700286 LOG(WARNING) << "Invalid hostname format: " << uri_without_transport;
287 return false;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200288 }
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000289
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200290 if (port <= 0 || port > 0xffff) {
291 LOG(WARNING) << "Invalid port: " << port;
deadbeef0a6c4ca2015-10-06 11:38:28 -0700292 return false;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200293 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000294
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200295 switch (service_type) {
296 case STUN:
297 case STUNS:
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800298 stun_servers->insert(rtc::SocketAddress(address, port));
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200299 break;
300 case TURN:
301 case TURNS: {
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200302 bool secure = (service_type == TURNS);
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800303 turn_servers->push_back(
304 cricket::RelayServerConfig(address, port, username, server.password,
305 turn_transport_type, secure));
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200306 break;
307 }
308 case INVALID:
309 default:
310 LOG(WARNING) << "Configuration not supported: " << url;
311 return false;
312 }
313 return true;
314}
315
deadbeefab9b2d12015-10-14 11:33:11 -0700316// Check if we can send |new_stream| on a PeerConnection.
317bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams,
318 webrtc::MediaStreamInterface* new_stream) {
319 if (!new_stream || !current_streams) {
320 return false;
321 }
322 if (current_streams->find(new_stream->label()) != nullptr) {
323 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label()
324 << " is already added.";
325 return false;
326 }
327 return true;
328}
329
330bool MediaContentDirectionHasSend(cricket::MediaContentDirection dir) {
331 return dir == cricket::MD_SENDONLY || dir == cricket::MD_SENDRECV;
332}
333
deadbeef5e97fb52015-10-15 12:49:08 -0700334// If the direction is "recvonly" or "inactive", treat the description
335// as containing no streams.
336// See: https://code.google.com/p/webrtc/issues/detail?id=5054
337std::vector<cricket::StreamParams> GetActiveStreams(
338 const cricket::MediaContentDescription* desc) {
339 return MediaContentDirectionHasSend(desc->direction())
340 ? desc->streams()
341 : std::vector<cricket::StreamParams>();
342}
343
deadbeefab9b2d12015-10-14 11:33:11 -0700344bool IsValidOfferToReceiveMedia(int value) {
345 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options;
346 return (value >= Options::kUndefined) &&
347 (value <= Options::kMaxOfferToReceiveMedia);
348}
349
350// Add the stream and RTP data channel info to |session_options|.
deadbeeffac06552015-11-25 11:26:01 -0800351void AddSendStreams(
352 cricket::MediaSessionOptions* session_options,
353 const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& senders,
354 const std::map<std::string, rtc::scoped_refptr<DataChannel>>&
355 rtp_data_channels) {
deadbeefab9b2d12015-10-14 11:33:11 -0700356 session_options->streams.clear();
deadbeeffac06552015-11-25 11:26:01 -0800357 for (const auto& sender : senders) {
358 session_options->AddSendStream(sender->media_type(), sender->id(),
359 sender->stream_id());
deadbeefab9b2d12015-10-14 11:33:11 -0700360 }
361
362 // Check for data channels.
363 for (const auto& kv : rtp_data_channels) {
364 const DataChannel* channel = kv.second;
365 if (channel->state() == DataChannel::kConnecting ||
366 channel->state() == DataChannel::kOpen) {
367 // |streamid| and |sync_label| are both set to the DataChannel label
368 // here so they can be signaled the same way as MediaStreams and Tracks.
369 // For MediaStreams, the sync_label is the MediaStream label and the
370 // track label is the same as |streamid|.
371 const std::string& streamid = channel->label();
372 const std::string& sync_label = channel->label();
373 session_options->AddSendStream(cricket::MEDIA_TYPE_DATA, streamid,
374 sync_label);
375 }
376 }
377}
378
deadbeef0a6c4ca2015-10-06 11:38:28 -0700379} // namespace
380
381namespace webrtc {
382
zhihuang8f65cdf2016-05-06 18:40:30 -0700383// Generate a RTCP CNAME when a PeerConnection is created.
384std::string GenerateRtcpCname() {
385 std::string cname;
386 if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) {
387 LOG(LS_ERROR) << "Failed to generate CNAME.";
388 RTC_DCHECK(false);
389 }
390 return cname;
391}
392
htaa2a49d92016-03-04 02:51:39 -0800393bool ExtractMediaSessionOptions(
deadbeefab9b2d12015-10-14 11:33:11 -0700394 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
htaaac2dea2016-03-10 13:35:55 -0800395 bool is_offer,
deadbeefab9b2d12015-10-14 11:33:11 -0700396 cricket::MediaSessionOptions* session_options) {
397 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
398 if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) ||
399 !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) {
400 return false;
401 }
402
htaaac2dea2016-03-10 13:35:55 -0800403 // If constraints don't prevent us, we always accept video.
deadbeefc80741f2015-10-22 13:14:45 -0700404 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
deadbeefab9b2d12015-10-14 11:33:11 -0700405 session_options->recv_audio = (rtc_options.offer_to_receive_audio > 0);
htaaac2dea2016-03-10 13:35:55 -0800406 } else {
407 session_options->recv_audio = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700408 }
htaaac2dea2016-03-10 13:35:55 -0800409 // For offers, we only offer video if we have it or it's forced by options.
410 // For answers, we will always accept video (if offered).
deadbeefc80741f2015-10-22 13:14:45 -0700411 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
deadbeefab9b2d12015-10-14 11:33:11 -0700412 session_options->recv_video = (rtc_options.offer_to_receive_video > 0);
htaaac2dea2016-03-10 13:35:55 -0800413 } else if (is_offer) {
414 session_options->recv_video = false;
415 } else {
416 session_options->recv_video = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700417 }
418
419 session_options->vad_enabled = rtc_options.voice_activity_detection;
deadbeefc80741f2015-10-22 13:14:45 -0700420 session_options->bundle_enabled = rtc_options.use_rtp_mux;
deadbeef0ed85b22016-02-23 17:24:52 -0800421 for (auto& kv : session_options->transport_options) {
422 kv.second.ice_restart = rtc_options.ice_restart;
423 }
deadbeefab9b2d12015-10-14 11:33:11 -0700424
425 return true;
426}
427
428bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints,
429 cricket::MediaSessionOptions* session_options) {
430 bool value = false;
431 size_t mandatory_constraints_satisfied = 0;
432
433 // kOfferToReceiveAudio defaults to true according to spec.
434 if (!FindConstraint(constraints,
435 MediaConstraintsInterface::kOfferToReceiveAudio, &value,
436 &mandatory_constraints_satisfied) ||
437 value) {
438 session_options->recv_audio = true;
439 }
440
441 // kOfferToReceiveVideo defaults to false according to spec. But
442 // if it is an answer and video is offered, we should still accept video
443 // per default.
444 value = false;
445 if (!FindConstraint(constraints,
446 MediaConstraintsInterface::kOfferToReceiveVideo, &value,
447 &mandatory_constraints_satisfied) ||
448 value) {
449 session_options->recv_video = true;
450 }
451
452 if (FindConstraint(constraints,
453 MediaConstraintsInterface::kVoiceActivityDetection, &value,
454 &mandatory_constraints_satisfied)) {
455 session_options->vad_enabled = value;
456 }
457
458 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
459 &mandatory_constraints_satisfied)) {
460 session_options->bundle_enabled = value;
461 } else {
462 // kUseRtpMux defaults to true according to spec.
463 session_options->bundle_enabled = true;
464 }
deadbeefab9b2d12015-10-14 11:33:11 -0700465
deadbeef0ed85b22016-02-23 17:24:52 -0800466 bool ice_restart = false;
deadbeefab9b2d12015-10-14 11:33:11 -0700467 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
468 &value, &mandatory_constraints_satisfied)) {
deadbeefab9b2d12015-10-14 11:33:11 -0700469 // kIceRestart defaults to false according to spec.
deadbeef0ed85b22016-02-23 17:24:52 -0800470 ice_restart = true;
471 }
472 for (auto& kv : session_options->transport_options) {
473 kv.second.ice_restart = ice_restart;
deadbeefab9b2d12015-10-14 11:33:11 -0700474 }
475
476 if (!constraints) {
477 return true;
478 }
479 return mandatory_constraints_satisfied == constraints->GetMandatory().size();
480}
481
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200482bool ParseIceServers(const PeerConnectionInterface::IceServers& servers,
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800483 cricket::ServerAddresses* stun_servers,
484 std::vector<cricket::RelayServerConfig>* turn_servers) {
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200485 for (const webrtc::PeerConnectionInterface::IceServer& server : servers) {
486 if (!server.urls.empty()) {
487 for (const std::string& url : server.urls) {
Joachim Bauchd935f912015-05-29 22:14:21 +0200488 if (url.empty()) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700489 LOG(LS_ERROR) << "Empty uri.";
490 return false;
Joachim Bauchd935f912015-05-29 22:14:21 +0200491 }
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800492 if (!ParseIceServerUrl(server, url, stun_servers, turn_servers)) {
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200493 return false;
494 }
495 }
496 } else if (!server.uri.empty()) {
497 // Fallback to old .uri if new .urls isn't present.
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800498 if (!ParseIceServerUrl(server, server.uri, stun_servers, turn_servers)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000499 return false;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200500 }
501 } else {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700502 LOG(LS_ERROR) << "Empty uri.";
503 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000504 }
505 }
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800506 // Candidates must have unique priorities, so that connectivity checks
507 // are performed in a well-defined order.
508 int priority = static_cast<int>(turn_servers->size() - 1);
509 for (cricket::RelayServerConfig& turn_server : *turn_servers) {
510 // First in the list gets highest priority.
511 turn_server.priority = priority--;
512 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000513 return true;
514}
515
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000516PeerConnection::PeerConnection(PeerConnectionFactory* factory)
517 : factory_(factory),
518 observer_(NULL),
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +0000519 uma_observer_(NULL),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000520 signaling_state_(kStable),
521 ice_state_(kIceNew),
522 ice_connection_state_(kIceConnectionNew),
deadbeefab9b2d12015-10-14 11:33:11 -0700523 ice_gathering_state_(kIceGatheringNew),
zhihuang8f65cdf2016-05-06 18:40:30 -0700524 rtcp_cname_(GenerateRtcpCname()),
deadbeefab9b2d12015-10-14 11:33:11 -0700525 local_streams_(StreamCollection::Create()),
526 remote_streams_(StreamCollection::Create()) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000527
528PeerConnection::~PeerConnection() {
Peter Boström1a9d6152015-12-08 22:15:17 +0100529 TRACE_EVENT0("webrtc", "PeerConnection::~PeerConnection");
deadbeef0a6c4ca2015-10-06 11:38:28 -0700530 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeef70ab1a12015-09-28 16:53:55 -0700531 // Need to detach RTP senders/receivers from WebRtcSession,
532 // since it's about to be destroyed.
533 for (const auto& sender : senders_) {
534 sender->Stop();
535 }
536 for (const auto& receiver : receivers_) {
537 receiver->Stop();
538 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000539}
540
541bool PeerConnection::Initialize(
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000542 const PeerConnectionInterface::RTCConfiguration& configuration,
kwibergd1fe2812016-04-27 06:47:29 -0700543 std::unique_ptr<cricket::PortAllocator> allocator,
544 std::unique_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
deadbeef653b8e02015-11-11 12:55:10 -0800545 PeerConnectionObserver* observer) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100546 TRACE_EVENT0("webrtc", "PeerConnection::Initialize");
deadbeef653b8e02015-11-11 12:55:10 -0800547 RTC_DCHECK(observer != nullptr);
548 if (!observer) {
549 return false;
550 }
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000551 observer_ = observer;
552
kwiberg0eb15ed2015-12-17 03:04:15 -0800553 port_allocator_ = std::move(allocator);
deadbeef653b8e02015-11-11 12:55:10 -0800554
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800555 cricket::ServerAddresses stun_servers;
556 std::vector<cricket::RelayServerConfig> turn_servers;
557 if (!ParseIceServers(configuration.servers, &stun_servers, &turn_servers)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000558 return false;
559 }
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800560 port_allocator_->SetIceServers(stun_servers, turn_servers);
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000561
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000562 // To handle both internal and externally created port allocator, we will
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000563 // enable BUNDLE here.
braveyao@webrtc.org1732df62014-10-27 03:01:37 +0000564 int portallocator_flags = port_allocator_->flags();
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700565 portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET |
guoweis@webrtc.orgbbce5ef2015-03-05 04:38:29 +0000566 cricket::PORTALLOCATOR_ENABLE_IPV6;
htaa2a49d92016-03-04 02:51:39 -0800567 // If the disable-IPv6 flag was specified, we'll not override it
568 // by experiment.
569 if (configuration.disable_ipv6) {
570 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
guoweis@webrtc.org2c1bcea2014-09-23 16:23:02 +0000571 } else if (webrtc::field_trial::FindFullName("WebRTC-IPv6Default") ==
guoweis@webrtc.orgbbce5ef2015-03-05 04:38:29 +0000572 "Disabled") {
573 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000574 }
575
Jiayang Liucac1b382015-04-30 12:35:24 -0700576 if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) {
577 portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP;
578 LOG(LS_INFO) << "TCP candidates are disabled.";
579 }
580
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000581 port_allocator_->set_flags(portallocator_flags);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000582 // No step delay is used while allocating ports.
583 port_allocator_->set_step_delay(cricket::kMinimumStepDelay);
584
nissec36b31b2016-04-11 23:25:29 -0700585 media_controller_.reset(
586 factory_->CreateMediaController(configuration.media_config));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000587
stefanc1aeaf02015-10-15 07:26:07 -0700588 session_.reset(
589 new WebRtcSession(media_controller_.get(), factory_->signaling_thread(),
590 factory_->worker_thread(), port_allocator_.get()));
deadbeefab9b2d12015-10-14 11:33:11 -0700591 stats_.reset(new StatsCollector(this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000592
593 // Initialize the WebRtcSession. It creates transport channels etc.
htaa2a49d92016-03-04 02:51:39 -0800594 if (!session_->Initialize(factory_->options(), std::move(dtls_identity_store),
595 configuration)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000596 return false;
deadbeefab9b2d12015-10-14 11:33:11 -0700597 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000598
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000599 // Register PeerConnection as receiver of local ice candidates.
600 // All the callbacks will be posted to the application from PeerConnection.
601 session_->RegisterIceObserver(this);
602 session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange);
deadbeefab9b2d12015-10-14 11:33:11 -0700603 session_->SignalVoiceChannelDestroyed.connect(
604 this, &PeerConnection::OnVoiceChannelDestroyed);
605 session_->SignalVideoChannelDestroyed.connect(
606 this, &PeerConnection::OnVideoChannelDestroyed);
607 session_->SignalDataChannelCreated.connect(
608 this, &PeerConnection::OnDataChannelCreated);
609 session_->SignalDataChannelDestroyed.connect(
610 this, &PeerConnection::OnDataChannelDestroyed);
611 session_->SignalDataChannelOpenMessage.connect(
612 this, &PeerConnection::OnDataChannelOpenMessage);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000613 return true;
614}
615
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000616rtc::scoped_refptr<StreamCollectionInterface>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000617PeerConnection::local_streams() {
deadbeefab9b2d12015-10-14 11:33:11 -0700618 return local_streams_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000619}
620
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000621rtc::scoped_refptr<StreamCollectionInterface>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000622PeerConnection::remote_streams() {
deadbeefab9b2d12015-10-14 11:33:11 -0700623 return remote_streams_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000624}
625
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000626bool PeerConnection::AddStream(MediaStreamInterface* local_stream) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100627 TRACE_EVENT0("webrtc", "PeerConnection::AddStream");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000628 if (IsClosed()) {
629 return false;
630 }
deadbeefab9b2d12015-10-14 11:33:11 -0700631 if (!CanAddLocalMediaStream(local_streams_, local_stream)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000632 return false;
633 }
deadbeefab9b2d12015-10-14 11:33:11 -0700634
635 local_streams_->AddStream(local_stream);
deadbeefeb459812015-12-15 19:24:43 -0800636 MediaStreamObserver* observer = new MediaStreamObserver(local_stream);
637 observer->SignalAudioTrackAdded.connect(this,
638 &PeerConnection::OnAudioTrackAdded);
639 observer->SignalAudioTrackRemoved.connect(
640 this, &PeerConnection::OnAudioTrackRemoved);
641 observer->SignalVideoTrackAdded.connect(this,
642 &PeerConnection::OnVideoTrackAdded);
643 observer->SignalVideoTrackRemoved.connect(
644 this, &PeerConnection::OnVideoTrackRemoved);
kwibergd1fe2812016-04-27 06:47:29 -0700645 stream_observers_.push_back(std::unique_ptr<MediaStreamObserver>(observer));
deadbeefab9b2d12015-10-14 11:33:11 -0700646
deadbeefab9b2d12015-10-14 11:33:11 -0700647 for (const auto& track : local_stream->GetAudioTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800648 OnAudioTrackAdded(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700649 }
650 for (const auto& track : local_stream->GetVideoTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800651 OnVideoTrackAdded(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700652 }
653
tommi@webrtc.org03505bc2014-07-14 20:15:26 +0000654 stats_->AddStream(local_stream);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000655 observer_->OnRenegotiationNeeded();
656 return true;
657}
658
659void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100660 TRACE_EVENT0("webrtc", "PeerConnection::RemoveStream");
deadbeefab9b2d12015-10-14 11:33:11 -0700661 for (const auto& track : local_stream->GetAudioTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800662 OnAudioTrackRemoved(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700663 }
664 for (const auto& track : local_stream->GetVideoTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800665 OnVideoTrackRemoved(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700666 }
667
668 local_streams_->RemoveStream(local_stream);
deadbeefeb459812015-12-15 19:24:43 -0800669 stream_observers_.erase(
670 std::remove_if(
671 stream_observers_.begin(), stream_observers_.end(),
kwibergd1fe2812016-04-27 06:47:29 -0700672 [local_stream](const std::unique_ptr<MediaStreamObserver>& observer) {
deadbeefeb459812015-12-15 19:24:43 -0800673 return observer->stream()->label().compare(local_stream->label()) ==
674 0;
675 }),
676 stream_observers_.end());
deadbeefab9b2d12015-10-14 11:33:11 -0700677
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000678 if (IsClosed()) {
679 return;
680 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681 observer_->OnRenegotiationNeeded();
682}
683
deadbeefe1f9d832016-01-14 15:35:42 -0800684rtc::scoped_refptr<RtpSenderInterface> PeerConnection::AddTrack(
685 MediaStreamTrackInterface* track,
686 std::vector<MediaStreamInterface*> streams) {
687 TRACE_EVENT0("webrtc", "PeerConnection::AddTrack");
688 if (IsClosed()) {
689 return nullptr;
690 }
691 if (streams.size() >= 2) {
692 LOG(LS_ERROR)
693 << "Adding a track with two streams is not currently supported.";
694 return nullptr;
695 }
696 // TODO(deadbeef): Support adding a track to two different senders.
697 if (FindSenderForTrack(track) != senders_.end()) {
698 LOG(LS_ERROR) << "Sender for track " << track->id() << " already exists.";
699 return nullptr;
700 }
701
702 // TODO(deadbeef): Support adding a track to multiple streams.
703 rtc::scoped_refptr<RtpSenderInterface> new_sender;
704 if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
705 new_sender = RtpSenderProxy::Create(
706 signaling_thread(),
707 new AudioRtpSender(static_cast<AudioTrackInterface*>(track),
708 session_.get(), stats_.get()));
709 if (!streams.empty()) {
710 new_sender->set_stream_id(streams[0]->label());
711 }
712 const TrackInfo* track_info = FindTrackInfo(
713 local_audio_tracks_, new_sender->stream_id(), track->id());
714 if (track_info) {
715 new_sender->SetSsrc(track_info->ssrc);
716 }
717 } else if (track->kind() == MediaStreamTrackInterface::kVideoKind) {
718 new_sender = RtpSenderProxy::Create(
719 signaling_thread(),
720 new VideoRtpSender(static_cast<VideoTrackInterface*>(track),
721 session_.get()));
722 if (!streams.empty()) {
723 new_sender->set_stream_id(streams[0]->label());
724 }
725 const TrackInfo* track_info = FindTrackInfo(
726 local_video_tracks_, new_sender->stream_id(), track->id());
727 if (track_info) {
728 new_sender->SetSsrc(track_info->ssrc);
729 }
730 } else {
731 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << track->kind();
732 return rtc::scoped_refptr<RtpSenderInterface>();
733 }
734
735 senders_.push_back(new_sender);
736 observer_->OnRenegotiationNeeded();
737 return new_sender;
738}
739
740bool PeerConnection::RemoveTrack(RtpSenderInterface* sender) {
741 TRACE_EVENT0("webrtc", "PeerConnection::RemoveTrack");
742 if (IsClosed()) {
743 return false;
744 }
745
746 auto it = std::find(senders_.begin(), senders_.end(), sender);
747 if (it == senders_.end()) {
748 LOG(LS_ERROR) << "Couldn't find sender " << sender->id() << " to remove.";
749 return false;
750 }
751 (*it)->Stop();
752 senders_.erase(it);
753
754 observer_->OnRenegotiationNeeded();
755 return true;
756}
757
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000758rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000759 AudioTrackInterface* track) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100760 TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000761 if (!track) {
762 LOG(LS_ERROR) << "CreateDtmfSender - track is NULL.";
763 return NULL;
764 }
deadbeefab9b2d12015-10-14 11:33:11 -0700765 if (!local_streams_->FindAudioTrack(track->id())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000766 LOG(LS_ERROR) << "CreateDtmfSender is called with a non local audio track.";
767 return NULL;
768 }
769
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000770 rtc::scoped_refptr<DtmfSenderInterface> sender(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000771 DtmfSender::Create(track, signaling_thread(), session_.get()));
772 if (!sender.get()) {
773 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create.";
774 return NULL;
775 }
776 return DtmfSenderProxy::Create(signaling_thread(), sender.get());
777}
778
deadbeeffac06552015-11-25 11:26:01 -0800779rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
deadbeefbd7d8f72015-12-18 16:58:44 -0800780 const std::string& kind,
781 const std::string& stream_id) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100782 TRACE_EVENT0("webrtc", "PeerConnection::CreateSender");
deadbeefe1f9d832016-01-14 15:35:42 -0800783 rtc::scoped_refptr<RtpSenderInterface> new_sender;
deadbeeffac06552015-11-25 11:26:01 -0800784 if (kind == MediaStreamTrackInterface::kAudioKind) {
deadbeefe1f9d832016-01-14 15:35:42 -0800785 new_sender = RtpSenderProxy::Create(
786 signaling_thread(), new AudioRtpSender(session_.get(), stats_.get()));
deadbeeffac06552015-11-25 11:26:01 -0800787 } else if (kind == MediaStreamTrackInterface::kVideoKind) {
deadbeefe1f9d832016-01-14 15:35:42 -0800788 new_sender = RtpSenderProxy::Create(signaling_thread(),
789 new VideoRtpSender(session_.get()));
deadbeeffac06552015-11-25 11:26:01 -0800790 } else {
791 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind;
deadbeefe1f9d832016-01-14 15:35:42 -0800792 return new_sender;
deadbeeffac06552015-11-25 11:26:01 -0800793 }
deadbeefbd7d8f72015-12-18 16:58:44 -0800794 if (!stream_id.empty()) {
795 new_sender->set_stream_id(stream_id);
796 }
deadbeeffac06552015-11-25 11:26:01 -0800797 senders_.push_back(new_sender);
deadbeefe1f9d832016-01-14 15:35:42 -0800798 return new_sender;
deadbeeffac06552015-11-25 11:26:01 -0800799}
800
deadbeef70ab1a12015-09-28 16:53:55 -0700801std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders()
802 const {
deadbeefe1f9d832016-01-14 15:35:42 -0800803 return senders_;
deadbeef70ab1a12015-09-28 16:53:55 -0700804}
805
806std::vector<rtc::scoped_refptr<RtpReceiverInterface>>
807PeerConnection::GetReceivers() const {
deadbeefe1f9d832016-01-14 15:35:42 -0800808 return receivers_;
deadbeef70ab1a12015-09-28 16:53:55 -0700809}
810
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000811bool PeerConnection::GetStats(StatsObserver* observer,
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000812 MediaStreamTrackInterface* track,
813 StatsOutputLevel level) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100814 TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
deadbeef0a6c4ca2015-10-06 11:38:28 -0700815 RTC_DCHECK(signaling_thread()->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000816 if (!VERIFY(observer != NULL)) {
817 LOG(LS_ERROR) << "GetStats - observer is NULL.";
818 return false;
819 }
820
tommi@webrtc.org03505bc2014-07-14 20:15:26 +0000821 stats_->UpdateStats(level);
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000822 signaling_thread()->Post(this, MSG_GETSTATS,
823 new GetStatsMsg(observer, track));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000824 return true;
825}
826
827PeerConnectionInterface::SignalingState PeerConnection::signaling_state() {
828 return signaling_state_;
829}
830
831PeerConnectionInterface::IceState PeerConnection::ice_state() {
832 return ice_state_;
833}
834
835PeerConnectionInterface::IceConnectionState
836PeerConnection::ice_connection_state() {
837 return ice_connection_state_;
838}
839
840PeerConnectionInterface::IceGatheringState
841PeerConnection::ice_gathering_state() {
842 return ice_gathering_state_;
843}
844
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000845rtc::scoped_refptr<DataChannelInterface>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000846PeerConnection::CreateDataChannel(
847 const std::string& label,
848 const DataChannelInit* config) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100849 TRACE_EVENT0("webrtc", "PeerConnection::CreateDataChannel");
deadbeefab9b2d12015-10-14 11:33:11 -0700850 bool first_datachannel = !HasDataChannels();
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +0000851
kwibergd1fe2812016-04-27 06:47:29 -0700852 std::unique_ptr<InternalDataChannelInit> internal_config;
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000853 if (config) {
854 internal_config.reset(new InternalDataChannelInit(*config));
855 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000856 rtc::scoped_refptr<DataChannelInterface> channel(
deadbeefab9b2d12015-10-14 11:33:11 -0700857 InternalCreateDataChannel(label, internal_config.get()));
858 if (!channel.get()) {
859 return nullptr;
860 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +0000862 // Trigger the onRenegotiationNeeded event for every new RTP DataChannel, or
863 // the first SCTP DataChannel.
864 if (session_->data_channel_type() == cricket::DCT_RTP || first_datachannel) {
865 observer_->OnRenegotiationNeeded();
866 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000867
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000868 return DataChannelProxy::Create(signaling_thread(), channel.get());
869}
870
871void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
872 const MediaConstraintsInterface* constraints) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100873 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer");
deadbeefab9b2d12015-10-14 11:33:11 -0700874 if (!VERIFY(observer != nullptr)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000875 LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
876 return;
877 }
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000878 RTCOfferAnswerOptions options;
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000879
880 bool value;
881 size_t mandatory_constraints = 0;
882
883 if (FindConstraint(constraints,
884 MediaConstraintsInterface::kOfferToReceiveAudio,
885 &value,
886 &mandatory_constraints)) {
887 options.offer_to_receive_audio =
888 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
889 }
890
891 if (FindConstraint(constraints,
892 MediaConstraintsInterface::kOfferToReceiveVideo,
893 &value,
894 &mandatory_constraints)) {
895 options.offer_to_receive_video =
896 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
897 }
898
899 if (FindConstraint(constraints,
900 MediaConstraintsInterface::kVoiceActivityDetection,
901 &value,
902 &mandatory_constraints)) {
903 options.voice_activity_detection = value;
904 }
905
906 if (FindConstraint(constraints,
907 MediaConstraintsInterface::kIceRestart,
908 &value,
909 &mandatory_constraints)) {
910 options.ice_restart = value;
911 }
912
913 if (FindConstraint(constraints,
914 MediaConstraintsInterface::kUseRtpMux,
915 &value,
916 &mandatory_constraints)) {
917 options.use_rtp_mux = value;
918 }
919
920 CreateOffer(observer, options);
921}
922
923void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
924 const RTCOfferAnswerOptions& options) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100925 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer");
deadbeefab9b2d12015-10-14 11:33:11 -0700926 if (!VERIFY(observer != nullptr)) {
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000927 LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
928 return;
929 }
deadbeefab9b2d12015-10-14 11:33:11 -0700930
931 cricket::MediaSessionOptions session_options;
932 if (!GetOptionsForOffer(options, &session_options)) {
933 std::string error = "CreateOffer called with invalid options.";
934 LOG(LS_ERROR) << error;
935 PostCreateSessionDescriptionFailure(observer, error);
936 return;
937 }
938
939 session_->CreateOffer(observer, options, session_options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000940}
941
942void PeerConnection::CreateAnswer(
943 CreateSessionDescriptionObserver* observer,
944 const MediaConstraintsInterface* constraints) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100945 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
deadbeefab9b2d12015-10-14 11:33:11 -0700946 if (!VERIFY(observer != nullptr)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000947 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
948 return;
949 }
deadbeefab9b2d12015-10-14 11:33:11 -0700950
951 cricket::MediaSessionOptions session_options;
952 if (!GetOptionsForAnswer(constraints, &session_options)) {
953 std::string error = "CreateAnswer called with invalid constraints.";
954 LOG(LS_ERROR) << error;
955 PostCreateSessionDescriptionFailure(observer, error);
956 return;
957 }
958
htaa2a49d92016-03-04 02:51:39 -0800959 session_->CreateAnswer(observer, session_options);
960}
961
962void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer,
963 const RTCOfferAnswerOptions& options) {
964 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
965 if (!VERIFY(observer != nullptr)) {
966 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
967 return;
968 }
969
970 cricket::MediaSessionOptions session_options;
971 if (!GetOptionsForAnswer(options, &session_options)) {
972 std::string error = "CreateAnswer called with invalid options.";
973 LOG(LS_ERROR) << error;
974 PostCreateSessionDescriptionFailure(observer, error);
975 return;
976 }
977
978 session_->CreateAnswer(observer, session_options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000979}
980
981void PeerConnection::SetLocalDescription(
982 SetSessionDescriptionObserver* observer,
983 SessionDescriptionInterface* desc) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100984 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription");
deadbeefab9b2d12015-10-14 11:33:11 -0700985 if (!VERIFY(observer != nullptr)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL.";
987 return;
988 }
989 if (!desc) {
990 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
991 return;
992 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000993 // Update stats here so that we have the most recent stats for tracks and
994 // streams that might be removed by updating the session description.
tommi@webrtc.org03505bc2014-07-14 20:15:26 +0000995 stats_->UpdateStats(kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000996 std::string error;
997 if (!session_->SetLocalDescription(desc, &error)) {
998 PostSetSessionDescriptionFailure(observer, error);
999 return;
1000 }
deadbeefab9b2d12015-10-14 11:33:11 -07001001
1002 // If setting the description decided our SSL role, allocate any necessary
1003 // SCTP sids.
1004 rtc::SSLRole role;
1005 if (session_->data_channel_type() == cricket::DCT_SCTP &&
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001006 session_->GetSslRole(session_->data_channel(), &role)) {
deadbeefab9b2d12015-10-14 11:33:11 -07001007 AllocateSctpSids(role);
1008 }
1009
1010 // Update state and SSRC of local MediaStreams and DataChannels based on the
1011 // local session description.
1012 const cricket::ContentInfo* audio_content =
1013 GetFirstAudioContent(desc->description());
1014 if (audio_content) {
deadbeeffaac4972015-11-12 15:33:07 -08001015 if (audio_content->rejected) {
1016 RemoveTracks(cricket::MEDIA_TYPE_AUDIO);
1017 } else {
1018 const cricket::AudioContentDescription* audio_desc =
1019 static_cast<const cricket::AudioContentDescription*>(
1020 audio_content->description);
1021 UpdateLocalTracks(audio_desc->streams(), audio_desc->type());
1022 }
deadbeefab9b2d12015-10-14 11:33:11 -07001023 }
1024
1025 const cricket::ContentInfo* video_content =
1026 GetFirstVideoContent(desc->description());
1027 if (video_content) {
deadbeeffaac4972015-11-12 15:33:07 -08001028 if (video_content->rejected) {
1029 RemoveTracks(cricket::MEDIA_TYPE_VIDEO);
1030 } else {
1031 const cricket::VideoContentDescription* video_desc =
1032 static_cast<const cricket::VideoContentDescription*>(
1033 video_content->description);
1034 UpdateLocalTracks(video_desc->streams(), video_desc->type());
1035 }
deadbeefab9b2d12015-10-14 11:33:11 -07001036 }
1037
1038 const cricket::ContentInfo* data_content =
1039 GetFirstDataContent(desc->description());
1040 if (data_content) {
1041 const cricket::DataContentDescription* data_desc =
1042 static_cast<const cricket::DataContentDescription*>(
1043 data_content->description);
1044 if (rtc::starts_with(data_desc->protocol().data(),
1045 cricket::kMediaProtocolRtpPrefix)) {
1046 UpdateLocalRtpDataChannels(data_desc->streams());
1047 }
1048 }
1049
1050 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001051 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
deadbeefab9b2d12015-10-14 11:33:11 -07001052
deadbeefcbecd352015-09-23 11:50:27 -07001053 // MaybeStartGathering needs to be called after posting
1054 // MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates
1055 // before signaling that SetLocalDescription completed.
1056 session_->MaybeStartGathering();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001057}
1058
1059void PeerConnection::SetRemoteDescription(
1060 SetSessionDescriptionObserver* observer,
1061 SessionDescriptionInterface* desc) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001062 TRACE_EVENT0("webrtc", "PeerConnection::SetRemoteDescription");
deadbeefab9b2d12015-10-14 11:33:11 -07001063 if (!VERIFY(observer != nullptr)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001064 LOG(LS_ERROR) << "SetRemoteDescription - observer is NULL.";
1065 return;
1066 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001067 if (!desc) {
1068 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
1069 return;
1070 }
1071 // Update stats here so that we have the most recent stats for tracks and
1072 // streams that might be removed by updating the session description.
tommi@webrtc.org03505bc2014-07-14 20:15:26 +00001073 stats_->UpdateStats(kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001074 std::string error;
1075 if (!session_->SetRemoteDescription(desc, &error)) {
1076 PostSetSessionDescriptionFailure(observer, error);
1077 return;
1078 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001079
deadbeefab9b2d12015-10-14 11:33:11 -07001080 // If setting the description decided our SSL role, allocate any necessary
1081 // SCTP sids.
1082 rtc::SSLRole role;
1083 if (session_->data_channel_type() == cricket::DCT_SCTP &&
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001084 session_->GetSslRole(session_->data_channel(), &role)) {
deadbeefab9b2d12015-10-14 11:33:11 -07001085 AllocateSctpSids(role);
1086 }
1087
1088 const cricket::SessionDescription* remote_desc = desc->description();
deadbeefbda7e0b2015-12-08 17:13:40 -08001089 const cricket::ContentInfo* audio_content = GetFirstAudioContent(remote_desc);
1090 const cricket::ContentInfo* video_content = GetFirstVideoContent(remote_desc);
1091 const cricket::AudioContentDescription* audio_desc =
1092 GetFirstAudioContentDescription(remote_desc);
1093 const cricket::VideoContentDescription* video_desc =
1094 GetFirstVideoContentDescription(remote_desc);
1095 const cricket::DataContentDescription* data_desc =
1096 GetFirstDataContentDescription(remote_desc);
1097
1098 // Check if the descriptions include streams, just in case the peer supports
1099 // MSID, but doesn't indicate so with "a=msid-semantic".
1100 if (remote_desc->msid_supported() ||
1101 (audio_desc && !audio_desc->streams().empty()) ||
1102 (video_desc && !video_desc->streams().empty())) {
1103 remote_peer_supports_msid_ = true;
1104 }
deadbeefab9b2d12015-10-14 11:33:11 -07001105
1106 // We wait to signal new streams until we finish processing the description,
1107 // since only at that point will new streams have all their tracks.
1108 rtc::scoped_refptr<StreamCollection> new_streams(StreamCollection::Create());
1109
1110 // Find all audio rtp streams and create corresponding remote AudioTracks
1111 // and MediaStreams.
deadbeefab9b2d12015-10-14 11:33:11 -07001112 if (audio_content) {
deadbeeffaac4972015-11-12 15:33:07 -08001113 if (audio_content->rejected) {
1114 RemoveTracks(cricket::MEDIA_TYPE_AUDIO);
1115 } else {
deadbeefbda7e0b2015-12-08 17:13:40 -08001116 bool default_audio_track_needed =
1117 !remote_peer_supports_msid_ &&
1118 MediaContentDirectionHasSend(audio_desc->direction());
1119 UpdateRemoteStreamsList(GetActiveStreams(audio_desc),
1120 default_audio_track_needed, audio_desc->type(),
deadbeeffaac4972015-11-12 15:33:07 -08001121 new_streams);
deadbeeffaac4972015-11-12 15:33:07 -08001122 }
deadbeefab9b2d12015-10-14 11:33:11 -07001123 }
1124
1125 // Find all video rtp streams and create corresponding remote VideoTracks
1126 // and MediaStreams.
deadbeefab9b2d12015-10-14 11:33:11 -07001127 if (video_content) {
deadbeeffaac4972015-11-12 15:33:07 -08001128 if (video_content->rejected) {
1129 RemoveTracks(cricket::MEDIA_TYPE_VIDEO);
1130 } else {
deadbeefbda7e0b2015-12-08 17:13:40 -08001131 bool default_video_track_needed =
1132 !remote_peer_supports_msid_ &&
1133 MediaContentDirectionHasSend(video_desc->direction());
1134 UpdateRemoteStreamsList(GetActiveStreams(video_desc),
1135 default_video_track_needed, video_desc->type(),
deadbeeffaac4972015-11-12 15:33:07 -08001136 new_streams);
deadbeeffaac4972015-11-12 15:33:07 -08001137 }
deadbeefab9b2d12015-10-14 11:33:11 -07001138 }
1139
1140 // Update the DataChannels with the information from the remote peer.
deadbeefbda7e0b2015-12-08 17:13:40 -08001141 if (data_desc) {
1142 if (rtc::starts_with(data_desc->protocol().data(),
deadbeefab9b2d12015-10-14 11:33:11 -07001143 cricket::kMediaProtocolRtpPrefix)) {
deadbeefbda7e0b2015-12-08 17:13:40 -08001144 UpdateRemoteRtpDataChannels(GetActiveStreams(data_desc));
deadbeefab9b2d12015-10-14 11:33:11 -07001145 }
1146 }
1147
1148 // Iterate new_streams and notify the observer about new MediaStreams.
1149 for (size_t i = 0; i < new_streams->count(); ++i) {
1150 MediaStreamInterface* new_stream = new_streams->at(i);
1151 stats_->AddStream(new_stream);
1152 observer_->OnAddStream(new_stream);
1153 }
1154
deadbeefbda7e0b2015-12-08 17:13:40 -08001155 UpdateEndedRemoteMediaStreams();
deadbeefab9b2d12015-10-14 11:33:11 -07001156
1157 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
1158 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
deadbeeffc648b62015-10-13 16:42:33 -07001159}
1160
deadbeefa67696b2015-09-29 11:56:26 -07001161bool PeerConnection::SetConfiguration(const RTCConfiguration& config) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001162 TRACE_EVENT0("webrtc", "PeerConnection::SetConfiguration");
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001163 if (port_allocator_) {
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -08001164 cricket::ServerAddresses stun_servers;
1165 std::vector<cricket::RelayServerConfig> turn_servers;
1166 if (!ParseIceServers(config.servers, &stun_servers, &turn_servers)) {
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001167 return false;
1168 }
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -08001169 port_allocator_->SetIceServers(stun_servers, turn_servers);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001170 }
honghaiz1f429e32015-09-28 07:57:34 -07001171 session_->SetIceConfig(session_->ParseIceConfig(config));
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001172 return session_->SetIceTransports(config.type);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001173}
1174
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001175bool PeerConnection::AddIceCandidate(
1176 const IceCandidateInterface* ice_candidate) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001177 TRACE_EVENT0("webrtc", "PeerConnection::AddIceCandidate");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001178 return session_->ProcessIceMessage(ice_candidate);
1179}
1180
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001181bool PeerConnection::RemoveIceCandidates(
1182 const std::vector<cricket::Candidate>& candidates) {
1183 TRACE_EVENT0("webrtc", "PeerConnection::RemoveIceCandidates");
1184 return session_->RemoveRemoteIceCandidates(candidates);
1185}
1186
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +00001187void PeerConnection::RegisterUMAObserver(UMAObserver* observer) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001188 TRACE_EVENT0("webrtc", "PeerConnection::RegisterUmaObserver");
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +00001189 uma_observer_ = observer;
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001190
1191 if (session_) {
1192 session_->set_metrics_observer(uma_observer_);
1193 }
1194
mallinath@webrtc.orgd37bcfa2014-05-12 23:10:18 +00001195 // Send information about IPv4/IPv6 status.
1196 if (uma_observer_ && port_allocator_) {
1197 if (port_allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_IPV6) {
Guo-wei Shiehdfbe6792015-09-03 17:12:07 -07001198 uma_observer_->IncrementEnumCounter(
1199 kEnumCounterAddressFamily, kPeerConnection_IPv6,
1200 kPeerConnectionAddressFamilyCounter_Max);
mallinath@webrtc.orgb445f262014-05-23 22:19:37 +00001201 } else {
Guo-wei Shiehdfbe6792015-09-03 17:12:07 -07001202 uma_observer_->IncrementEnumCounter(
1203 kEnumCounterAddressFamily, kPeerConnection_IPv4,
1204 kPeerConnectionAddressFamilyCounter_Max);
mallinath@webrtc.orgd37bcfa2014-05-12 23:10:18 +00001205 }
1206 }
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +00001207}
1208
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001209const SessionDescriptionInterface* PeerConnection::local_description() const {
1210 return session_->local_description();
1211}
1212
1213const SessionDescriptionInterface* PeerConnection::remote_description() const {
1214 return session_->remote_description();
1215}
1216
1217void PeerConnection::Close() {
Peter Boström1a9d6152015-12-08 22:15:17 +01001218 TRACE_EVENT0("webrtc", "PeerConnection::Close");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001219 // Update stats here so that we have the most recent stats for tracks and
1220 // streams before the channels are closed.
tommi@webrtc.org03505bc2014-07-14 20:15:26 +00001221 stats_->UpdateStats(kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001222
deadbeefd59daf82015-10-14 15:02:44 -07001223 session_->Close();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001224}
1225
deadbeefd59daf82015-10-14 15:02:44 -07001226void PeerConnection::OnSessionStateChange(WebRtcSession* /*session*/,
1227 WebRtcSession::State state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001228 switch (state) {
deadbeefd59daf82015-10-14 15:02:44 -07001229 case WebRtcSession::STATE_INIT:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001230 ChangeSignalingState(PeerConnectionInterface::kStable);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001231 break;
deadbeefd59daf82015-10-14 15:02:44 -07001232 case WebRtcSession::STATE_SENTOFFER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001233 ChangeSignalingState(PeerConnectionInterface::kHaveLocalOffer);
1234 break;
deadbeefd59daf82015-10-14 15:02:44 -07001235 case WebRtcSession::STATE_SENTPRANSWER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001236 ChangeSignalingState(PeerConnectionInterface::kHaveLocalPrAnswer);
1237 break;
deadbeefd59daf82015-10-14 15:02:44 -07001238 case WebRtcSession::STATE_RECEIVEDOFFER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001239 ChangeSignalingState(PeerConnectionInterface::kHaveRemoteOffer);
1240 break;
deadbeefd59daf82015-10-14 15:02:44 -07001241 case WebRtcSession::STATE_RECEIVEDPRANSWER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001242 ChangeSignalingState(PeerConnectionInterface::kHaveRemotePrAnswer);
1243 break;
deadbeefd59daf82015-10-14 15:02:44 -07001244 case WebRtcSession::STATE_INPROGRESS:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001245 ChangeSignalingState(PeerConnectionInterface::kStable);
1246 break;
deadbeefd59daf82015-10-14 15:02:44 -07001247 case WebRtcSession::STATE_CLOSED:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001248 ChangeSignalingState(PeerConnectionInterface::kClosed);
1249 break;
1250 default:
1251 break;
1252 }
1253}
1254
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001255void PeerConnection::OnMessage(rtc::Message* msg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001256 switch (msg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001257 case MSG_SET_SESSIONDESCRIPTION_SUCCESS: {
1258 SetSessionDescriptionMsg* param =
1259 static_cast<SetSessionDescriptionMsg*>(msg->pdata);
1260 param->observer->OnSuccess();
1261 delete param;
1262 break;
1263 }
1264 case MSG_SET_SESSIONDESCRIPTION_FAILED: {
1265 SetSessionDescriptionMsg* param =
1266 static_cast<SetSessionDescriptionMsg*>(msg->pdata);
1267 param->observer->OnFailure(param->error);
1268 delete param;
1269 break;
1270 }
deadbeefab9b2d12015-10-14 11:33:11 -07001271 case MSG_CREATE_SESSIONDESCRIPTION_FAILED: {
1272 CreateSessionDescriptionMsg* param =
1273 static_cast<CreateSessionDescriptionMsg*>(msg->pdata);
1274 param->observer->OnFailure(param->error);
1275 delete param;
1276 break;
1277 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001278 case MSG_GETSTATS: {
1279 GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata);
tommi@webrtc.org5b06b062014-08-15 08:38:30 +00001280 StatsReports reports;
1281 stats_->GetStats(param->track, &reports);
1282 param->observer->OnComplete(reports);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001283 delete param;
1284 break;
1285 }
deadbeefbd292462015-12-14 18:15:29 -08001286 case MSG_FREE_DATACHANNELS: {
1287 sctp_data_channels_to_free_.clear();
1288 break;
1289 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001290 default:
deadbeef0a6c4ca2015-10-06 11:38:28 -07001291 RTC_DCHECK(false && "Not implemented");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001292 break;
1293 }
1294}
1295
deadbeefab9b2d12015-10-14 11:33:11 -07001296void PeerConnection::CreateAudioReceiver(MediaStreamInterface* stream,
perkjd61bf802016-03-24 03:16:19 -07001297 const std::string& track_id,
deadbeefab9b2d12015-10-14 11:33:11 -07001298 uint32_t ssrc) {
deadbeefe1f9d832016-01-14 15:35:42 -08001299 receivers_.push_back(RtpReceiverProxy::Create(
1300 signaling_thread(),
perkjd61bf802016-03-24 03:16:19 -07001301 new AudioRtpReceiver(stream, track_id, ssrc, session_.get())));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001302}
1303
deadbeefab9b2d12015-10-14 11:33:11 -07001304void PeerConnection::CreateVideoReceiver(MediaStreamInterface* stream,
perkjf0dcfe22016-03-10 18:32:00 +01001305 const std::string& track_id,
deadbeefab9b2d12015-10-14 11:33:11 -07001306 uint32_t ssrc) {
perkjd61bf802016-03-24 03:16:19 -07001307 receivers_.push_back(RtpReceiverProxy::Create(
1308 signaling_thread(),
1309 new VideoRtpReceiver(stream, track_id, factory_->worker_thread(), ssrc,
1310 session_.get())));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001311}
1312
deadbeef70ab1a12015-09-28 16:53:55 -07001313// TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote
1314// description.
perkjd61bf802016-03-24 03:16:19 -07001315void PeerConnection::DestroyReceiver(const std::string& track_id) {
1316 auto it = FindReceiverForTrack(track_id);
deadbeef70ab1a12015-09-28 16:53:55 -07001317 if (it == receivers_.end()) {
perkjd61bf802016-03-24 03:16:19 -07001318 LOG(LS_WARNING) << "RtpReceiver for track with id " << track_id
deadbeef70ab1a12015-09-28 16:53:55 -07001319 << " doesn't exist.";
1320 } else {
1321 (*it)->Stop();
1322 receivers_.erase(it);
1323 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001324}
1325
perkjd61bf802016-03-24 03:16:19 -07001326void PeerConnection::StopReceivers(cricket::MediaType media_type) {
1327 TrackInfos* current_tracks = GetRemoteTracks(media_type);
1328 for (const auto& track_info : *current_tracks) {
1329 auto it = FindReceiverForTrack(track_info.track_id);
1330 if (it == receivers_.end()) {
1331 LOG(LS_WARNING) << "RtpReceiver for track with id " << track_info.track_id
1332 << " doesn't exist.";
1333 } else {
1334 (*it)->Stop();
1335 }
deadbeef70ab1a12015-09-28 16:53:55 -07001336 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001337}
deadbeef70ab1a12015-09-28 16:53:55 -07001338
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001339void PeerConnection::OnIceConnectionChange(
1340 PeerConnectionInterface::IceConnectionState new_state) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001341 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -07001342 // After transitioning to "closed", ignore any additional states from
1343 // WebRtcSession (such as "disconnected").
deadbeefab9b2d12015-10-14 11:33:11 -07001344 if (IsClosed()) {
deadbeefcbecd352015-09-23 11:50:27 -07001345 return;
1346 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001347 ice_connection_state_ = new_state;
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001348 observer_->OnIceConnectionChange(ice_connection_state_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001349}
1350
1351void PeerConnection::OnIceGatheringChange(
1352 PeerConnectionInterface::IceGatheringState new_state) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001353 RTC_DCHECK(signaling_thread()->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001354 if (IsClosed()) {
1355 return;
1356 }
1357 ice_gathering_state_ = new_state;
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001358 observer_->OnIceGatheringChange(ice_gathering_state_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001359}
1360
1361void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001362 RTC_DCHECK(signaling_thread()->IsCurrent());
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001363 observer_->OnIceCandidate(candidate);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001364}
1365
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001366void PeerConnection::OnIceCandidatesRemoved(
1367 const std::vector<cricket::Candidate>& candidates) {
1368 RTC_DCHECK(signaling_thread()->IsCurrent());
1369 observer_->OnIceCandidatesRemoved(candidates);
1370}
1371
Peter Thatcher54360512015-07-08 11:08:35 -07001372void PeerConnection::OnIceConnectionReceivingChange(bool receiving) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001373 RTC_DCHECK(signaling_thread()->IsCurrent());
Peter Thatcher54360512015-07-08 11:08:35 -07001374 observer_->OnIceConnectionReceivingChange(receiving);
1375}
1376
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001377void PeerConnection::ChangeSignalingState(
1378 PeerConnectionInterface::SignalingState signaling_state) {
1379 signaling_state_ = signaling_state;
1380 if (signaling_state == kClosed) {
1381 ice_connection_state_ = kIceConnectionClosed;
1382 observer_->OnIceConnectionChange(ice_connection_state_);
1383 if (ice_gathering_state_ != kIceGatheringComplete) {
1384 ice_gathering_state_ = kIceGatheringComplete;
1385 observer_->OnIceGatheringChange(ice_gathering_state_);
1386 }
1387 }
1388 observer_->OnSignalingChange(signaling_state_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001389}
1390
deadbeefeb459812015-12-15 19:24:43 -08001391void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track,
1392 MediaStreamInterface* stream) {
1393 auto sender = FindSenderForTrack(track);
1394 if (sender != senders_.end()) {
1395 // We already have a sender for this track, so just change the stream_id
1396 // so that it's correct in the next call to CreateOffer.
1397 (*sender)->set_stream_id(stream->label());
1398 return;
1399 }
1400
1401 // Normal case; we've never seen this track before.
deadbeefe1f9d832016-01-14 15:35:42 -08001402 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create(
1403 signaling_thread(),
1404 new AudioRtpSender(track, stream->label(), session_.get(), stats_.get()));
deadbeefeb459812015-12-15 19:24:43 -08001405 senders_.push_back(new_sender);
1406 // If the sender has already been configured in SDP, we call SetSsrc,
1407 // which will connect the sender to the underlying transport. This can
1408 // occur if a local session description that contains the ID of the sender
1409 // is set before AddStream is called. It can also occur if the local
1410 // session description is not changed and RemoveStream is called, and
1411 // later AddStream is called again with the same stream.
1412 const TrackInfo* track_info =
1413 FindTrackInfo(local_audio_tracks_, stream->label(), track->id());
1414 if (track_info) {
1415 new_sender->SetSsrc(track_info->ssrc);
1416 }
1417}
1418
1419// TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around
1420// indefinitely, when we have unified plan SDP.
1421void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track,
1422 MediaStreamInterface* stream) {
1423 auto sender = FindSenderForTrack(track);
1424 if (sender == senders_.end()) {
1425 LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
1426 << " doesn't exist.";
1427 return;
1428 }
1429 (*sender)->Stop();
1430 senders_.erase(sender);
1431}
1432
1433void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track,
1434 MediaStreamInterface* stream) {
1435 auto sender = FindSenderForTrack(track);
1436 if (sender != senders_.end()) {
1437 // We already have a sender for this track, so just change the stream_id
1438 // so that it's correct in the next call to CreateOffer.
1439 (*sender)->set_stream_id(stream->label());
1440 return;
1441 }
1442
1443 // Normal case; we've never seen this track before.
deadbeefe1f9d832016-01-14 15:35:42 -08001444 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create(
1445 signaling_thread(),
1446 new VideoRtpSender(track, stream->label(), session_.get()));
deadbeefeb459812015-12-15 19:24:43 -08001447 senders_.push_back(new_sender);
1448 const TrackInfo* track_info =
1449 FindTrackInfo(local_video_tracks_, stream->label(), track->id());
1450 if (track_info) {
1451 new_sender->SetSsrc(track_info->ssrc);
1452 }
1453}
1454
1455void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track,
1456 MediaStreamInterface* stream) {
1457 auto sender = FindSenderForTrack(track);
1458 if (sender == senders_.end()) {
1459 LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
1460 << " doesn't exist.";
1461 return;
1462 }
1463 (*sender)->Stop();
1464 senders_.erase(sender);
1465}
1466
deadbeefab9b2d12015-10-14 11:33:11 -07001467void PeerConnection::PostSetSessionDescriptionFailure(
1468 SetSessionDescriptionObserver* observer,
1469 const std::string& error) {
1470 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
1471 msg->error = error;
1472 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_FAILED, msg);
1473}
1474
1475void PeerConnection::PostCreateSessionDescriptionFailure(
1476 CreateSessionDescriptionObserver* observer,
1477 const std::string& error) {
1478 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
1479 msg->error = error;
1480 signaling_thread()->Post(this, MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
1481}
1482
1483bool PeerConnection::GetOptionsForOffer(
1484 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
1485 cricket::MediaSessionOptions* session_options) {
deadbeef0ed85b22016-02-23 17:24:52 -08001486 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of
1487 // ContentInfos.
1488 if (session_->local_description()) {
1489 for (const cricket::ContentInfo& content :
1490 session_->local_description()->description()->contents()) {
1491 session_options->transport_options[content.name] =
1492 cricket::TransportOptions();
1493 }
1494 }
htaaac2dea2016-03-10 13:35:55 -08001495 if (!ExtractMediaSessionOptions(rtc_options, true, session_options)) {
deadbeefab9b2d12015-10-14 11:33:11 -07001496 return false;
1497 }
1498
deadbeeffac06552015-11-25 11:26:01 -08001499 AddSendStreams(session_options, senders_, rtp_data_channels_);
deadbeefc80741f2015-10-22 13:14:45 -07001500 // Offer to receive audio/video if the constraint is not set and there are
1501 // send streams, or we're currently receiving.
1502 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) {
1503 session_options->recv_audio =
1504 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) ||
1505 !remote_audio_tracks_.empty();
1506 }
1507 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) {
1508 session_options->recv_video =
1509 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) ||
1510 !remote_video_tracks_.empty();
1511 }
1512 session_options->bundle_enabled =
1513 session_options->bundle_enabled &&
1514 (session_options->has_audio() || session_options->has_video() ||
1515 session_options->has_data());
1516
deadbeefab9b2d12015-10-14 11:33:11 -07001517 if (session_->data_channel_type() == cricket::DCT_SCTP && HasDataChannels()) {
1518 session_options->data_channel_type = cricket::DCT_SCTP;
1519 }
zhihuang8f65cdf2016-05-06 18:40:30 -07001520
1521 session_options->rtcp_cname = rtcp_cname_;
deadbeefab9b2d12015-10-14 11:33:11 -07001522 return true;
1523}
1524
htaa2a49d92016-03-04 02:51:39 -08001525void PeerConnection::FinishOptionsForAnswer(
deadbeefab9b2d12015-10-14 11:33:11 -07001526 cricket::MediaSessionOptions* session_options) {
deadbeef0ed85b22016-02-23 17:24:52 -08001527 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of
1528 // ContentInfos.
1529 if (session_->remote_description()) {
1530 // Initialize the transport_options map.
1531 for (const cricket::ContentInfo& content :
1532 session_->remote_description()->description()->contents()) {
1533 session_options->transport_options[content.name] =
1534 cricket::TransportOptions();
1535 }
1536 }
deadbeeffac06552015-11-25 11:26:01 -08001537 AddSendStreams(session_options, senders_, rtp_data_channels_);
deadbeefc80741f2015-10-22 13:14:45 -07001538 session_options->bundle_enabled =
1539 session_options->bundle_enabled &&
1540 (session_options->has_audio() || session_options->has_video() ||
1541 session_options->has_data());
1542
deadbeefab9b2d12015-10-14 11:33:11 -07001543 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams
1544 // are not signaled in the SDP so does not go through that path and must be
1545 // handled here.
1546 if (session_->data_channel_type() == cricket::DCT_SCTP) {
1547 session_options->data_channel_type = cricket::DCT_SCTP;
1548 }
htaa2a49d92016-03-04 02:51:39 -08001549}
1550
1551bool PeerConnection::GetOptionsForAnswer(
1552 const MediaConstraintsInterface* constraints,
1553 cricket::MediaSessionOptions* session_options) {
1554 session_options->recv_audio = false;
1555 session_options->recv_video = false;
1556 if (!ParseConstraintsForAnswer(constraints, session_options)) {
1557 return false;
1558 }
zhihuang8f65cdf2016-05-06 18:40:30 -07001559 session_options->rtcp_cname = rtcp_cname_;
1560
htaa2a49d92016-03-04 02:51:39 -08001561 FinishOptionsForAnswer(session_options);
1562 return true;
1563}
1564
1565bool PeerConnection::GetOptionsForAnswer(
1566 const RTCOfferAnswerOptions& options,
1567 cricket::MediaSessionOptions* session_options) {
1568 session_options->recv_audio = false;
1569 session_options->recv_video = false;
htaaac2dea2016-03-10 13:35:55 -08001570 if (!ExtractMediaSessionOptions(options, false, session_options)) {
htaa2a49d92016-03-04 02:51:39 -08001571 return false;
1572 }
zhihuang8f65cdf2016-05-06 18:40:30 -07001573 session_options->rtcp_cname = rtcp_cname_;
1574
htaa2a49d92016-03-04 02:51:39 -08001575 FinishOptionsForAnswer(session_options);
deadbeefab9b2d12015-10-14 11:33:11 -07001576 return true;
1577}
1578
deadbeeffaac4972015-11-12 15:33:07 -08001579void PeerConnection::RemoveTracks(cricket::MediaType media_type) {
1580 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type);
deadbeefbda7e0b2015-12-08 17:13:40 -08001581 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false,
1582 media_type, nullptr);
deadbeeffaac4972015-11-12 15:33:07 -08001583}
1584
deadbeefab9b2d12015-10-14 11:33:11 -07001585void PeerConnection::UpdateRemoteStreamsList(
1586 const cricket::StreamParamsVec& streams,
deadbeefbda7e0b2015-12-08 17:13:40 -08001587 bool default_track_needed,
deadbeefab9b2d12015-10-14 11:33:11 -07001588 cricket::MediaType media_type,
1589 StreamCollection* new_streams) {
1590 TrackInfos* current_tracks = GetRemoteTracks(media_type);
1591
1592 // Find removed tracks. I.e., tracks where the track id or ssrc don't match
deadbeeffac06552015-11-25 11:26:01 -08001593 // the new StreamParam.
deadbeefab9b2d12015-10-14 11:33:11 -07001594 auto track_it = current_tracks->begin();
1595 while (track_it != current_tracks->end()) {
1596 const TrackInfo& info = *track_it;
1597 const cricket::StreamParams* params =
1598 cricket::GetStreamBySsrc(streams, info.ssrc);
deadbeefbda7e0b2015-12-08 17:13:40 -08001599 bool track_exists = params && params->id == info.track_id;
1600 // If this is a default track, and we still need it, don't remove it.
1601 if ((info.stream_label == kDefaultStreamLabel && default_track_needed) ||
1602 track_exists) {
1603 ++track_it;
1604 } else {
deadbeefab9b2d12015-10-14 11:33:11 -07001605 OnRemoteTrackRemoved(info.stream_label, info.track_id, media_type);
1606 track_it = current_tracks->erase(track_it);
deadbeefab9b2d12015-10-14 11:33:11 -07001607 }
1608 }
1609
1610 // Find new and active tracks.
1611 for (const cricket::StreamParams& params : streams) {
1612 // The sync_label is the MediaStream label and the |stream.id| is the
1613 // track id.
1614 const std::string& stream_label = params.sync_label;
1615 const std::string& track_id = params.id;
1616 uint32_t ssrc = params.first_ssrc();
1617
1618 rtc::scoped_refptr<MediaStreamInterface> stream =
1619 remote_streams_->find(stream_label);
1620 if (!stream) {
1621 // This is a new MediaStream. Create a new remote MediaStream.
perkjd61bf802016-03-24 03:16:19 -07001622 stream = MediaStreamProxy::Create(rtc::Thread::Current(),
1623 MediaStream::Create(stream_label));
deadbeefab9b2d12015-10-14 11:33:11 -07001624 remote_streams_->AddStream(stream);
1625 new_streams->AddStream(stream);
1626 }
1627
1628 const TrackInfo* track_info =
1629 FindTrackInfo(*current_tracks, stream_label, track_id);
1630 if (!track_info) {
1631 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc));
1632 OnRemoteTrackSeen(stream_label, track_id, ssrc, media_type);
1633 }
1634 }
deadbeefbda7e0b2015-12-08 17:13:40 -08001635
1636 // Add default track if necessary.
1637 if (default_track_needed) {
1638 rtc::scoped_refptr<MediaStreamInterface> default_stream =
1639 remote_streams_->find(kDefaultStreamLabel);
1640 if (!default_stream) {
1641 // Create the new default MediaStream.
perkjd61bf802016-03-24 03:16:19 -07001642 default_stream = MediaStreamProxy::Create(
1643 rtc::Thread::Current(), MediaStream::Create(kDefaultStreamLabel));
deadbeefbda7e0b2015-12-08 17:13:40 -08001644 remote_streams_->AddStream(default_stream);
1645 new_streams->AddStream(default_stream);
1646 }
1647 std::string default_track_id = (media_type == cricket::MEDIA_TYPE_AUDIO)
1648 ? kDefaultAudioTrackLabel
1649 : kDefaultVideoTrackLabel;
1650 const TrackInfo* default_track_info =
1651 FindTrackInfo(*current_tracks, kDefaultStreamLabel, default_track_id);
1652 if (!default_track_info) {
1653 current_tracks->push_back(
1654 TrackInfo(kDefaultStreamLabel, default_track_id, 0));
1655 OnRemoteTrackSeen(kDefaultStreamLabel, default_track_id, 0, media_type);
1656 }
1657 }
deadbeefab9b2d12015-10-14 11:33:11 -07001658}
1659
1660void PeerConnection::OnRemoteTrackSeen(const std::string& stream_label,
1661 const std::string& track_id,
1662 uint32_t ssrc,
1663 cricket::MediaType media_type) {
1664 MediaStreamInterface* stream = remote_streams_->find(stream_label);
1665
1666 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
perkjd61bf802016-03-24 03:16:19 -07001667 CreateAudioReceiver(stream, track_id, ssrc);
deadbeefab9b2d12015-10-14 11:33:11 -07001668 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
perkjf0dcfe22016-03-10 18:32:00 +01001669 CreateVideoReceiver(stream, track_id, ssrc);
deadbeefab9b2d12015-10-14 11:33:11 -07001670 } else {
1671 RTC_DCHECK(false && "Invalid media type");
1672 }
1673}
1674
1675void PeerConnection::OnRemoteTrackRemoved(const std::string& stream_label,
1676 const std::string& track_id,
1677 cricket::MediaType media_type) {
1678 MediaStreamInterface* stream = remote_streams_->find(stream_label);
1679
1680 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
perkjd61bf802016-03-24 03:16:19 -07001681 // When the MediaEngine audio channel is destroyed, the RemoteAudioSource
1682 // will be notified which will end the AudioRtpReceiver::track().
1683 DestroyReceiver(track_id);
deadbeefab9b2d12015-10-14 11:33:11 -07001684 rtc::scoped_refptr<AudioTrackInterface> audio_track =
1685 stream->FindAudioTrack(track_id);
1686 if (audio_track) {
deadbeefab9b2d12015-10-14 11:33:11 -07001687 stream->RemoveTrack(audio_track);
deadbeefab9b2d12015-10-14 11:33:11 -07001688 }
1689 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
perkjd61bf802016-03-24 03:16:19 -07001690 // Stopping or destroying a VideoRtpReceiver will end the
1691 // VideoRtpReceiver::track().
1692 DestroyReceiver(track_id);
deadbeefab9b2d12015-10-14 11:33:11 -07001693 rtc::scoped_refptr<VideoTrackInterface> video_track =
1694 stream->FindVideoTrack(track_id);
1695 if (video_track) {
perkjd61bf802016-03-24 03:16:19 -07001696 // There's no guarantee the track is still available, e.g. the track may
1697 // have been removed from the stream by an application.
deadbeefab9b2d12015-10-14 11:33:11 -07001698 stream->RemoveTrack(video_track);
deadbeefab9b2d12015-10-14 11:33:11 -07001699 }
1700 } else {
1701 ASSERT(false && "Invalid media type");
1702 }
1703}
1704
1705void PeerConnection::UpdateEndedRemoteMediaStreams() {
1706 std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_to_remove;
1707 for (size_t i = 0; i < remote_streams_->count(); ++i) {
1708 MediaStreamInterface* stream = remote_streams_->at(i);
1709 if (stream->GetAudioTracks().empty() && stream->GetVideoTracks().empty()) {
1710 streams_to_remove.push_back(stream);
1711 }
1712 }
1713
1714 for (const auto& stream : streams_to_remove) {
1715 remote_streams_->RemoveStream(stream);
1716 observer_->OnRemoveStream(stream);
1717 }
1718}
1719
deadbeefab9b2d12015-10-14 11:33:11 -07001720void PeerConnection::UpdateLocalTracks(
1721 const std::vector<cricket::StreamParams>& streams,
1722 cricket::MediaType media_type) {
1723 TrackInfos* current_tracks = GetLocalTracks(media_type);
1724
1725 // Find removed tracks. I.e., tracks where the track id, stream label or ssrc
1726 // don't match the new StreamParam.
1727 TrackInfos::iterator track_it = current_tracks->begin();
1728 while (track_it != current_tracks->end()) {
1729 const TrackInfo& info = *track_it;
1730 const cricket::StreamParams* params =
1731 cricket::GetStreamBySsrc(streams, info.ssrc);
1732 if (!params || params->id != info.track_id ||
1733 params->sync_label != info.stream_label) {
1734 OnLocalTrackRemoved(info.stream_label, info.track_id, info.ssrc,
1735 media_type);
1736 track_it = current_tracks->erase(track_it);
1737 } else {
1738 ++track_it;
1739 }
1740 }
1741
1742 // Find new and active tracks.
1743 for (const cricket::StreamParams& params : streams) {
1744 // The sync_label is the MediaStream label and the |stream.id| is the
1745 // track id.
1746 const std::string& stream_label = params.sync_label;
1747 const std::string& track_id = params.id;
1748 uint32_t ssrc = params.first_ssrc();
1749 const TrackInfo* track_info =
1750 FindTrackInfo(*current_tracks, stream_label, track_id);
1751 if (!track_info) {
1752 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc));
1753 OnLocalTrackSeen(stream_label, track_id, params.first_ssrc(), media_type);
1754 }
1755 }
1756}
1757
1758void PeerConnection::OnLocalTrackSeen(const std::string& stream_label,
1759 const std::string& track_id,
1760 uint32_t ssrc,
1761 cricket::MediaType media_type) {
deadbeeffac06552015-11-25 11:26:01 -08001762 RtpSenderInterface* sender = FindSenderById(track_id);
1763 if (!sender) {
1764 LOG(LS_WARNING) << "An unknown RtpSender with id " << track_id
1765 << " has been configured in the local description.";
deadbeefab9b2d12015-10-14 11:33:11 -07001766 return;
1767 }
1768
deadbeeffac06552015-11-25 11:26:01 -08001769 if (sender->media_type() != media_type) {
1770 LOG(LS_WARNING) << "An RtpSender has been configured in the local"
1771 << " description with an unexpected media type.";
1772 return;
deadbeefab9b2d12015-10-14 11:33:11 -07001773 }
deadbeeffac06552015-11-25 11:26:01 -08001774
1775 sender->set_stream_id(stream_label);
1776 sender->SetSsrc(ssrc);
deadbeefab9b2d12015-10-14 11:33:11 -07001777}
1778
1779void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label,
1780 const std::string& track_id,
1781 uint32_t ssrc,
1782 cricket::MediaType media_type) {
deadbeeffac06552015-11-25 11:26:01 -08001783 RtpSenderInterface* sender = FindSenderById(track_id);
1784 if (!sender) {
1785 // This is the normal case. I.e., RemoveStream has been called and the
deadbeefab9b2d12015-10-14 11:33:11 -07001786 // SessionDescriptions has been renegotiated.
1787 return;
1788 }
deadbeeffac06552015-11-25 11:26:01 -08001789
1790 // A sender has been removed from the SessionDescription but it's still
1791 // associated with the PeerConnection. This only occurs if the SDP doesn't
1792 // match with the calls to CreateSender, AddStream and RemoveStream.
1793 if (sender->media_type() != media_type) {
1794 LOG(LS_WARNING) << "An RtpSender has been configured in the local"
1795 << " description with an unexpected media type.";
1796 return;
deadbeefab9b2d12015-10-14 11:33:11 -07001797 }
deadbeeffac06552015-11-25 11:26:01 -08001798
1799 sender->SetSsrc(0);
deadbeefab9b2d12015-10-14 11:33:11 -07001800}
1801
1802void PeerConnection::UpdateLocalRtpDataChannels(
1803 const cricket::StreamParamsVec& streams) {
1804 std::vector<std::string> existing_channels;
1805
1806 // Find new and active data channels.
1807 for (const cricket::StreamParams& params : streams) {
1808 // |it->sync_label| is actually the data channel label. The reason is that
1809 // we use the same naming of data channels as we do for
1810 // MediaStreams and Tracks.
1811 // For MediaStreams, the sync_label is the MediaStream label and the
1812 // track label is the same as |streamid|.
1813 const std::string& channel_label = params.sync_label;
1814 auto data_channel_it = rtp_data_channels_.find(channel_label);
1815 if (!VERIFY(data_channel_it != rtp_data_channels_.end())) {
1816 continue;
1817 }
1818 // Set the SSRC the data channel should use for sending.
1819 data_channel_it->second->SetSendSsrc(params.first_ssrc());
1820 existing_channels.push_back(data_channel_it->first);
1821 }
1822
1823 UpdateClosingRtpDataChannels(existing_channels, true);
1824}
1825
1826void PeerConnection::UpdateRemoteRtpDataChannels(
1827 const cricket::StreamParamsVec& streams) {
1828 std::vector<std::string> existing_channels;
1829
1830 // Find new and active data channels.
1831 for (const cricket::StreamParams& params : streams) {
1832 // The data channel label is either the mslabel or the SSRC if the mslabel
1833 // does not exist. Ex a=ssrc:444330170 mslabel:test1.
1834 std::string label = params.sync_label.empty()
1835 ? rtc::ToString(params.first_ssrc())
1836 : params.sync_label;
1837 auto data_channel_it = rtp_data_channels_.find(label);
1838 if (data_channel_it == rtp_data_channels_.end()) {
1839 // This is a new data channel.
1840 CreateRemoteRtpDataChannel(label, params.first_ssrc());
1841 } else {
1842 data_channel_it->second->SetReceiveSsrc(params.first_ssrc());
1843 }
1844 existing_channels.push_back(label);
1845 }
1846
1847 UpdateClosingRtpDataChannels(existing_channels, false);
1848}
1849
1850void PeerConnection::UpdateClosingRtpDataChannels(
1851 const std::vector<std::string>& active_channels,
1852 bool is_local_update) {
1853 auto it = rtp_data_channels_.begin();
1854 while (it != rtp_data_channels_.end()) {
1855 DataChannel* data_channel = it->second;
1856 if (std::find(active_channels.begin(), active_channels.end(),
1857 data_channel->label()) != active_channels.end()) {
1858 ++it;
1859 continue;
1860 }
1861
1862 if (is_local_update) {
1863 data_channel->SetSendSsrc(0);
1864 } else {
1865 data_channel->RemotePeerRequestClose();
1866 }
1867
1868 if (data_channel->state() == DataChannel::kClosed) {
1869 rtp_data_channels_.erase(it);
1870 it = rtp_data_channels_.begin();
1871 } else {
1872 ++it;
1873 }
1874 }
1875}
1876
1877void PeerConnection::CreateRemoteRtpDataChannel(const std::string& label,
1878 uint32_t remote_ssrc) {
1879 rtc::scoped_refptr<DataChannel> channel(
1880 InternalCreateDataChannel(label, nullptr));
1881 if (!channel.get()) {
1882 LOG(LS_WARNING) << "Remote peer requested a DataChannel but"
1883 << "CreateDataChannel failed.";
1884 return;
1885 }
1886 channel->SetReceiveSsrc(remote_ssrc);
1887 observer_->OnDataChannel(
1888 DataChannelProxy::Create(signaling_thread(), channel));
1889}
1890
1891rtc::scoped_refptr<DataChannel> PeerConnection::InternalCreateDataChannel(
1892 const std::string& label,
1893 const InternalDataChannelInit* config) {
1894 if (IsClosed()) {
1895 return nullptr;
1896 }
1897 if (session_->data_channel_type() == cricket::DCT_NONE) {
1898 LOG(LS_ERROR)
1899 << "InternalCreateDataChannel: Data is not supported in this call.";
1900 return nullptr;
1901 }
1902 InternalDataChannelInit new_config =
1903 config ? (*config) : InternalDataChannelInit();
1904 if (session_->data_channel_type() == cricket::DCT_SCTP) {
1905 if (new_config.id < 0) {
1906 rtc::SSLRole role;
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001907 if ((session_->GetSslRole(session_->data_channel(), &role)) &&
deadbeefab9b2d12015-10-14 11:33:11 -07001908 !sid_allocator_.AllocateSid(role, &new_config.id)) {
1909 LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
1910 return nullptr;
1911 }
1912 } else if (!sid_allocator_.ReserveSid(new_config.id)) {
1913 LOG(LS_ERROR) << "Failed to create a SCTP data channel "
1914 << "because the id is already in use or out of range.";
1915 return nullptr;
1916 }
1917 }
1918
1919 rtc::scoped_refptr<DataChannel> channel(DataChannel::Create(
1920 session_.get(), session_->data_channel_type(), label, new_config));
1921 if (!channel) {
1922 sid_allocator_.ReleaseSid(new_config.id);
1923 return nullptr;
1924 }
1925
1926 if (channel->data_channel_type() == cricket::DCT_RTP) {
1927 if (rtp_data_channels_.find(channel->label()) != rtp_data_channels_.end()) {
1928 LOG(LS_ERROR) << "DataChannel with label " << channel->label()
1929 << " already exists.";
1930 return nullptr;
1931 }
1932 rtp_data_channels_[channel->label()] = channel;
1933 } else {
1934 RTC_DCHECK(channel->data_channel_type() == cricket::DCT_SCTP);
1935 sctp_data_channels_.push_back(channel);
1936 channel->SignalClosed.connect(this,
1937 &PeerConnection::OnSctpDataChannelClosed);
1938 }
1939
1940 return channel;
1941}
1942
1943bool PeerConnection::HasDataChannels() const {
1944 return !rtp_data_channels_.empty() || !sctp_data_channels_.empty();
1945}
1946
1947void PeerConnection::AllocateSctpSids(rtc::SSLRole role) {
1948 for (const auto& channel : sctp_data_channels_) {
1949 if (channel->id() < 0) {
1950 int sid;
1951 if (!sid_allocator_.AllocateSid(role, &sid)) {
1952 LOG(LS_ERROR) << "Failed to allocate SCTP sid.";
1953 continue;
1954 }
1955 channel->SetSctpSid(sid);
1956 }
1957 }
1958}
1959
1960void PeerConnection::OnSctpDataChannelClosed(DataChannel* channel) {
deadbeefbd292462015-12-14 18:15:29 -08001961 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeefab9b2d12015-10-14 11:33:11 -07001962 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end();
1963 ++it) {
1964 if (it->get() == channel) {
1965 if (channel->id() >= 0) {
1966 sid_allocator_.ReleaseSid(channel->id());
1967 }
deadbeefbd292462015-12-14 18:15:29 -08001968 // Since this method is triggered by a signal from the DataChannel,
1969 // we can't free it directly here; we need to free it asynchronously.
1970 sctp_data_channels_to_free_.push_back(*it);
deadbeefab9b2d12015-10-14 11:33:11 -07001971 sctp_data_channels_.erase(it);
deadbeefbd292462015-12-14 18:15:29 -08001972 signaling_thread()->Post(this, MSG_FREE_DATACHANNELS, nullptr);
deadbeefab9b2d12015-10-14 11:33:11 -07001973 return;
1974 }
1975 }
1976}
1977
1978void PeerConnection::OnVoiceChannelDestroyed() {
perkjd61bf802016-03-24 03:16:19 -07001979 StopReceivers(cricket::MEDIA_TYPE_AUDIO);
deadbeefab9b2d12015-10-14 11:33:11 -07001980}
1981
1982void PeerConnection::OnVideoChannelDestroyed() {
perkjd61bf802016-03-24 03:16:19 -07001983 StopReceivers(cricket::MEDIA_TYPE_VIDEO);
deadbeefab9b2d12015-10-14 11:33:11 -07001984}
1985
1986void PeerConnection::OnDataChannelCreated() {
1987 for (const auto& channel : sctp_data_channels_) {
1988 channel->OnTransportChannelCreated();
1989 }
1990}
1991
1992void PeerConnection::OnDataChannelDestroyed() {
1993 // Use a temporary copy of the RTP/SCTP DataChannel list because the
1994 // DataChannel may callback to us and try to modify the list.
1995 std::map<std::string, rtc::scoped_refptr<DataChannel>> temp_rtp_dcs;
1996 temp_rtp_dcs.swap(rtp_data_channels_);
1997 for (const auto& kv : temp_rtp_dcs) {
1998 kv.second->OnTransportChannelDestroyed();
1999 }
2000
2001 std::vector<rtc::scoped_refptr<DataChannel>> temp_sctp_dcs;
2002 temp_sctp_dcs.swap(sctp_data_channels_);
2003 for (const auto& channel : temp_sctp_dcs) {
2004 channel->OnTransportChannelDestroyed();
2005 }
2006}
2007
2008void PeerConnection::OnDataChannelOpenMessage(
2009 const std::string& label,
2010 const InternalDataChannelInit& config) {
2011 rtc::scoped_refptr<DataChannel> channel(
2012 InternalCreateDataChannel(label, &config));
2013 if (!channel.get()) {
2014 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
2015 return;
2016 }
2017
2018 observer_->OnDataChannel(
2019 DataChannelProxy::Create(signaling_thread(), channel));
2020}
2021
deadbeeffac06552015-11-25 11:26:01 -08002022RtpSenderInterface* PeerConnection::FindSenderById(const std::string& id) {
2023 auto it =
2024 std::find_if(senders_.begin(), senders_.end(),
2025 [id](const rtc::scoped_refptr<RtpSenderInterface>& sender) {
2026 return sender->id() == id;
2027 });
2028 return it != senders_.end() ? it->get() : nullptr;
2029}
2030
deadbeef70ab1a12015-09-28 16:53:55 -07002031std::vector<rtc::scoped_refptr<RtpSenderInterface>>::iterator
2032PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) {
2033 return std::find_if(
2034 senders_.begin(), senders_.end(),
2035 [track](const rtc::scoped_refptr<RtpSenderInterface>& sender) {
2036 return sender->track() == track;
2037 });
2038}
2039
2040std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator
perkjd61bf802016-03-24 03:16:19 -07002041PeerConnection::FindReceiverForTrack(const std::string& track_id) {
deadbeef70ab1a12015-09-28 16:53:55 -07002042 return std::find_if(
2043 receivers_.begin(), receivers_.end(),
perkjd61bf802016-03-24 03:16:19 -07002044 [track_id](const rtc::scoped_refptr<RtpReceiverInterface>& receiver) {
2045 return receiver->id() == track_id;
deadbeef70ab1a12015-09-28 16:53:55 -07002046 });
2047}
2048
deadbeefab9b2d12015-10-14 11:33:11 -07002049PeerConnection::TrackInfos* PeerConnection::GetRemoteTracks(
2050 cricket::MediaType media_type) {
2051 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
2052 media_type == cricket::MEDIA_TYPE_VIDEO);
2053 return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &remote_audio_tracks_
2054 : &remote_video_tracks_;
2055}
2056
2057PeerConnection::TrackInfos* PeerConnection::GetLocalTracks(
2058 cricket::MediaType media_type) {
2059 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
2060 media_type == cricket::MEDIA_TYPE_VIDEO);
2061 return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &local_audio_tracks_
2062 : &local_video_tracks_;
2063}
2064
2065const PeerConnection::TrackInfo* PeerConnection::FindTrackInfo(
2066 const PeerConnection::TrackInfos& infos,
2067 const std::string& stream_label,
2068 const std::string track_id) const {
2069 for (const TrackInfo& track_info : infos) {
2070 if (track_info.stream_label == stream_label &&
2071 track_info.track_id == track_id) {
2072 return &track_info;
2073 }
2074 }
2075 return nullptr;
2076}
2077
2078DataChannel* PeerConnection::FindDataChannelBySid(int sid) const {
2079 for (const auto& channel : sctp_data_channels_) {
2080 if (channel->id() == sid) {
2081 return channel;
2082 }
2083 }
2084 return nullptr;
2085}
2086
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002087} // namespace webrtc