blob: 5f8acca5669c0c1aabb8a568e9d8a4d46a5c22f9 [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"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010039#include "webrtc/pc/channelmanager.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010040#include "webrtc/system_wrappers/include/field_trial.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000041
42namespace {
43
deadbeefab9b2d12015-10-14 11:33:11 -070044using webrtc::DataChannel;
45using webrtc::MediaConstraintsInterface;
46using webrtc::MediaStreamInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000047using webrtc::PeerConnectionInterface;
deadbeeffac06552015-11-25 11:26:01 -080048using webrtc::RtpSenderInterface;
deadbeefab9b2d12015-10-14 11:33:11 -070049using webrtc::StreamCollection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000050
deadbeefab9b2d12015-10-14 11:33:11 -070051static const char kDefaultStreamLabel[] = "default";
52static const char kDefaultAudioTrackLabel[] = "defaulta0";
53static const char kDefaultVideoTrackLabel[] = "defaultv0";
54
henrike@webrtc.org28e20752013-07-10 00:45:36 +000055// The min number of tokens must present in Turn host uri.
56// e.g. user@turn.example.org
57static const size_t kTurnHostTokensNum = 2;
58// Number of tokens must be preset when TURN uri has transport param.
59static const size_t kTurnTransportTokensNum = 2;
60// The default stun port.
wu@webrtc.org91053e72013-08-10 07:18:04 +000061static const int kDefaultStunPort = 3478;
62static const int kDefaultStunTlsPort = 5349;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000063static const char kTransport[] = "transport";
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064
65// NOTE: Must be in the same order as the ServiceType enum.
deadbeef0a6c4ca2015-10-06 11:38:28 -070066static const char* kValidIceServiceTypes[] = {"stun", "stuns", "turn", "turns"};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067
zhihuang8f65cdf2016-05-06 18:40:30 -070068// The length of RTCP CNAMEs.
69static const int kRtcpCnameLength = 16;
70
deadbeef0a6c4ca2015-10-06 11:38:28 -070071// NOTE: A loop below assumes that the first value of this enum is 0 and all
72// other values are incremental.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000073enum ServiceType {
deadbeef0a6c4ca2015-10-06 11:38:28 -070074 STUN = 0, // Indicates a STUN server.
75 STUNS, // Indicates a STUN server used with a TLS session.
76 TURN, // Indicates a TURN server
77 TURNS, // Indicates a TURN server used with a TLS session.
78 INVALID, // Unknown.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079};
tfarina5237aaf2015-11-10 23:44:30 -080080static_assert(INVALID == arraysize(kValidIceServiceTypes),
deadbeef0a6c4ca2015-10-06 11:38:28 -070081 "kValidIceServiceTypes must have as many strings as ServiceType "
82 "has values.");
henrike@webrtc.org28e20752013-07-10 00:45:36 +000083
84enum {
wu@webrtc.org91053e72013-08-10 07:18:04 +000085 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086 MSG_SET_SESSIONDESCRIPTION_FAILED,
deadbeefab9b2d12015-10-14 11:33:11 -070087 MSG_CREATE_SESSIONDESCRIPTION_FAILED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000088 MSG_GETSTATS,
deadbeefbd292462015-12-14 18:15:29 -080089 MSG_FREE_DATACHANNELS,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000090};
91
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000092struct SetSessionDescriptionMsg : public rtc::MessageData {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000093 explicit SetSessionDescriptionMsg(
94 webrtc::SetSessionDescriptionObserver* observer)
95 : observer(observer) {
96 }
97
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000098 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserver> observer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099 std::string error;
100};
101
deadbeefab9b2d12015-10-14 11:33:11 -0700102struct CreateSessionDescriptionMsg : public rtc::MessageData {
103 explicit CreateSessionDescriptionMsg(
104 webrtc::CreateSessionDescriptionObserver* observer)
105 : observer(observer) {}
106
107 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer;
108 std::string error;
109};
110
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000111struct GetStatsMsg : public rtc::MessageData {
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000112 GetStatsMsg(webrtc::StatsObserver* observer,
113 webrtc::MediaStreamTrackInterface* track)
114 : observer(observer), track(track) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000116 rtc::scoped_refptr<webrtc::StatsObserver> observer;
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000117 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000118};
119
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000120// |in_str| should be of format
121// stunURI = scheme ":" stun-host [ ":" stun-port ]
122// scheme = "stun" / "stuns"
123// stun-host = IP-literal / IPv4address / reg-name
124// stun-port = *DIGIT
deadbeef0a6c4ca2015-10-06 11:38:28 -0700125//
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000126// draft-petithuguenin-behave-turn-uris-01
127// turnURI = scheme ":" turn-host [ ":" turn-port ]
128// turn-host = username@IP-literal / IPv4address / reg-name
129bool GetServiceTypeAndHostnameFromUri(const std::string& in_str,
130 ServiceType* service_type,
131 std::string* hostname) {
Tommi77d444a2015-04-24 15:38:38 +0200132 const std::string::size_type colonpos = in_str.find(':');
deadbeef0a6c4ca2015-10-06 11:38:28 -0700133 if (colonpos == std::string::npos) {
134 LOG(LS_WARNING) << "Missing ':' in ICE URI: " << in_str;
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000135 return false;
136 }
deadbeef0a6c4ca2015-10-06 11:38:28 -0700137 if ((colonpos + 1) == in_str.length()) {
138 LOG(LS_WARNING) << "Empty hostname in ICE URI: " << in_str;
139 return false;
140 }
141 *service_type = INVALID;
tfarina5237aaf2015-11-10 23:44:30 -0800142 for (size_t i = 0; i < arraysize(kValidIceServiceTypes); ++i) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700143 if (in_str.compare(0, colonpos, kValidIceServiceTypes[i]) == 0) {
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000144 *service_type = static_cast<ServiceType>(i);
145 break;
146 }
147 }
148 if (*service_type == INVALID) {
149 return false;
150 }
151 *hostname = in_str.substr(colonpos + 1, std::string::npos);
152 return true;
153}
154
deadbeef0a6c4ca2015-10-06 11:38:28 -0700155bool ParsePort(const std::string& in_str, int* port) {
156 // Make sure port only contains digits. FromString doesn't check this.
157 for (const char& c : in_str) {
158 if (!std::isdigit(c)) {
159 return false;
160 }
161 }
162 return rtc::FromString(in_str, port);
163}
164
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000165// This method parses IPv6 and IPv4 literal strings, along with hostnames in
166// standard hostname:port format.
167// Consider following formats as correct.
168// |hostname:port|, |[IPV6 address]:port|, |IPv4 address|:port,
deadbeef0a6c4ca2015-10-06 11:38:28 -0700169// |hostname|, |[IPv6 address]|, |IPv4 address|.
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000170bool ParseHostnameAndPortFromString(const std::string& in_str,
171 std::string* host,
172 int* port) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700173 RTC_DCHECK(host->empty());
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000174 if (in_str.at(0) == '[') {
175 std::string::size_type closebracket = in_str.rfind(']');
176 if (closebracket != std::string::npos) {
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000177 std::string::size_type colonpos = in_str.find(':', closebracket);
178 if (std::string::npos != colonpos) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700179 if (!ParsePort(in_str.substr(closebracket + 2, std::string::npos),
180 port)) {
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000181 return false;
182 }
183 }
deadbeef0a6c4ca2015-10-06 11:38:28 -0700184 *host = in_str.substr(1, closebracket - 1);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000185 } else {
186 return false;
187 }
188 } else {
189 std::string::size_type colonpos = in_str.find(':');
190 if (std::string::npos != colonpos) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700191 if (!ParsePort(in_str.substr(colonpos + 1, std::string::npos), port)) {
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000192 return false;
193 }
deadbeef0a6c4ca2015-10-06 11:38:28 -0700194 *host = in_str.substr(0, colonpos);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000195 } else {
196 *host = in_str;
197 }
198 }
deadbeef0a6c4ca2015-10-06 11:38:28 -0700199 return !host->empty();
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000200}
201
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800202// Adds a STUN or TURN server to the appropriate list,
deadbeef0a6c4ca2015-10-06 11:38:28 -0700203// by parsing |url| and using the username/password in |server|.
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200204bool ParseIceServerUrl(const PeerConnectionInterface::IceServer& server,
205 const std::string& url,
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800206 cricket::ServerAddresses* stun_servers,
207 std::vector<cricket::RelayServerConfig>* turn_servers) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000208 // draft-nandakumar-rtcweb-stun-uri-01
209 // stunURI = scheme ":" stun-host [ ":" stun-port ]
210 // scheme = "stun" / "stuns"
211 // stun-host = IP-literal / IPv4address / reg-name
212 // stun-port = *DIGIT
213
214 // draft-petithuguenin-behave-turn-uris-01
215 // turnURI = scheme ":" turn-host [ ":" turn-port ]
216 // [ "?transport=" transport ]
217 // scheme = "turn" / "turns"
218 // transport = "udp" / "tcp" / transport-ext
219 // transport-ext = 1*unreserved
220 // turn-host = IP-literal / IPv4address / reg-name
221 // turn-port = *DIGIT
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800222 RTC_DCHECK(stun_servers != nullptr);
223 RTC_DCHECK(turn_servers != nullptr);
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200224 std::vector<std::string> tokens;
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800225 cricket::ProtocolType turn_transport_type = cricket::PROTO_UDP;
deadbeef0a6c4ca2015-10-06 11:38:28 -0700226 RTC_DCHECK(!url.empty());
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200227 rtc::tokenize(url, '?', &tokens);
228 std::string uri_without_transport = tokens[0];
229 // Let's look into transport= param, if it exists.
230 if (tokens.size() == kTurnTransportTokensNum) { // ?transport= is present.
231 std::string uri_transport_param = tokens[1];
232 rtc::tokenize(uri_transport_param, '=', &tokens);
233 if (tokens[0] == kTransport) {
234 // As per above grammar transport param will be consist of lower case
235 // letters.
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800236 if (!cricket::StringToProto(tokens[1].c_str(), &turn_transport_type) ||
237 (turn_transport_type != cricket::PROTO_UDP &&
238 turn_transport_type != cricket::PROTO_TCP)) {
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200239 LOG(LS_WARNING) << "Transport param should always be udp or tcp.";
deadbeef0a6c4ca2015-10-06 11:38:28 -0700240 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000241 }
242 }
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200243 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000244
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200245 std::string hoststring;
deadbeef0a6c4ca2015-10-06 11:38:28 -0700246 ServiceType service_type;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200247 if (!GetServiceTypeAndHostnameFromUri(uri_without_transport,
248 &service_type,
249 &hoststring)) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700250 LOG(LS_WARNING) << "Invalid transport parameter in ICE URI: " << url;
251 return false;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200252 }
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000253
deadbeef0a6c4ca2015-10-06 11:38:28 -0700254 // GetServiceTypeAndHostnameFromUri should never give an empty hoststring
255 RTC_DCHECK(!hoststring.empty());
Tommi77d444a2015-04-24 15:38:38 +0200256
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200257 // Let's break hostname.
258 tokens.clear();
deadbeef0a6c4ca2015-10-06 11:38:28 -0700259 rtc::tokenize_with_empty_tokens(hoststring, '@', &tokens);
260
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200261 std::string username(server.username);
deadbeef0a6c4ca2015-10-06 11:38:28 -0700262 if (tokens.size() > kTurnHostTokensNum) {
263 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring;
264 return false;
265 }
266 if (tokens.size() == kTurnHostTokensNum) {
267 if (tokens[0].empty() || tokens[1].empty()) {
268 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring;
269 return false;
270 }
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200271 username.assign(rtc::s_url_decode(tokens[0]));
272 hoststring = tokens[1];
273 } else {
274 hoststring = tokens[0];
275 }
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000276
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200277 int port = kDefaultStunPort;
278 if (service_type == TURNS) {
279 port = kDefaultStunTlsPort;
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800280 turn_transport_type = cricket::PROTO_TCP;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200281 }
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000282
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200283 std::string address;
284 if (!ParseHostnameAndPortFromString(hoststring, &address, &port)) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700285 LOG(WARNING) << "Invalid hostname format: " << uri_without_transport;
286 return false;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200287 }
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +0000288
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200289 if (port <= 0 || port > 0xffff) {
290 LOG(WARNING) << "Invalid port: " << port;
deadbeef0a6c4ca2015-10-06 11:38:28 -0700291 return false;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200292 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000293
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200294 switch (service_type) {
295 case STUN:
296 case STUNS:
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800297 stun_servers->insert(rtc::SocketAddress(address, port));
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200298 break;
299 case TURN:
300 case TURNS: {
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200301 bool secure = (service_type == TURNS);
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800302 turn_servers->push_back(
303 cricket::RelayServerConfig(address, port, username, server.password,
304 turn_transport_type, secure));
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200305 break;
306 }
307 case INVALID:
308 default:
309 LOG(WARNING) << "Configuration not supported: " << url;
310 return false;
311 }
312 return true;
313}
314
deadbeefab9b2d12015-10-14 11:33:11 -0700315// Check if we can send |new_stream| on a PeerConnection.
316bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams,
317 webrtc::MediaStreamInterface* new_stream) {
318 if (!new_stream || !current_streams) {
319 return false;
320 }
321 if (current_streams->find(new_stream->label()) != nullptr) {
322 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label()
323 << " is already added.";
324 return false;
325 }
326 return true;
327}
328
329bool MediaContentDirectionHasSend(cricket::MediaContentDirection dir) {
330 return dir == cricket::MD_SENDONLY || dir == cricket::MD_SENDRECV;
331}
332
deadbeef5e97fb52015-10-15 12:49:08 -0700333// If the direction is "recvonly" or "inactive", treat the description
334// as containing no streams.
335// See: https://code.google.com/p/webrtc/issues/detail?id=5054
336std::vector<cricket::StreamParams> GetActiveStreams(
337 const cricket::MediaContentDescription* desc) {
338 return MediaContentDirectionHasSend(desc->direction())
339 ? desc->streams()
340 : std::vector<cricket::StreamParams>();
341}
342
deadbeefab9b2d12015-10-14 11:33:11 -0700343bool IsValidOfferToReceiveMedia(int value) {
344 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options;
345 return (value >= Options::kUndefined) &&
346 (value <= Options::kMaxOfferToReceiveMedia);
347}
348
349// Add the stream and RTP data channel info to |session_options|.
deadbeeffac06552015-11-25 11:26:01 -0800350void AddSendStreams(
351 cricket::MediaSessionOptions* session_options,
352 const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& senders,
353 const std::map<std::string, rtc::scoped_refptr<DataChannel>>&
354 rtp_data_channels) {
deadbeefab9b2d12015-10-14 11:33:11 -0700355 session_options->streams.clear();
deadbeeffac06552015-11-25 11:26:01 -0800356 for (const auto& sender : senders) {
357 session_options->AddSendStream(sender->media_type(), sender->id(),
358 sender->stream_id());
deadbeefab9b2d12015-10-14 11:33:11 -0700359 }
360
361 // Check for data channels.
362 for (const auto& kv : rtp_data_channels) {
363 const DataChannel* channel = kv.second;
364 if (channel->state() == DataChannel::kConnecting ||
365 channel->state() == DataChannel::kOpen) {
366 // |streamid| and |sync_label| are both set to the DataChannel label
367 // here so they can be signaled the same way as MediaStreams and Tracks.
368 // For MediaStreams, the sync_label is the MediaStream label and the
369 // track label is the same as |streamid|.
370 const std::string& streamid = channel->label();
371 const std::string& sync_label = channel->label();
372 session_options->AddSendStream(cricket::MEDIA_TYPE_DATA, streamid,
373 sync_label);
374 }
375 }
376}
377
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700378uint32_t ConvertIceTransportTypeToCandidateFilter(
379 PeerConnectionInterface::IceTransportsType type) {
380 switch (type) {
381 case PeerConnectionInterface::kNone:
382 return cricket::CF_NONE;
383 case PeerConnectionInterface::kRelay:
384 return cricket::CF_RELAY;
385 case PeerConnectionInterface::kNoHost:
386 return (cricket::CF_ALL & ~cricket::CF_HOST);
387 case PeerConnectionInterface::kAll:
388 return cricket::CF_ALL;
389 default:
390 ASSERT(false);
391 }
392 return cricket::CF_NONE;
393}
394
deadbeef0a6c4ca2015-10-06 11:38:28 -0700395} // namespace
396
397namespace webrtc {
398
zhihuang8f65cdf2016-05-06 18:40:30 -0700399// Generate a RTCP CNAME when a PeerConnection is created.
400std::string GenerateRtcpCname() {
401 std::string cname;
402 if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) {
403 LOG(LS_ERROR) << "Failed to generate CNAME.";
404 RTC_DCHECK(false);
405 }
406 return cname;
407}
408
htaa2a49d92016-03-04 02:51:39 -0800409bool ExtractMediaSessionOptions(
deadbeefab9b2d12015-10-14 11:33:11 -0700410 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
htaaac2dea2016-03-10 13:35:55 -0800411 bool is_offer,
deadbeefab9b2d12015-10-14 11:33:11 -0700412 cricket::MediaSessionOptions* session_options) {
413 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
414 if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) ||
415 !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) {
416 return false;
417 }
418
htaaac2dea2016-03-10 13:35:55 -0800419 // If constraints don't prevent us, we always accept video.
deadbeefc80741f2015-10-22 13:14:45 -0700420 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
deadbeefab9b2d12015-10-14 11:33:11 -0700421 session_options->recv_audio = (rtc_options.offer_to_receive_audio > 0);
htaaac2dea2016-03-10 13:35:55 -0800422 } else {
423 session_options->recv_audio = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700424 }
htaaac2dea2016-03-10 13:35:55 -0800425 // For offers, we only offer video if we have it or it's forced by options.
426 // For answers, we will always accept video (if offered).
deadbeefc80741f2015-10-22 13:14:45 -0700427 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
deadbeefab9b2d12015-10-14 11:33:11 -0700428 session_options->recv_video = (rtc_options.offer_to_receive_video > 0);
htaaac2dea2016-03-10 13:35:55 -0800429 } else if (is_offer) {
430 session_options->recv_video = false;
431 } else {
432 session_options->recv_video = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700433 }
434
435 session_options->vad_enabled = rtc_options.voice_activity_detection;
deadbeefc80741f2015-10-22 13:14:45 -0700436 session_options->bundle_enabled = rtc_options.use_rtp_mux;
deadbeef0ed85b22016-02-23 17:24:52 -0800437 for (auto& kv : session_options->transport_options) {
438 kv.second.ice_restart = rtc_options.ice_restart;
439 }
deadbeefab9b2d12015-10-14 11:33:11 -0700440
441 return true;
442}
443
444bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints,
445 cricket::MediaSessionOptions* session_options) {
446 bool value = false;
447 size_t mandatory_constraints_satisfied = 0;
448
449 // kOfferToReceiveAudio defaults to true according to spec.
450 if (!FindConstraint(constraints,
451 MediaConstraintsInterface::kOfferToReceiveAudio, &value,
452 &mandatory_constraints_satisfied) ||
453 value) {
454 session_options->recv_audio = true;
455 }
456
457 // kOfferToReceiveVideo defaults to false according to spec. But
458 // if it is an answer and video is offered, we should still accept video
459 // per default.
460 value = false;
461 if (!FindConstraint(constraints,
462 MediaConstraintsInterface::kOfferToReceiveVideo, &value,
463 &mandatory_constraints_satisfied) ||
464 value) {
465 session_options->recv_video = true;
466 }
467
468 if (FindConstraint(constraints,
469 MediaConstraintsInterface::kVoiceActivityDetection, &value,
470 &mandatory_constraints_satisfied)) {
471 session_options->vad_enabled = value;
472 }
473
474 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
475 &mandatory_constraints_satisfied)) {
476 session_options->bundle_enabled = value;
477 } else {
478 // kUseRtpMux defaults to true according to spec.
479 session_options->bundle_enabled = true;
480 }
deadbeefab9b2d12015-10-14 11:33:11 -0700481
deadbeef0ed85b22016-02-23 17:24:52 -0800482 bool ice_restart = false;
deadbeefab9b2d12015-10-14 11:33:11 -0700483 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
484 &value, &mandatory_constraints_satisfied)) {
deadbeefab9b2d12015-10-14 11:33:11 -0700485 // kIceRestart defaults to false according to spec.
deadbeef0ed85b22016-02-23 17:24:52 -0800486 ice_restart = true;
487 }
488 for (auto& kv : session_options->transport_options) {
489 kv.second.ice_restart = ice_restart;
deadbeefab9b2d12015-10-14 11:33:11 -0700490 }
491
492 if (!constraints) {
493 return true;
494 }
495 return mandatory_constraints_satisfied == constraints->GetMandatory().size();
496}
497
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200498bool ParseIceServers(const PeerConnectionInterface::IceServers& servers,
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800499 cricket::ServerAddresses* stun_servers,
500 std::vector<cricket::RelayServerConfig>* turn_servers) {
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200501 for (const webrtc::PeerConnectionInterface::IceServer& server : servers) {
502 if (!server.urls.empty()) {
503 for (const std::string& url : server.urls) {
Joachim Bauchd935f912015-05-29 22:14:21 +0200504 if (url.empty()) {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700505 LOG(LS_ERROR) << "Empty uri.";
506 return false;
Joachim Bauchd935f912015-05-29 22:14:21 +0200507 }
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800508 if (!ParseIceServerUrl(server, url, stun_servers, turn_servers)) {
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200509 return false;
510 }
511 }
512 } else if (!server.uri.empty()) {
513 // Fallback to old .uri if new .urls isn't present.
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800514 if (!ParseIceServerUrl(server, server.uri, stun_servers, turn_servers)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000515 return false;
Joachim Bauch7c4e7452015-05-28 23:06:30 +0200516 }
517 } else {
deadbeef0a6c4ca2015-10-06 11:38:28 -0700518 LOG(LS_ERROR) << "Empty uri.";
519 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000520 }
521 }
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800522 // Candidates must have unique priorities, so that connectivity checks
523 // are performed in a well-defined order.
524 int priority = static_cast<int>(turn_servers->size() - 1);
525 for (cricket::RelayServerConfig& turn_server : *turn_servers) {
526 // First in the list gets highest priority.
527 turn_server.priority = priority--;
528 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000529 return true;
530}
531
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000532PeerConnection::PeerConnection(PeerConnectionFactory* factory)
533 : factory_(factory),
534 observer_(NULL),
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +0000535 uma_observer_(NULL),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000536 signaling_state_(kStable),
537 ice_state_(kIceNew),
538 ice_connection_state_(kIceConnectionNew),
deadbeefab9b2d12015-10-14 11:33:11 -0700539 ice_gathering_state_(kIceGatheringNew),
zhihuang8f65cdf2016-05-06 18:40:30 -0700540 rtcp_cname_(GenerateRtcpCname()),
deadbeefab9b2d12015-10-14 11:33:11 -0700541 local_streams_(StreamCollection::Create()),
542 remote_streams_(StreamCollection::Create()) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000543
544PeerConnection::~PeerConnection() {
Peter Boström1a9d6152015-12-08 22:15:17 +0100545 TRACE_EVENT0("webrtc", "PeerConnection::~PeerConnection");
deadbeef0a6c4ca2015-10-06 11:38:28 -0700546 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeef70ab1a12015-09-28 16:53:55 -0700547 // Need to detach RTP senders/receivers from WebRtcSession,
548 // since it's about to be destroyed.
549 for (const auto& sender : senders_) {
550 sender->Stop();
551 }
552 for (const auto& receiver : receivers_) {
553 receiver->Stop();
554 }
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700555 // Destroy stats_ because it depends on session_.
556 stats_.reset(nullptr);
557 // Now destroy session_ before destroying other members,
558 // because its destruction fires signals (such as VoiceChannelDestroyed)
559 // which will trigger some final actions in PeerConnection...
560 session_.reset(nullptr);
deadbeef91dd5672016-05-18 16:55:30 -0700561 // port_allocator_ lives on the network thread and should be destroyed there.
562 network_thread()->Invoke<void>([this] { port_allocator_.reset(nullptr); });
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000563}
564
565bool PeerConnection::Initialize(
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000566 const PeerConnectionInterface::RTCConfiguration& configuration,
kwibergd1fe2812016-04-27 06:47:29 -0700567 std::unique_ptr<cricket::PortAllocator> allocator,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200568 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
deadbeef653b8e02015-11-11 12:55:10 -0800569 PeerConnectionObserver* observer) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100570 TRACE_EVENT0("webrtc", "PeerConnection::Initialize");
deadbeef653b8e02015-11-11 12:55:10 -0800571 RTC_DCHECK(observer != nullptr);
572 if (!observer) {
573 return false;
574 }
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000575 observer_ = observer;
576
kwiberg0eb15ed2015-12-17 03:04:15 -0800577 port_allocator_ = std::move(allocator);
deadbeef653b8e02015-11-11 12:55:10 -0800578
deadbeef91dd5672016-05-18 16:55:30 -0700579 // The port allocator lives on the network thread and should be initialized
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700580 // there.
deadbeef91dd5672016-05-18 16:55:30 -0700581 if (!network_thread()->Invoke<bool>(rtc::Bind(
582 &PeerConnection::InitializePortAllocator_n, this, configuration))) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000583 return false;
584 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000585
nissec36b31b2016-04-11 23:25:29 -0700586 media_controller_.reset(
587 factory_->CreateMediaController(configuration.media_config));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000588
stefanc1aeaf02015-10-15 07:26:07 -0700589 session_.reset(
danilchape9021a32016-05-17 01:52:02 -0700590 new WebRtcSession(media_controller_.get(), factory_->network_thread(),
591 factory_->worker_thread(), factory_->signaling_thread(),
592 port_allocator_.get()));
deadbeefab9b2d12015-10-14 11:33:11 -0700593 stats_.reset(new StatsCollector(this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000594
595 // Initialize the WebRtcSession. It creates transport channels etc.
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200596 if (!session_->Initialize(factory_->options(), std::move(cert_generator),
htaa2a49d92016-03-04 02:51:39 -0800597 configuration)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000598 return false;
deadbeefab9b2d12015-10-14 11:33:11 -0700599 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000600
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000601 // Register PeerConnection as receiver of local ice candidates.
602 // All the callbacks will be posted to the application from PeerConnection.
603 session_->RegisterIceObserver(this);
604 session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange);
deadbeefab9b2d12015-10-14 11:33:11 -0700605 session_->SignalVoiceChannelDestroyed.connect(
606 this, &PeerConnection::OnVoiceChannelDestroyed);
607 session_->SignalVideoChannelDestroyed.connect(
608 this, &PeerConnection::OnVideoChannelDestroyed);
609 session_->SignalDataChannelCreated.connect(
610 this, &PeerConnection::OnDataChannelCreated);
611 session_->SignalDataChannelDestroyed.connect(
612 this, &PeerConnection::OnDataChannelDestroyed);
613 session_->SignalDataChannelOpenMessage.connect(
614 this, &PeerConnection::OnDataChannelOpenMessage);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000615 return true;
616}
617
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000618rtc::scoped_refptr<StreamCollectionInterface>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000619PeerConnection::local_streams() {
deadbeefab9b2d12015-10-14 11:33:11 -0700620 return local_streams_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000621}
622
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000623rtc::scoped_refptr<StreamCollectionInterface>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000624PeerConnection::remote_streams() {
deadbeefab9b2d12015-10-14 11:33:11 -0700625 return remote_streams_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000626}
627
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000628bool PeerConnection::AddStream(MediaStreamInterface* local_stream) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100629 TRACE_EVENT0("webrtc", "PeerConnection::AddStream");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000630 if (IsClosed()) {
631 return false;
632 }
deadbeefab9b2d12015-10-14 11:33:11 -0700633 if (!CanAddLocalMediaStream(local_streams_, local_stream)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000634 return false;
635 }
deadbeefab9b2d12015-10-14 11:33:11 -0700636
637 local_streams_->AddStream(local_stream);
deadbeefeb459812015-12-15 19:24:43 -0800638 MediaStreamObserver* observer = new MediaStreamObserver(local_stream);
639 observer->SignalAudioTrackAdded.connect(this,
640 &PeerConnection::OnAudioTrackAdded);
641 observer->SignalAudioTrackRemoved.connect(
642 this, &PeerConnection::OnAudioTrackRemoved);
643 observer->SignalVideoTrackAdded.connect(this,
644 &PeerConnection::OnVideoTrackAdded);
645 observer->SignalVideoTrackRemoved.connect(
646 this, &PeerConnection::OnVideoTrackRemoved);
kwibergd1fe2812016-04-27 06:47:29 -0700647 stream_observers_.push_back(std::unique_ptr<MediaStreamObserver>(observer));
deadbeefab9b2d12015-10-14 11:33:11 -0700648
deadbeefab9b2d12015-10-14 11:33:11 -0700649 for (const auto& track : local_stream->GetAudioTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800650 OnAudioTrackAdded(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700651 }
652 for (const auto& track : local_stream->GetVideoTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800653 OnVideoTrackAdded(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700654 }
655
tommi@webrtc.org03505bc2014-07-14 20:15:26 +0000656 stats_->AddStream(local_stream);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000657 observer_->OnRenegotiationNeeded();
658 return true;
659}
660
661void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100662 TRACE_EVENT0("webrtc", "PeerConnection::RemoveStream");
deadbeefab9b2d12015-10-14 11:33:11 -0700663 for (const auto& track : local_stream->GetAudioTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800664 OnAudioTrackRemoved(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700665 }
666 for (const auto& track : local_stream->GetVideoTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800667 OnVideoTrackRemoved(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700668 }
669
670 local_streams_->RemoveStream(local_stream);
deadbeefeb459812015-12-15 19:24:43 -0800671 stream_observers_.erase(
672 std::remove_if(
673 stream_observers_.begin(), stream_observers_.end(),
kwibergd1fe2812016-04-27 06:47:29 -0700674 [local_stream](const std::unique_ptr<MediaStreamObserver>& observer) {
deadbeefeb459812015-12-15 19:24:43 -0800675 return observer->stream()->label().compare(local_stream->label()) ==
676 0;
677 }),
678 stream_observers_.end());
deadbeefab9b2d12015-10-14 11:33:11 -0700679
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680 if (IsClosed()) {
681 return;
682 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000683 observer_->OnRenegotiationNeeded();
684}
685
deadbeefe1f9d832016-01-14 15:35:42 -0800686rtc::scoped_refptr<RtpSenderInterface> PeerConnection::AddTrack(
687 MediaStreamTrackInterface* track,
688 std::vector<MediaStreamInterface*> streams) {
689 TRACE_EVENT0("webrtc", "PeerConnection::AddTrack");
690 if (IsClosed()) {
691 return nullptr;
692 }
693 if (streams.size() >= 2) {
694 LOG(LS_ERROR)
695 << "Adding a track with two streams is not currently supported.";
696 return nullptr;
697 }
698 // TODO(deadbeef): Support adding a track to two different senders.
699 if (FindSenderForTrack(track) != senders_.end()) {
700 LOG(LS_ERROR) << "Sender for track " << track->id() << " already exists.";
701 return nullptr;
702 }
703
704 // TODO(deadbeef): Support adding a track to multiple streams.
705 rtc::scoped_refptr<RtpSenderInterface> new_sender;
706 if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
707 new_sender = RtpSenderProxy::Create(
708 signaling_thread(),
709 new AudioRtpSender(static_cast<AudioTrackInterface*>(track),
710 session_.get(), stats_.get()));
711 if (!streams.empty()) {
712 new_sender->set_stream_id(streams[0]->label());
713 }
714 const TrackInfo* track_info = FindTrackInfo(
715 local_audio_tracks_, new_sender->stream_id(), track->id());
716 if (track_info) {
717 new_sender->SetSsrc(track_info->ssrc);
718 }
719 } else if (track->kind() == MediaStreamTrackInterface::kVideoKind) {
720 new_sender = RtpSenderProxy::Create(
721 signaling_thread(),
722 new VideoRtpSender(static_cast<VideoTrackInterface*>(track),
723 session_.get()));
724 if (!streams.empty()) {
725 new_sender->set_stream_id(streams[0]->label());
726 }
727 const TrackInfo* track_info = FindTrackInfo(
728 local_video_tracks_, new_sender->stream_id(), track->id());
729 if (track_info) {
730 new_sender->SetSsrc(track_info->ssrc);
731 }
732 } else {
733 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << track->kind();
734 return rtc::scoped_refptr<RtpSenderInterface>();
735 }
736
737 senders_.push_back(new_sender);
738 observer_->OnRenegotiationNeeded();
739 return new_sender;
740}
741
742bool PeerConnection::RemoveTrack(RtpSenderInterface* sender) {
743 TRACE_EVENT0("webrtc", "PeerConnection::RemoveTrack");
744 if (IsClosed()) {
745 return false;
746 }
747
748 auto it = std::find(senders_.begin(), senders_.end(), sender);
749 if (it == senders_.end()) {
750 LOG(LS_ERROR) << "Couldn't find sender " << sender->id() << " to remove.";
751 return false;
752 }
753 (*it)->Stop();
754 senders_.erase(it);
755
756 observer_->OnRenegotiationNeeded();
757 return true;
758}
759
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000760rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000761 AudioTrackInterface* track) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100762 TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000763 if (!track) {
764 LOG(LS_ERROR) << "CreateDtmfSender - track is NULL.";
765 return NULL;
766 }
deadbeefab9b2d12015-10-14 11:33:11 -0700767 if (!local_streams_->FindAudioTrack(track->id())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000768 LOG(LS_ERROR) << "CreateDtmfSender is called with a non local audio track.";
769 return NULL;
770 }
771
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000772 rtc::scoped_refptr<DtmfSenderInterface> sender(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000773 DtmfSender::Create(track, signaling_thread(), session_.get()));
774 if (!sender.get()) {
775 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create.";
776 return NULL;
777 }
778 return DtmfSenderProxy::Create(signaling_thread(), sender.get());
779}
780
deadbeeffac06552015-11-25 11:26:01 -0800781rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
deadbeefbd7d8f72015-12-18 16:58:44 -0800782 const std::string& kind,
783 const std::string& stream_id) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100784 TRACE_EVENT0("webrtc", "PeerConnection::CreateSender");
deadbeefe1f9d832016-01-14 15:35:42 -0800785 rtc::scoped_refptr<RtpSenderInterface> new_sender;
deadbeeffac06552015-11-25 11:26:01 -0800786 if (kind == MediaStreamTrackInterface::kAudioKind) {
deadbeefe1f9d832016-01-14 15:35:42 -0800787 new_sender = RtpSenderProxy::Create(
788 signaling_thread(), new AudioRtpSender(session_.get(), stats_.get()));
deadbeeffac06552015-11-25 11:26:01 -0800789 } else if (kind == MediaStreamTrackInterface::kVideoKind) {
deadbeefe1f9d832016-01-14 15:35:42 -0800790 new_sender = RtpSenderProxy::Create(signaling_thread(),
791 new VideoRtpSender(session_.get()));
deadbeeffac06552015-11-25 11:26:01 -0800792 } else {
793 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind;
deadbeefe1f9d832016-01-14 15:35:42 -0800794 return new_sender;
deadbeeffac06552015-11-25 11:26:01 -0800795 }
deadbeefbd7d8f72015-12-18 16:58:44 -0800796 if (!stream_id.empty()) {
797 new_sender->set_stream_id(stream_id);
798 }
deadbeeffac06552015-11-25 11:26:01 -0800799 senders_.push_back(new_sender);
deadbeefe1f9d832016-01-14 15:35:42 -0800800 return new_sender;
deadbeeffac06552015-11-25 11:26:01 -0800801}
802
deadbeef70ab1a12015-09-28 16:53:55 -0700803std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders()
804 const {
deadbeefe1f9d832016-01-14 15:35:42 -0800805 return senders_;
deadbeef70ab1a12015-09-28 16:53:55 -0700806}
807
808std::vector<rtc::scoped_refptr<RtpReceiverInterface>>
809PeerConnection::GetReceivers() const {
deadbeefe1f9d832016-01-14 15:35:42 -0800810 return receivers_;
deadbeef70ab1a12015-09-28 16:53:55 -0700811}
812
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000813bool PeerConnection::GetStats(StatsObserver* observer,
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000814 MediaStreamTrackInterface* track,
815 StatsOutputLevel level) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100816 TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
deadbeef0a6c4ca2015-10-06 11:38:28 -0700817 RTC_DCHECK(signaling_thread()->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000818 if (!VERIFY(observer != NULL)) {
819 LOG(LS_ERROR) << "GetStats - observer is NULL.";
820 return false;
821 }
822
tommi@webrtc.org03505bc2014-07-14 20:15:26 +0000823 stats_->UpdateStats(level);
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000824 signaling_thread()->Post(this, MSG_GETSTATS,
825 new GetStatsMsg(observer, track));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000826 return true;
827}
828
829PeerConnectionInterface::SignalingState PeerConnection::signaling_state() {
830 return signaling_state_;
831}
832
833PeerConnectionInterface::IceState PeerConnection::ice_state() {
834 return ice_state_;
835}
836
837PeerConnectionInterface::IceConnectionState
838PeerConnection::ice_connection_state() {
839 return ice_connection_state_;
840}
841
842PeerConnectionInterface::IceGatheringState
843PeerConnection::ice_gathering_state() {
844 return ice_gathering_state_;
845}
846
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000847rtc::scoped_refptr<DataChannelInterface>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000848PeerConnection::CreateDataChannel(
849 const std::string& label,
850 const DataChannelInit* config) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100851 TRACE_EVENT0("webrtc", "PeerConnection::CreateDataChannel");
deadbeefab9b2d12015-10-14 11:33:11 -0700852 bool first_datachannel = !HasDataChannels();
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +0000853
kwibergd1fe2812016-04-27 06:47:29 -0700854 std::unique_ptr<InternalDataChannelInit> internal_config;
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000855 if (config) {
856 internal_config.reset(new InternalDataChannelInit(*config));
857 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000858 rtc::scoped_refptr<DataChannelInterface> channel(
deadbeefab9b2d12015-10-14 11:33:11 -0700859 InternalCreateDataChannel(label, internal_config.get()));
860 if (!channel.get()) {
861 return nullptr;
862 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000863
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +0000864 // Trigger the onRenegotiationNeeded event for every new RTP DataChannel, or
865 // the first SCTP DataChannel.
866 if (session_->data_channel_type() == cricket::DCT_RTP || first_datachannel) {
867 observer_->OnRenegotiationNeeded();
868 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000869
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000870 return DataChannelProxy::Create(signaling_thread(), channel.get());
871}
872
873void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
874 const MediaConstraintsInterface* constraints) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100875 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer");
deadbeefab9b2d12015-10-14 11:33:11 -0700876 if (!VERIFY(observer != nullptr)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000877 LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
878 return;
879 }
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000880 RTCOfferAnswerOptions options;
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000881
882 bool value;
883 size_t mandatory_constraints = 0;
884
885 if (FindConstraint(constraints,
886 MediaConstraintsInterface::kOfferToReceiveAudio,
887 &value,
888 &mandatory_constraints)) {
889 options.offer_to_receive_audio =
890 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
891 }
892
893 if (FindConstraint(constraints,
894 MediaConstraintsInterface::kOfferToReceiveVideo,
895 &value,
896 &mandatory_constraints)) {
897 options.offer_to_receive_video =
898 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
899 }
900
901 if (FindConstraint(constraints,
902 MediaConstraintsInterface::kVoiceActivityDetection,
903 &value,
904 &mandatory_constraints)) {
905 options.voice_activity_detection = value;
906 }
907
908 if (FindConstraint(constraints,
909 MediaConstraintsInterface::kIceRestart,
910 &value,
911 &mandatory_constraints)) {
912 options.ice_restart = value;
913 }
914
915 if (FindConstraint(constraints,
916 MediaConstraintsInterface::kUseRtpMux,
917 &value,
918 &mandatory_constraints)) {
919 options.use_rtp_mux = value;
920 }
921
922 CreateOffer(observer, options);
923}
924
925void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
926 const RTCOfferAnswerOptions& options) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100927 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer");
deadbeefab9b2d12015-10-14 11:33:11 -0700928 if (!VERIFY(observer != nullptr)) {
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000929 LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
930 return;
931 }
deadbeefab9b2d12015-10-14 11:33:11 -0700932
933 cricket::MediaSessionOptions session_options;
934 if (!GetOptionsForOffer(options, &session_options)) {
935 std::string error = "CreateOffer called with invalid options.";
936 LOG(LS_ERROR) << error;
937 PostCreateSessionDescriptionFailure(observer, error);
938 return;
939 }
940
941 session_->CreateOffer(observer, options, session_options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000942}
943
944void PeerConnection::CreateAnswer(
945 CreateSessionDescriptionObserver* observer,
946 const MediaConstraintsInterface* constraints) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100947 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
deadbeefab9b2d12015-10-14 11:33:11 -0700948 if (!VERIFY(observer != nullptr)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000949 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
950 return;
951 }
deadbeefab9b2d12015-10-14 11:33:11 -0700952
953 cricket::MediaSessionOptions session_options;
954 if (!GetOptionsForAnswer(constraints, &session_options)) {
955 std::string error = "CreateAnswer called with invalid constraints.";
956 LOG(LS_ERROR) << error;
957 PostCreateSessionDescriptionFailure(observer, error);
958 return;
959 }
960
htaa2a49d92016-03-04 02:51:39 -0800961 session_->CreateAnswer(observer, session_options);
962}
963
964void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer,
965 const RTCOfferAnswerOptions& options) {
966 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
967 if (!VERIFY(observer != nullptr)) {
968 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
969 return;
970 }
971
972 cricket::MediaSessionOptions session_options;
973 if (!GetOptionsForAnswer(options, &session_options)) {
974 std::string error = "CreateAnswer called with invalid options.";
975 LOG(LS_ERROR) << error;
976 PostCreateSessionDescriptionFailure(observer, error);
977 return;
978 }
979
980 session_->CreateAnswer(observer, session_options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000981}
982
983void PeerConnection::SetLocalDescription(
984 SetSessionDescriptionObserver* observer,
985 SessionDescriptionInterface* desc) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100986 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription");
deadbeefab9b2d12015-10-14 11:33:11 -0700987 if (!VERIFY(observer != nullptr)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000988 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL.";
989 return;
990 }
991 if (!desc) {
992 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
993 return;
994 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000995 // Update stats here so that we have the most recent stats for tracks and
996 // streams that might be removed by updating the session description.
tommi@webrtc.org03505bc2014-07-14 20:15:26 +0000997 stats_->UpdateStats(kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000998 std::string error;
999 if (!session_->SetLocalDescription(desc, &error)) {
1000 PostSetSessionDescriptionFailure(observer, error);
1001 return;
1002 }
deadbeefab9b2d12015-10-14 11:33:11 -07001003
1004 // If setting the description decided our SSL role, allocate any necessary
1005 // SCTP sids.
1006 rtc::SSLRole role;
1007 if (session_->data_channel_type() == cricket::DCT_SCTP &&
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001008 session_->GetSslRole(session_->data_channel(), &role)) {
deadbeefab9b2d12015-10-14 11:33:11 -07001009 AllocateSctpSids(role);
1010 }
1011
1012 // Update state and SSRC of local MediaStreams and DataChannels based on the
1013 // local session description.
1014 const cricket::ContentInfo* audio_content =
1015 GetFirstAudioContent(desc->description());
1016 if (audio_content) {
deadbeeffaac4972015-11-12 15:33:07 -08001017 if (audio_content->rejected) {
1018 RemoveTracks(cricket::MEDIA_TYPE_AUDIO);
1019 } else {
1020 const cricket::AudioContentDescription* audio_desc =
1021 static_cast<const cricket::AudioContentDescription*>(
1022 audio_content->description);
1023 UpdateLocalTracks(audio_desc->streams(), audio_desc->type());
1024 }
deadbeefab9b2d12015-10-14 11:33:11 -07001025 }
1026
1027 const cricket::ContentInfo* video_content =
1028 GetFirstVideoContent(desc->description());
1029 if (video_content) {
deadbeeffaac4972015-11-12 15:33:07 -08001030 if (video_content->rejected) {
1031 RemoveTracks(cricket::MEDIA_TYPE_VIDEO);
1032 } else {
1033 const cricket::VideoContentDescription* video_desc =
1034 static_cast<const cricket::VideoContentDescription*>(
1035 video_content->description);
1036 UpdateLocalTracks(video_desc->streams(), video_desc->type());
1037 }
deadbeefab9b2d12015-10-14 11:33:11 -07001038 }
1039
1040 const cricket::ContentInfo* data_content =
1041 GetFirstDataContent(desc->description());
1042 if (data_content) {
1043 const cricket::DataContentDescription* data_desc =
1044 static_cast<const cricket::DataContentDescription*>(
1045 data_content->description);
1046 if (rtc::starts_with(data_desc->protocol().data(),
1047 cricket::kMediaProtocolRtpPrefix)) {
1048 UpdateLocalRtpDataChannels(data_desc->streams());
1049 }
1050 }
1051
1052 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001053 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
deadbeefab9b2d12015-10-14 11:33:11 -07001054
deadbeefcbecd352015-09-23 11:50:27 -07001055 // MaybeStartGathering needs to be called after posting
1056 // MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates
1057 // before signaling that SetLocalDescription completed.
1058 session_->MaybeStartGathering();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001059}
1060
1061void PeerConnection::SetRemoteDescription(
1062 SetSessionDescriptionObserver* observer,
1063 SessionDescriptionInterface* desc) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001064 TRACE_EVENT0("webrtc", "PeerConnection::SetRemoteDescription");
deadbeefab9b2d12015-10-14 11:33:11 -07001065 if (!VERIFY(observer != nullptr)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001066 LOG(LS_ERROR) << "SetRemoteDescription - observer is NULL.";
1067 return;
1068 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001069 if (!desc) {
1070 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
1071 return;
1072 }
1073 // Update stats here so that we have the most recent stats for tracks and
1074 // streams that might be removed by updating the session description.
tommi@webrtc.org03505bc2014-07-14 20:15:26 +00001075 stats_->UpdateStats(kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001076 std::string error;
1077 if (!session_->SetRemoteDescription(desc, &error)) {
1078 PostSetSessionDescriptionFailure(observer, error);
1079 return;
1080 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001081
deadbeefab9b2d12015-10-14 11:33:11 -07001082 // If setting the description decided our SSL role, allocate any necessary
1083 // SCTP sids.
1084 rtc::SSLRole role;
1085 if (session_->data_channel_type() == cricket::DCT_SCTP &&
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001086 session_->GetSslRole(session_->data_channel(), &role)) {
deadbeefab9b2d12015-10-14 11:33:11 -07001087 AllocateSctpSids(role);
1088 }
1089
1090 const cricket::SessionDescription* remote_desc = desc->description();
deadbeefbda7e0b2015-12-08 17:13:40 -08001091 const cricket::ContentInfo* audio_content = GetFirstAudioContent(remote_desc);
1092 const cricket::ContentInfo* video_content = GetFirstVideoContent(remote_desc);
1093 const cricket::AudioContentDescription* audio_desc =
1094 GetFirstAudioContentDescription(remote_desc);
1095 const cricket::VideoContentDescription* video_desc =
1096 GetFirstVideoContentDescription(remote_desc);
1097 const cricket::DataContentDescription* data_desc =
1098 GetFirstDataContentDescription(remote_desc);
1099
1100 // Check if the descriptions include streams, just in case the peer supports
1101 // MSID, but doesn't indicate so with "a=msid-semantic".
1102 if (remote_desc->msid_supported() ||
1103 (audio_desc && !audio_desc->streams().empty()) ||
1104 (video_desc && !video_desc->streams().empty())) {
1105 remote_peer_supports_msid_ = true;
1106 }
deadbeefab9b2d12015-10-14 11:33:11 -07001107
1108 // We wait to signal new streams until we finish processing the description,
1109 // since only at that point will new streams have all their tracks.
1110 rtc::scoped_refptr<StreamCollection> new_streams(StreamCollection::Create());
1111
1112 // Find all audio rtp streams and create corresponding remote AudioTracks
1113 // and MediaStreams.
deadbeefab9b2d12015-10-14 11:33:11 -07001114 if (audio_content) {
deadbeeffaac4972015-11-12 15:33:07 -08001115 if (audio_content->rejected) {
1116 RemoveTracks(cricket::MEDIA_TYPE_AUDIO);
1117 } else {
deadbeefbda7e0b2015-12-08 17:13:40 -08001118 bool default_audio_track_needed =
1119 !remote_peer_supports_msid_ &&
1120 MediaContentDirectionHasSend(audio_desc->direction());
1121 UpdateRemoteStreamsList(GetActiveStreams(audio_desc),
1122 default_audio_track_needed, audio_desc->type(),
deadbeeffaac4972015-11-12 15:33:07 -08001123 new_streams);
deadbeeffaac4972015-11-12 15:33:07 -08001124 }
deadbeefab9b2d12015-10-14 11:33:11 -07001125 }
1126
1127 // Find all video rtp streams and create corresponding remote VideoTracks
1128 // and MediaStreams.
deadbeefab9b2d12015-10-14 11:33:11 -07001129 if (video_content) {
deadbeeffaac4972015-11-12 15:33:07 -08001130 if (video_content->rejected) {
1131 RemoveTracks(cricket::MEDIA_TYPE_VIDEO);
1132 } else {
deadbeefbda7e0b2015-12-08 17:13:40 -08001133 bool default_video_track_needed =
1134 !remote_peer_supports_msid_ &&
1135 MediaContentDirectionHasSend(video_desc->direction());
1136 UpdateRemoteStreamsList(GetActiveStreams(video_desc),
1137 default_video_track_needed, video_desc->type(),
deadbeeffaac4972015-11-12 15:33:07 -08001138 new_streams);
deadbeeffaac4972015-11-12 15:33:07 -08001139 }
deadbeefab9b2d12015-10-14 11:33:11 -07001140 }
1141
1142 // Update the DataChannels with the information from the remote peer.
deadbeefbda7e0b2015-12-08 17:13:40 -08001143 if (data_desc) {
1144 if (rtc::starts_with(data_desc->protocol().data(),
deadbeefab9b2d12015-10-14 11:33:11 -07001145 cricket::kMediaProtocolRtpPrefix)) {
deadbeefbda7e0b2015-12-08 17:13:40 -08001146 UpdateRemoteRtpDataChannels(GetActiveStreams(data_desc));
deadbeefab9b2d12015-10-14 11:33:11 -07001147 }
1148 }
1149
1150 // Iterate new_streams and notify the observer about new MediaStreams.
1151 for (size_t i = 0; i < new_streams->count(); ++i) {
1152 MediaStreamInterface* new_stream = new_streams->at(i);
1153 stats_->AddStream(new_stream);
Taylor Brandstetter98cde262016-05-31 13:02:21 -07001154 // Call both the raw pointer and scoped_refptr versions of the method
1155 // for compatibility.
deadbeefab9b2d12015-10-14 11:33:11 -07001156 observer_->OnAddStream(new_stream);
Taylor Brandstetter98cde262016-05-31 13:02:21 -07001157 observer_->OnAddStream(
1158 rtc::scoped_refptr<MediaStreamInterface>(new_stream));
deadbeefab9b2d12015-10-14 11:33:11 -07001159 }
1160
deadbeefbda7e0b2015-12-08 17:13:40 -08001161 UpdateEndedRemoteMediaStreams();
deadbeefab9b2d12015-10-14 11:33:11 -07001162
1163 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
1164 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
deadbeeffc648b62015-10-13 16:42:33 -07001165}
1166
Taylor Brandstettera1c30352016-05-13 08:15:11 -07001167bool PeerConnection::SetConfiguration(const RTCConfiguration& configuration) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001168 TRACE_EVENT0("webrtc", "PeerConnection::SetConfiguration");
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001169 if (port_allocator_) {
deadbeef91dd5672016-05-18 16:55:30 -07001170 if (!network_thread()->Invoke<bool>(
1171 rtc::Bind(&PeerConnection::ReconfigurePortAllocator_n, this,
Taylor Brandstettera1c30352016-05-13 08:15:11 -07001172 configuration))) {
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001173 return false;
1174 }
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001175 }
Taylor Brandstettera1c30352016-05-13 08:15:11 -07001176
1177 // TODO(deadbeef): Shouldn't have to hop to the worker thread twice...
1178 session_->SetIceConfig(session_->ParseIceConfig(configuration));
1179 return true;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001180}
1181
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001182bool PeerConnection::AddIceCandidate(
1183 const IceCandidateInterface* ice_candidate) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001184 TRACE_EVENT0("webrtc", "PeerConnection::AddIceCandidate");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001185 return session_->ProcessIceMessage(ice_candidate);
1186}
1187
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001188bool PeerConnection::RemoveIceCandidates(
1189 const std::vector<cricket::Candidate>& candidates) {
1190 TRACE_EVENT0("webrtc", "PeerConnection::RemoveIceCandidates");
1191 return session_->RemoveRemoteIceCandidates(candidates);
1192}
1193
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +00001194void PeerConnection::RegisterUMAObserver(UMAObserver* observer) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001195 TRACE_EVENT0("webrtc", "PeerConnection::RegisterUmaObserver");
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +00001196 uma_observer_ = observer;
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001197
1198 if (session_) {
1199 session_->set_metrics_observer(uma_observer_);
1200 }
1201
mallinath@webrtc.orgd37bcfa2014-05-12 23:10:18 +00001202 // Send information about IPv4/IPv6 status.
1203 if (uma_observer_ && port_allocator_) {
1204 if (port_allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_IPV6) {
Guo-wei Shiehdfbe6792015-09-03 17:12:07 -07001205 uma_observer_->IncrementEnumCounter(
1206 kEnumCounterAddressFamily, kPeerConnection_IPv6,
1207 kPeerConnectionAddressFamilyCounter_Max);
mallinath@webrtc.orgb445f262014-05-23 22:19:37 +00001208 } else {
Guo-wei Shiehdfbe6792015-09-03 17:12:07 -07001209 uma_observer_->IncrementEnumCounter(
1210 kEnumCounterAddressFamily, kPeerConnection_IPv4,
1211 kPeerConnectionAddressFamilyCounter_Max);
mallinath@webrtc.orgd37bcfa2014-05-12 23:10:18 +00001212 }
1213 }
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +00001214}
1215
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001216const SessionDescriptionInterface* PeerConnection::local_description() const {
1217 return session_->local_description();
1218}
1219
1220const SessionDescriptionInterface* PeerConnection::remote_description() const {
1221 return session_->remote_description();
1222}
1223
1224void PeerConnection::Close() {
Peter Boström1a9d6152015-12-08 22:15:17 +01001225 TRACE_EVENT0("webrtc", "PeerConnection::Close");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001226 // Update stats here so that we have the most recent stats for tracks and
1227 // streams before the channels are closed.
tommi@webrtc.org03505bc2014-07-14 20:15:26 +00001228 stats_->UpdateStats(kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001229
deadbeefd59daf82015-10-14 15:02:44 -07001230 session_->Close();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001231}
1232
deadbeefd59daf82015-10-14 15:02:44 -07001233void PeerConnection::OnSessionStateChange(WebRtcSession* /*session*/,
1234 WebRtcSession::State state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001235 switch (state) {
deadbeefd59daf82015-10-14 15:02:44 -07001236 case WebRtcSession::STATE_INIT:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001237 ChangeSignalingState(PeerConnectionInterface::kStable);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001238 break;
deadbeefd59daf82015-10-14 15:02:44 -07001239 case WebRtcSession::STATE_SENTOFFER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001240 ChangeSignalingState(PeerConnectionInterface::kHaveLocalOffer);
1241 break;
deadbeefd59daf82015-10-14 15:02:44 -07001242 case WebRtcSession::STATE_SENTPRANSWER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001243 ChangeSignalingState(PeerConnectionInterface::kHaveLocalPrAnswer);
1244 break;
deadbeefd59daf82015-10-14 15:02:44 -07001245 case WebRtcSession::STATE_RECEIVEDOFFER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001246 ChangeSignalingState(PeerConnectionInterface::kHaveRemoteOffer);
1247 break;
deadbeefd59daf82015-10-14 15:02:44 -07001248 case WebRtcSession::STATE_RECEIVEDPRANSWER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001249 ChangeSignalingState(PeerConnectionInterface::kHaveRemotePrAnswer);
1250 break;
deadbeefd59daf82015-10-14 15:02:44 -07001251 case WebRtcSession::STATE_INPROGRESS:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001252 ChangeSignalingState(PeerConnectionInterface::kStable);
1253 break;
deadbeefd59daf82015-10-14 15:02:44 -07001254 case WebRtcSession::STATE_CLOSED:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001255 ChangeSignalingState(PeerConnectionInterface::kClosed);
1256 break;
1257 default:
1258 break;
1259 }
1260}
1261
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001262void PeerConnection::OnMessage(rtc::Message* msg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001263 switch (msg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001264 case MSG_SET_SESSIONDESCRIPTION_SUCCESS: {
1265 SetSessionDescriptionMsg* param =
1266 static_cast<SetSessionDescriptionMsg*>(msg->pdata);
1267 param->observer->OnSuccess();
1268 delete param;
1269 break;
1270 }
1271 case MSG_SET_SESSIONDESCRIPTION_FAILED: {
1272 SetSessionDescriptionMsg* param =
1273 static_cast<SetSessionDescriptionMsg*>(msg->pdata);
1274 param->observer->OnFailure(param->error);
1275 delete param;
1276 break;
1277 }
deadbeefab9b2d12015-10-14 11:33:11 -07001278 case MSG_CREATE_SESSIONDESCRIPTION_FAILED: {
1279 CreateSessionDescriptionMsg* param =
1280 static_cast<CreateSessionDescriptionMsg*>(msg->pdata);
1281 param->observer->OnFailure(param->error);
1282 delete param;
1283 break;
1284 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001285 case MSG_GETSTATS: {
1286 GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata);
tommi@webrtc.org5b06b062014-08-15 08:38:30 +00001287 StatsReports reports;
1288 stats_->GetStats(param->track, &reports);
1289 param->observer->OnComplete(reports);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001290 delete param;
1291 break;
1292 }
deadbeefbd292462015-12-14 18:15:29 -08001293 case MSG_FREE_DATACHANNELS: {
1294 sctp_data_channels_to_free_.clear();
1295 break;
1296 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001297 default:
deadbeef0a6c4ca2015-10-06 11:38:28 -07001298 RTC_DCHECK(false && "Not implemented");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001299 break;
1300 }
1301}
1302
deadbeefab9b2d12015-10-14 11:33:11 -07001303void PeerConnection::CreateAudioReceiver(MediaStreamInterface* stream,
perkjd61bf802016-03-24 03:16:19 -07001304 const std::string& track_id,
deadbeefab9b2d12015-10-14 11:33:11 -07001305 uint32_t ssrc) {
deadbeefe1f9d832016-01-14 15:35:42 -08001306 receivers_.push_back(RtpReceiverProxy::Create(
1307 signaling_thread(),
perkjd61bf802016-03-24 03:16:19 -07001308 new AudioRtpReceiver(stream, track_id, ssrc, session_.get())));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001309}
1310
deadbeefab9b2d12015-10-14 11:33:11 -07001311void PeerConnection::CreateVideoReceiver(MediaStreamInterface* stream,
perkjf0dcfe22016-03-10 18:32:00 +01001312 const std::string& track_id,
deadbeefab9b2d12015-10-14 11:33:11 -07001313 uint32_t ssrc) {
perkjd61bf802016-03-24 03:16:19 -07001314 receivers_.push_back(RtpReceiverProxy::Create(
1315 signaling_thread(),
1316 new VideoRtpReceiver(stream, track_id, factory_->worker_thread(), ssrc,
1317 session_.get())));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001318}
1319
deadbeef70ab1a12015-09-28 16:53:55 -07001320// TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote
1321// description.
perkjd61bf802016-03-24 03:16:19 -07001322void PeerConnection::DestroyReceiver(const std::string& track_id) {
1323 auto it = FindReceiverForTrack(track_id);
deadbeef70ab1a12015-09-28 16:53:55 -07001324 if (it == receivers_.end()) {
perkjd61bf802016-03-24 03:16:19 -07001325 LOG(LS_WARNING) << "RtpReceiver for track with id " << track_id
deadbeef70ab1a12015-09-28 16:53:55 -07001326 << " doesn't exist.";
1327 } else {
1328 (*it)->Stop();
1329 receivers_.erase(it);
1330 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001331}
1332
perkjd61bf802016-03-24 03:16:19 -07001333void PeerConnection::StopReceivers(cricket::MediaType media_type) {
1334 TrackInfos* current_tracks = GetRemoteTracks(media_type);
1335 for (const auto& track_info : *current_tracks) {
1336 auto it = FindReceiverForTrack(track_info.track_id);
1337 if (it == receivers_.end()) {
1338 LOG(LS_WARNING) << "RtpReceiver for track with id " << track_info.track_id
1339 << " doesn't exist.";
1340 } else {
1341 (*it)->Stop();
1342 }
deadbeef70ab1a12015-09-28 16:53:55 -07001343 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001344}
deadbeef70ab1a12015-09-28 16:53:55 -07001345
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001346void PeerConnection::OnIceConnectionChange(
1347 PeerConnectionInterface::IceConnectionState new_state) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001348 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -07001349 // After transitioning to "closed", ignore any additional states from
1350 // WebRtcSession (such as "disconnected").
deadbeefab9b2d12015-10-14 11:33:11 -07001351 if (IsClosed()) {
deadbeefcbecd352015-09-23 11:50:27 -07001352 return;
1353 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001354 ice_connection_state_ = new_state;
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001355 observer_->OnIceConnectionChange(ice_connection_state_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001356}
1357
1358void PeerConnection::OnIceGatheringChange(
1359 PeerConnectionInterface::IceGatheringState new_state) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001360 RTC_DCHECK(signaling_thread()->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001361 if (IsClosed()) {
1362 return;
1363 }
1364 ice_gathering_state_ = new_state;
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001365 observer_->OnIceGatheringChange(ice_gathering_state_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001366}
1367
1368void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001369 RTC_DCHECK(signaling_thread()->IsCurrent());
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001370 observer_->OnIceCandidate(candidate);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001371}
1372
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001373void PeerConnection::OnIceCandidatesRemoved(
1374 const std::vector<cricket::Candidate>& candidates) {
1375 RTC_DCHECK(signaling_thread()->IsCurrent());
1376 observer_->OnIceCandidatesRemoved(candidates);
1377}
1378
Peter Thatcher54360512015-07-08 11:08:35 -07001379void PeerConnection::OnIceConnectionReceivingChange(bool receiving) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001380 RTC_DCHECK(signaling_thread()->IsCurrent());
Peter Thatcher54360512015-07-08 11:08:35 -07001381 observer_->OnIceConnectionReceivingChange(receiving);
1382}
1383
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001384void PeerConnection::ChangeSignalingState(
1385 PeerConnectionInterface::SignalingState signaling_state) {
1386 signaling_state_ = signaling_state;
1387 if (signaling_state == kClosed) {
1388 ice_connection_state_ = kIceConnectionClosed;
1389 observer_->OnIceConnectionChange(ice_connection_state_);
1390 if (ice_gathering_state_ != kIceGatheringComplete) {
1391 ice_gathering_state_ = kIceGatheringComplete;
1392 observer_->OnIceGatheringChange(ice_gathering_state_);
1393 }
1394 }
1395 observer_->OnSignalingChange(signaling_state_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001396}
1397
deadbeefeb459812015-12-15 19:24:43 -08001398void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track,
1399 MediaStreamInterface* stream) {
1400 auto sender = FindSenderForTrack(track);
1401 if (sender != senders_.end()) {
1402 // We already have a sender for this track, so just change the stream_id
1403 // so that it's correct in the next call to CreateOffer.
1404 (*sender)->set_stream_id(stream->label());
1405 return;
1406 }
1407
1408 // Normal case; we've never seen this track before.
deadbeefe1f9d832016-01-14 15:35:42 -08001409 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create(
1410 signaling_thread(),
1411 new AudioRtpSender(track, stream->label(), session_.get(), stats_.get()));
deadbeefeb459812015-12-15 19:24:43 -08001412 senders_.push_back(new_sender);
1413 // If the sender has already been configured in SDP, we call SetSsrc,
1414 // which will connect the sender to the underlying transport. This can
1415 // occur if a local session description that contains the ID of the sender
1416 // is set before AddStream is called. It can also occur if the local
1417 // session description is not changed and RemoveStream is called, and
1418 // later AddStream is called again with the same stream.
1419 const TrackInfo* track_info =
1420 FindTrackInfo(local_audio_tracks_, stream->label(), track->id());
1421 if (track_info) {
1422 new_sender->SetSsrc(track_info->ssrc);
1423 }
1424}
1425
1426// TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around
1427// indefinitely, when we have unified plan SDP.
1428void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track,
1429 MediaStreamInterface* stream) {
1430 auto sender = FindSenderForTrack(track);
1431 if (sender == senders_.end()) {
1432 LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
1433 << " doesn't exist.";
1434 return;
1435 }
1436 (*sender)->Stop();
1437 senders_.erase(sender);
1438}
1439
1440void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track,
1441 MediaStreamInterface* stream) {
1442 auto sender = FindSenderForTrack(track);
1443 if (sender != senders_.end()) {
1444 // We already have a sender for this track, so just change the stream_id
1445 // so that it's correct in the next call to CreateOffer.
1446 (*sender)->set_stream_id(stream->label());
1447 return;
1448 }
1449
1450 // Normal case; we've never seen this track before.
deadbeefe1f9d832016-01-14 15:35:42 -08001451 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create(
1452 signaling_thread(),
1453 new VideoRtpSender(track, stream->label(), session_.get()));
deadbeefeb459812015-12-15 19:24:43 -08001454 senders_.push_back(new_sender);
1455 const TrackInfo* track_info =
1456 FindTrackInfo(local_video_tracks_, stream->label(), track->id());
1457 if (track_info) {
1458 new_sender->SetSsrc(track_info->ssrc);
1459 }
1460}
1461
1462void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track,
1463 MediaStreamInterface* stream) {
1464 auto sender = FindSenderForTrack(track);
1465 if (sender == senders_.end()) {
1466 LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
1467 << " doesn't exist.";
1468 return;
1469 }
1470 (*sender)->Stop();
1471 senders_.erase(sender);
1472}
1473
deadbeefab9b2d12015-10-14 11:33:11 -07001474void PeerConnection::PostSetSessionDescriptionFailure(
1475 SetSessionDescriptionObserver* observer,
1476 const std::string& error) {
1477 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
1478 msg->error = error;
1479 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_FAILED, msg);
1480}
1481
1482void PeerConnection::PostCreateSessionDescriptionFailure(
1483 CreateSessionDescriptionObserver* observer,
1484 const std::string& error) {
1485 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
1486 msg->error = error;
1487 signaling_thread()->Post(this, MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
1488}
1489
1490bool PeerConnection::GetOptionsForOffer(
1491 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
1492 cricket::MediaSessionOptions* session_options) {
deadbeef0ed85b22016-02-23 17:24:52 -08001493 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of
1494 // ContentInfos.
1495 if (session_->local_description()) {
1496 for (const cricket::ContentInfo& content :
1497 session_->local_description()->description()->contents()) {
1498 session_options->transport_options[content.name] =
1499 cricket::TransportOptions();
1500 }
1501 }
htaaac2dea2016-03-10 13:35:55 -08001502 if (!ExtractMediaSessionOptions(rtc_options, true, session_options)) {
deadbeefab9b2d12015-10-14 11:33:11 -07001503 return false;
1504 }
1505
deadbeeffac06552015-11-25 11:26:01 -08001506 AddSendStreams(session_options, senders_, rtp_data_channels_);
deadbeefc80741f2015-10-22 13:14:45 -07001507 // Offer to receive audio/video if the constraint is not set and there are
1508 // send streams, or we're currently receiving.
1509 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) {
1510 session_options->recv_audio =
1511 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) ||
1512 !remote_audio_tracks_.empty();
1513 }
1514 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) {
1515 session_options->recv_video =
1516 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) ||
1517 !remote_video_tracks_.empty();
1518 }
1519 session_options->bundle_enabled =
1520 session_options->bundle_enabled &&
1521 (session_options->has_audio() || session_options->has_video() ||
1522 session_options->has_data());
1523
deadbeefab9b2d12015-10-14 11:33:11 -07001524 if (session_->data_channel_type() == cricket::DCT_SCTP && HasDataChannels()) {
1525 session_options->data_channel_type = cricket::DCT_SCTP;
1526 }
zhihuang8f65cdf2016-05-06 18:40:30 -07001527
1528 session_options->rtcp_cname = rtcp_cname_;
deadbeefab9b2d12015-10-14 11:33:11 -07001529 return true;
1530}
1531
htaa2a49d92016-03-04 02:51:39 -08001532void PeerConnection::FinishOptionsForAnswer(
deadbeefab9b2d12015-10-14 11:33:11 -07001533 cricket::MediaSessionOptions* session_options) {
deadbeef0ed85b22016-02-23 17:24:52 -08001534 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of
1535 // ContentInfos.
1536 if (session_->remote_description()) {
1537 // Initialize the transport_options map.
1538 for (const cricket::ContentInfo& content :
1539 session_->remote_description()->description()->contents()) {
1540 session_options->transport_options[content.name] =
1541 cricket::TransportOptions();
1542 }
1543 }
deadbeeffac06552015-11-25 11:26:01 -08001544 AddSendStreams(session_options, senders_, rtp_data_channels_);
deadbeefc80741f2015-10-22 13:14:45 -07001545 session_options->bundle_enabled =
1546 session_options->bundle_enabled &&
1547 (session_options->has_audio() || session_options->has_video() ||
1548 session_options->has_data());
1549
deadbeefab9b2d12015-10-14 11:33:11 -07001550 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams
1551 // are not signaled in the SDP so does not go through that path and must be
1552 // handled here.
1553 if (session_->data_channel_type() == cricket::DCT_SCTP) {
1554 session_options->data_channel_type = cricket::DCT_SCTP;
1555 }
htaa2a49d92016-03-04 02:51:39 -08001556}
1557
1558bool PeerConnection::GetOptionsForAnswer(
1559 const MediaConstraintsInterface* constraints,
1560 cricket::MediaSessionOptions* session_options) {
1561 session_options->recv_audio = false;
1562 session_options->recv_video = false;
1563 if (!ParseConstraintsForAnswer(constraints, session_options)) {
1564 return false;
1565 }
zhihuang8f65cdf2016-05-06 18:40:30 -07001566 session_options->rtcp_cname = rtcp_cname_;
1567
htaa2a49d92016-03-04 02:51:39 -08001568 FinishOptionsForAnswer(session_options);
1569 return true;
1570}
1571
1572bool PeerConnection::GetOptionsForAnswer(
1573 const RTCOfferAnswerOptions& options,
1574 cricket::MediaSessionOptions* session_options) {
1575 session_options->recv_audio = false;
1576 session_options->recv_video = false;
htaaac2dea2016-03-10 13:35:55 -08001577 if (!ExtractMediaSessionOptions(options, false, session_options)) {
htaa2a49d92016-03-04 02:51:39 -08001578 return false;
1579 }
zhihuang8f65cdf2016-05-06 18:40:30 -07001580 session_options->rtcp_cname = rtcp_cname_;
1581
htaa2a49d92016-03-04 02:51:39 -08001582 FinishOptionsForAnswer(session_options);
deadbeefab9b2d12015-10-14 11:33:11 -07001583 return true;
1584}
1585
deadbeeffaac4972015-11-12 15:33:07 -08001586void PeerConnection::RemoveTracks(cricket::MediaType media_type) {
1587 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type);
deadbeefbda7e0b2015-12-08 17:13:40 -08001588 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false,
1589 media_type, nullptr);
deadbeeffaac4972015-11-12 15:33:07 -08001590}
1591
deadbeefab9b2d12015-10-14 11:33:11 -07001592void PeerConnection::UpdateRemoteStreamsList(
1593 const cricket::StreamParamsVec& streams,
deadbeefbda7e0b2015-12-08 17:13:40 -08001594 bool default_track_needed,
deadbeefab9b2d12015-10-14 11:33:11 -07001595 cricket::MediaType media_type,
1596 StreamCollection* new_streams) {
1597 TrackInfos* current_tracks = GetRemoteTracks(media_type);
1598
1599 // Find removed tracks. I.e., tracks where the track id or ssrc don't match
deadbeeffac06552015-11-25 11:26:01 -08001600 // the new StreamParam.
deadbeefab9b2d12015-10-14 11:33:11 -07001601 auto track_it = current_tracks->begin();
1602 while (track_it != current_tracks->end()) {
1603 const TrackInfo& info = *track_it;
1604 const cricket::StreamParams* params =
1605 cricket::GetStreamBySsrc(streams, info.ssrc);
deadbeefbda7e0b2015-12-08 17:13:40 -08001606 bool track_exists = params && params->id == info.track_id;
1607 // If this is a default track, and we still need it, don't remove it.
1608 if ((info.stream_label == kDefaultStreamLabel && default_track_needed) ||
1609 track_exists) {
1610 ++track_it;
1611 } else {
deadbeefab9b2d12015-10-14 11:33:11 -07001612 OnRemoteTrackRemoved(info.stream_label, info.track_id, media_type);
1613 track_it = current_tracks->erase(track_it);
deadbeefab9b2d12015-10-14 11:33:11 -07001614 }
1615 }
1616
1617 // Find new and active tracks.
1618 for (const cricket::StreamParams& params : streams) {
1619 // The sync_label is the MediaStream label and the |stream.id| is the
1620 // track id.
1621 const std::string& stream_label = params.sync_label;
1622 const std::string& track_id = params.id;
1623 uint32_t ssrc = params.first_ssrc();
1624
1625 rtc::scoped_refptr<MediaStreamInterface> stream =
1626 remote_streams_->find(stream_label);
1627 if (!stream) {
1628 // This is a new MediaStream. Create a new remote MediaStream.
perkjd61bf802016-03-24 03:16:19 -07001629 stream = MediaStreamProxy::Create(rtc::Thread::Current(),
1630 MediaStream::Create(stream_label));
deadbeefab9b2d12015-10-14 11:33:11 -07001631 remote_streams_->AddStream(stream);
1632 new_streams->AddStream(stream);
1633 }
1634
1635 const TrackInfo* track_info =
1636 FindTrackInfo(*current_tracks, stream_label, track_id);
1637 if (!track_info) {
1638 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc));
1639 OnRemoteTrackSeen(stream_label, track_id, ssrc, media_type);
1640 }
1641 }
deadbeefbda7e0b2015-12-08 17:13:40 -08001642
1643 // Add default track if necessary.
1644 if (default_track_needed) {
1645 rtc::scoped_refptr<MediaStreamInterface> default_stream =
1646 remote_streams_->find(kDefaultStreamLabel);
1647 if (!default_stream) {
1648 // Create the new default MediaStream.
perkjd61bf802016-03-24 03:16:19 -07001649 default_stream = MediaStreamProxy::Create(
1650 rtc::Thread::Current(), MediaStream::Create(kDefaultStreamLabel));
deadbeefbda7e0b2015-12-08 17:13:40 -08001651 remote_streams_->AddStream(default_stream);
1652 new_streams->AddStream(default_stream);
1653 }
1654 std::string default_track_id = (media_type == cricket::MEDIA_TYPE_AUDIO)
1655 ? kDefaultAudioTrackLabel
1656 : kDefaultVideoTrackLabel;
1657 const TrackInfo* default_track_info =
1658 FindTrackInfo(*current_tracks, kDefaultStreamLabel, default_track_id);
1659 if (!default_track_info) {
1660 current_tracks->push_back(
1661 TrackInfo(kDefaultStreamLabel, default_track_id, 0));
1662 OnRemoteTrackSeen(kDefaultStreamLabel, default_track_id, 0, media_type);
1663 }
1664 }
deadbeefab9b2d12015-10-14 11:33:11 -07001665}
1666
1667void PeerConnection::OnRemoteTrackSeen(const std::string& stream_label,
1668 const std::string& track_id,
1669 uint32_t ssrc,
1670 cricket::MediaType media_type) {
1671 MediaStreamInterface* stream = remote_streams_->find(stream_label);
1672
1673 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
perkjd61bf802016-03-24 03:16:19 -07001674 CreateAudioReceiver(stream, track_id, ssrc);
deadbeefab9b2d12015-10-14 11:33:11 -07001675 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
perkjf0dcfe22016-03-10 18:32:00 +01001676 CreateVideoReceiver(stream, track_id, ssrc);
deadbeefab9b2d12015-10-14 11:33:11 -07001677 } else {
1678 RTC_DCHECK(false && "Invalid media type");
1679 }
1680}
1681
1682void PeerConnection::OnRemoteTrackRemoved(const std::string& stream_label,
1683 const std::string& track_id,
1684 cricket::MediaType media_type) {
1685 MediaStreamInterface* stream = remote_streams_->find(stream_label);
1686
1687 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
perkjd61bf802016-03-24 03:16:19 -07001688 // When the MediaEngine audio channel is destroyed, the RemoteAudioSource
1689 // will be notified which will end the AudioRtpReceiver::track().
1690 DestroyReceiver(track_id);
deadbeefab9b2d12015-10-14 11:33:11 -07001691 rtc::scoped_refptr<AudioTrackInterface> audio_track =
1692 stream->FindAudioTrack(track_id);
1693 if (audio_track) {
deadbeefab9b2d12015-10-14 11:33:11 -07001694 stream->RemoveTrack(audio_track);
deadbeefab9b2d12015-10-14 11:33:11 -07001695 }
1696 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
perkjd61bf802016-03-24 03:16:19 -07001697 // Stopping or destroying a VideoRtpReceiver will end the
1698 // VideoRtpReceiver::track().
1699 DestroyReceiver(track_id);
deadbeefab9b2d12015-10-14 11:33:11 -07001700 rtc::scoped_refptr<VideoTrackInterface> video_track =
1701 stream->FindVideoTrack(track_id);
1702 if (video_track) {
perkjd61bf802016-03-24 03:16:19 -07001703 // There's no guarantee the track is still available, e.g. the track may
1704 // have been removed from the stream by an application.
deadbeefab9b2d12015-10-14 11:33:11 -07001705 stream->RemoveTrack(video_track);
deadbeefab9b2d12015-10-14 11:33:11 -07001706 }
1707 } else {
1708 ASSERT(false && "Invalid media type");
1709 }
1710}
1711
1712void PeerConnection::UpdateEndedRemoteMediaStreams() {
1713 std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_to_remove;
1714 for (size_t i = 0; i < remote_streams_->count(); ++i) {
1715 MediaStreamInterface* stream = remote_streams_->at(i);
1716 if (stream->GetAudioTracks().empty() && stream->GetVideoTracks().empty()) {
1717 streams_to_remove.push_back(stream);
1718 }
1719 }
1720
Taylor Brandstetter98cde262016-05-31 13:02:21 -07001721 for (auto& stream : streams_to_remove) {
deadbeefab9b2d12015-10-14 11:33:11 -07001722 remote_streams_->RemoveStream(stream);
Taylor Brandstetter98cde262016-05-31 13:02:21 -07001723 // Call both the raw pointer and scoped_refptr versions of the method
1724 // for compatibility.
1725 observer_->OnRemoveStream(stream.get());
1726 observer_->OnRemoveStream(std::move(stream));
deadbeefab9b2d12015-10-14 11:33:11 -07001727 }
1728}
1729
deadbeefab9b2d12015-10-14 11:33:11 -07001730void PeerConnection::UpdateLocalTracks(
1731 const std::vector<cricket::StreamParams>& streams,
1732 cricket::MediaType media_type) {
1733 TrackInfos* current_tracks = GetLocalTracks(media_type);
1734
1735 // Find removed tracks. I.e., tracks where the track id, stream label or ssrc
1736 // don't match the new StreamParam.
1737 TrackInfos::iterator track_it = current_tracks->begin();
1738 while (track_it != current_tracks->end()) {
1739 const TrackInfo& info = *track_it;
1740 const cricket::StreamParams* params =
1741 cricket::GetStreamBySsrc(streams, info.ssrc);
1742 if (!params || params->id != info.track_id ||
1743 params->sync_label != info.stream_label) {
1744 OnLocalTrackRemoved(info.stream_label, info.track_id, info.ssrc,
1745 media_type);
1746 track_it = current_tracks->erase(track_it);
1747 } else {
1748 ++track_it;
1749 }
1750 }
1751
1752 // Find new and active tracks.
1753 for (const cricket::StreamParams& params : streams) {
1754 // The sync_label is the MediaStream label and the |stream.id| is the
1755 // track id.
1756 const std::string& stream_label = params.sync_label;
1757 const std::string& track_id = params.id;
1758 uint32_t ssrc = params.first_ssrc();
1759 const TrackInfo* track_info =
1760 FindTrackInfo(*current_tracks, stream_label, track_id);
1761 if (!track_info) {
1762 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc));
1763 OnLocalTrackSeen(stream_label, track_id, params.first_ssrc(), media_type);
1764 }
1765 }
1766}
1767
1768void PeerConnection::OnLocalTrackSeen(const std::string& stream_label,
1769 const std::string& track_id,
1770 uint32_t ssrc,
1771 cricket::MediaType media_type) {
deadbeeffac06552015-11-25 11:26:01 -08001772 RtpSenderInterface* sender = FindSenderById(track_id);
1773 if (!sender) {
1774 LOG(LS_WARNING) << "An unknown RtpSender with id " << track_id
1775 << " has been configured in the local description.";
deadbeefab9b2d12015-10-14 11:33:11 -07001776 return;
1777 }
1778
deadbeeffac06552015-11-25 11:26:01 -08001779 if (sender->media_type() != media_type) {
1780 LOG(LS_WARNING) << "An RtpSender has been configured in the local"
1781 << " description with an unexpected media type.";
1782 return;
deadbeefab9b2d12015-10-14 11:33:11 -07001783 }
deadbeeffac06552015-11-25 11:26:01 -08001784
1785 sender->set_stream_id(stream_label);
1786 sender->SetSsrc(ssrc);
deadbeefab9b2d12015-10-14 11:33:11 -07001787}
1788
1789void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label,
1790 const std::string& track_id,
1791 uint32_t ssrc,
1792 cricket::MediaType media_type) {
deadbeeffac06552015-11-25 11:26:01 -08001793 RtpSenderInterface* sender = FindSenderById(track_id);
1794 if (!sender) {
1795 // This is the normal case. I.e., RemoveStream has been called and the
deadbeefab9b2d12015-10-14 11:33:11 -07001796 // SessionDescriptions has been renegotiated.
1797 return;
1798 }
deadbeeffac06552015-11-25 11:26:01 -08001799
1800 // A sender has been removed from the SessionDescription but it's still
1801 // associated with the PeerConnection. This only occurs if the SDP doesn't
1802 // match with the calls to CreateSender, AddStream and RemoveStream.
1803 if (sender->media_type() != media_type) {
1804 LOG(LS_WARNING) << "An RtpSender has been configured in the local"
1805 << " description with an unexpected media type.";
1806 return;
deadbeefab9b2d12015-10-14 11:33:11 -07001807 }
deadbeeffac06552015-11-25 11:26:01 -08001808
1809 sender->SetSsrc(0);
deadbeefab9b2d12015-10-14 11:33:11 -07001810}
1811
1812void PeerConnection::UpdateLocalRtpDataChannels(
1813 const cricket::StreamParamsVec& streams) {
1814 std::vector<std::string> existing_channels;
1815
1816 // Find new and active data channels.
1817 for (const cricket::StreamParams& params : streams) {
1818 // |it->sync_label| is actually the data channel label. The reason is that
1819 // we use the same naming of data channels as we do for
1820 // MediaStreams and Tracks.
1821 // For MediaStreams, the sync_label is the MediaStream label and the
1822 // track label is the same as |streamid|.
1823 const std::string& channel_label = params.sync_label;
1824 auto data_channel_it = rtp_data_channels_.find(channel_label);
1825 if (!VERIFY(data_channel_it != rtp_data_channels_.end())) {
1826 continue;
1827 }
1828 // Set the SSRC the data channel should use for sending.
1829 data_channel_it->second->SetSendSsrc(params.first_ssrc());
1830 existing_channels.push_back(data_channel_it->first);
1831 }
1832
1833 UpdateClosingRtpDataChannels(existing_channels, true);
1834}
1835
1836void PeerConnection::UpdateRemoteRtpDataChannels(
1837 const cricket::StreamParamsVec& streams) {
1838 std::vector<std::string> existing_channels;
1839
1840 // Find new and active data channels.
1841 for (const cricket::StreamParams& params : streams) {
1842 // The data channel label is either the mslabel or the SSRC if the mslabel
1843 // does not exist. Ex a=ssrc:444330170 mslabel:test1.
1844 std::string label = params.sync_label.empty()
1845 ? rtc::ToString(params.first_ssrc())
1846 : params.sync_label;
1847 auto data_channel_it = rtp_data_channels_.find(label);
1848 if (data_channel_it == rtp_data_channels_.end()) {
1849 // This is a new data channel.
1850 CreateRemoteRtpDataChannel(label, params.first_ssrc());
1851 } else {
1852 data_channel_it->second->SetReceiveSsrc(params.first_ssrc());
1853 }
1854 existing_channels.push_back(label);
1855 }
1856
1857 UpdateClosingRtpDataChannels(existing_channels, false);
1858}
1859
1860void PeerConnection::UpdateClosingRtpDataChannels(
1861 const std::vector<std::string>& active_channels,
1862 bool is_local_update) {
1863 auto it = rtp_data_channels_.begin();
1864 while (it != rtp_data_channels_.end()) {
1865 DataChannel* data_channel = it->second;
1866 if (std::find(active_channels.begin(), active_channels.end(),
1867 data_channel->label()) != active_channels.end()) {
1868 ++it;
1869 continue;
1870 }
1871
1872 if (is_local_update) {
1873 data_channel->SetSendSsrc(0);
1874 } else {
1875 data_channel->RemotePeerRequestClose();
1876 }
1877
1878 if (data_channel->state() == DataChannel::kClosed) {
1879 rtp_data_channels_.erase(it);
1880 it = rtp_data_channels_.begin();
1881 } else {
1882 ++it;
1883 }
1884 }
1885}
1886
1887void PeerConnection::CreateRemoteRtpDataChannel(const std::string& label,
1888 uint32_t remote_ssrc) {
1889 rtc::scoped_refptr<DataChannel> channel(
1890 InternalCreateDataChannel(label, nullptr));
1891 if (!channel.get()) {
1892 LOG(LS_WARNING) << "Remote peer requested a DataChannel but"
1893 << "CreateDataChannel failed.";
1894 return;
1895 }
1896 channel->SetReceiveSsrc(remote_ssrc);
Taylor Brandstetter98cde262016-05-31 13:02:21 -07001897 auto proxy_channel = DataChannelProxy::Create(signaling_thread(), channel);
1898 // Call both the raw pointer and scoped_refptr versions of the method
1899 // for compatibility.
1900 observer_->OnDataChannel(proxy_channel.get());
1901 observer_->OnDataChannel(std::move(proxy_channel));
deadbeefab9b2d12015-10-14 11:33:11 -07001902}
1903
1904rtc::scoped_refptr<DataChannel> PeerConnection::InternalCreateDataChannel(
1905 const std::string& label,
1906 const InternalDataChannelInit* config) {
1907 if (IsClosed()) {
1908 return nullptr;
1909 }
1910 if (session_->data_channel_type() == cricket::DCT_NONE) {
1911 LOG(LS_ERROR)
1912 << "InternalCreateDataChannel: Data is not supported in this call.";
1913 return nullptr;
1914 }
1915 InternalDataChannelInit new_config =
1916 config ? (*config) : InternalDataChannelInit();
1917 if (session_->data_channel_type() == cricket::DCT_SCTP) {
1918 if (new_config.id < 0) {
1919 rtc::SSLRole role;
Taylor Brandstetterf475d362016-01-08 15:35:57 -08001920 if ((session_->GetSslRole(session_->data_channel(), &role)) &&
deadbeefab9b2d12015-10-14 11:33:11 -07001921 !sid_allocator_.AllocateSid(role, &new_config.id)) {
1922 LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
1923 return nullptr;
1924 }
1925 } else if (!sid_allocator_.ReserveSid(new_config.id)) {
1926 LOG(LS_ERROR) << "Failed to create a SCTP data channel "
1927 << "because the id is already in use or out of range.";
1928 return nullptr;
1929 }
1930 }
1931
1932 rtc::scoped_refptr<DataChannel> channel(DataChannel::Create(
1933 session_.get(), session_->data_channel_type(), label, new_config));
1934 if (!channel) {
1935 sid_allocator_.ReleaseSid(new_config.id);
1936 return nullptr;
1937 }
1938
1939 if (channel->data_channel_type() == cricket::DCT_RTP) {
1940 if (rtp_data_channels_.find(channel->label()) != rtp_data_channels_.end()) {
1941 LOG(LS_ERROR) << "DataChannel with label " << channel->label()
1942 << " already exists.";
1943 return nullptr;
1944 }
1945 rtp_data_channels_[channel->label()] = channel;
1946 } else {
1947 RTC_DCHECK(channel->data_channel_type() == cricket::DCT_SCTP);
1948 sctp_data_channels_.push_back(channel);
1949 channel->SignalClosed.connect(this,
1950 &PeerConnection::OnSctpDataChannelClosed);
1951 }
1952
1953 return channel;
1954}
1955
1956bool PeerConnection::HasDataChannels() const {
1957 return !rtp_data_channels_.empty() || !sctp_data_channels_.empty();
1958}
1959
1960void PeerConnection::AllocateSctpSids(rtc::SSLRole role) {
1961 for (const auto& channel : sctp_data_channels_) {
1962 if (channel->id() < 0) {
1963 int sid;
1964 if (!sid_allocator_.AllocateSid(role, &sid)) {
1965 LOG(LS_ERROR) << "Failed to allocate SCTP sid.";
1966 continue;
1967 }
1968 channel->SetSctpSid(sid);
1969 }
1970 }
1971}
1972
1973void PeerConnection::OnSctpDataChannelClosed(DataChannel* channel) {
deadbeefbd292462015-12-14 18:15:29 -08001974 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeefab9b2d12015-10-14 11:33:11 -07001975 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end();
1976 ++it) {
1977 if (it->get() == channel) {
1978 if (channel->id() >= 0) {
1979 sid_allocator_.ReleaseSid(channel->id());
1980 }
deadbeefbd292462015-12-14 18:15:29 -08001981 // Since this method is triggered by a signal from the DataChannel,
1982 // we can't free it directly here; we need to free it asynchronously.
1983 sctp_data_channels_to_free_.push_back(*it);
deadbeefab9b2d12015-10-14 11:33:11 -07001984 sctp_data_channels_.erase(it);
deadbeefbd292462015-12-14 18:15:29 -08001985 signaling_thread()->Post(this, MSG_FREE_DATACHANNELS, nullptr);
deadbeefab9b2d12015-10-14 11:33:11 -07001986 return;
1987 }
1988 }
1989}
1990
1991void PeerConnection::OnVoiceChannelDestroyed() {
perkjd61bf802016-03-24 03:16:19 -07001992 StopReceivers(cricket::MEDIA_TYPE_AUDIO);
deadbeefab9b2d12015-10-14 11:33:11 -07001993}
1994
1995void PeerConnection::OnVideoChannelDestroyed() {
perkjd61bf802016-03-24 03:16:19 -07001996 StopReceivers(cricket::MEDIA_TYPE_VIDEO);
deadbeefab9b2d12015-10-14 11:33:11 -07001997}
1998
1999void PeerConnection::OnDataChannelCreated() {
2000 for (const auto& channel : sctp_data_channels_) {
2001 channel->OnTransportChannelCreated();
2002 }
2003}
2004
2005void PeerConnection::OnDataChannelDestroyed() {
2006 // Use a temporary copy of the RTP/SCTP DataChannel list because the
2007 // DataChannel may callback to us and try to modify the list.
2008 std::map<std::string, rtc::scoped_refptr<DataChannel>> temp_rtp_dcs;
2009 temp_rtp_dcs.swap(rtp_data_channels_);
2010 for (const auto& kv : temp_rtp_dcs) {
2011 kv.second->OnTransportChannelDestroyed();
2012 }
2013
2014 std::vector<rtc::scoped_refptr<DataChannel>> temp_sctp_dcs;
2015 temp_sctp_dcs.swap(sctp_data_channels_);
2016 for (const auto& channel : temp_sctp_dcs) {
2017 channel->OnTransportChannelDestroyed();
2018 }
2019}
2020
2021void PeerConnection::OnDataChannelOpenMessage(
2022 const std::string& label,
2023 const InternalDataChannelInit& config) {
2024 rtc::scoped_refptr<DataChannel> channel(
2025 InternalCreateDataChannel(label, &config));
2026 if (!channel.get()) {
2027 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
2028 return;
2029 }
2030
Taylor Brandstetter98cde262016-05-31 13:02:21 -07002031 auto proxy_channel = DataChannelProxy::Create(signaling_thread(), channel);
2032 // Call both the raw pointer and scoped_refptr versions of the method
2033 // for compatibility.
2034 observer_->OnDataChannel(proxy_channel.get());
2035 observer_->OnDataChannel(std::move(proxy_channel));
deadbeefab9b2d12015-10-14 11:33:11 -07002036}
2037
deadbeeffac06552015-11-25 11:26:01 -08002038RtpSenderInterface* PeerConnection::FindSenderById(const std::string& id) {
2039 auto it =
2040 std::find_if(senders_.begin(), senders_.end(),
2041 [id](const rtc::scoped_refptr<RtpSenderInterface>& sender) {
2042 return sender->id() == id;
2043 });
2044 return it != senders_.end() ? it->get() : nullptr;
2045}
2046
deadbeef70ab1a12015-09-28 16:53:55 -07002047std::vector<rtc::scoped_refptr<RtpSenderInterface>>::iterator
2048PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) {
2049 return std::find_if(
2050 senders_.begin(), senders_.end(),
2051 [track](const rtc::scoped_refptr<RtpSenderInterface>& sender) {
2052 return sender->track() == track;
2053 });
2054}
2055
2056std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator
perkjd61bf802016-03-24 03:16:19 -07002057PeerConnection::FindReceiverForTrack(const std::string& track_id) {
deadbeef70ab1a12015-09-28 16:53:55 -07002058 return std::find_if(
2059 receivers_.begin(), receivers_.end(),
perkjd61bf802016-03-24 03:16:19 -07002060 [track_id](const rtc::scoped_refptr<RtpReceiverInterface>& receiver) {
2061 return receiver->id() == track_id;
deadbeef70ab1a12015-09-28 16:53:55 -07002062 });
2063}
2064
deadbeefab9b2d12015-10-14 11:33:11 -07002065PeerConnection::TrackInfos* PeerConnection::GetRemoteTracks(
2066 cricket::MediaType media_type) {
2067 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
2068 media_type == cricket::MEDIA_TYPE_VIDEO);
2069 return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &remote_audio_tracks_
2070 : &remote_video_tracks_;
2071}
2072
2073PeerConnection::TrackInfos* PeerConnection::GetLocalTracks(
2074 cricket::MediaType media_type) {
2075 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
2076 media_type == cricket::MEDIA_TYPE_VIDEO);
2077 return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &local_audio_tracks_
2078 : &local_video_tracks_;
2079}
2080
2081const PeerConnection::TrackInfo* PeerConnection::FindTrackInfo(
2082 const PeerConnection::TrackInfos& infos,
2083 const std::string& stream_label,
2084 const std::string track_id) const {
2085 for (const TrackInfo& track_info : infos) {
2086 if (track_info.stream_label == stream_label &&
2087 track_info.track_id == track_id) {
2088 return &track_info;
2089 }
2090 }
2091 return nullptr;
2092}
2093
2094DataChannel* PeerConnection::FindDataChannelBySid(int sid) const {
2095 for (const auto& channel : sctp_data_channels_) {
2096 if (channel->id() == sid) {
2097 return channel;
2098 }
2099 }
2100 return nullptr;
2101}
2102
deadbeef91dd5672016-05-18 16:55:30 -07002103bool PeerConnection::InitializePortAllocator_n(
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002104 const RTCConfiguration& configuration) {
2105 cricket::ServerAddresses stun_servers;
2106 std::vector<cricket::RelayServerConfig> turn_servers;
2107 if (!ParseIceServers(configuration.servers, &stun_servers, &turn_servers)) {
2108 return false;
2109 }
2110
2111 // To handle both internal and externally created port allocator, we will
2112 // enable BUNDLE here.
2113 int portallocator_flags = port_allocator_->flags();
2114 portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET |
2115 cricket::PORTALLOCATOR_ENABLE_IPV6;
2116 // If the disable-IPv6 flag was specified, we'll not override it
2117 // by experiment.
2118 if (configuration.disable_ipv6) {
2119 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
2120 } else if (webrtc::field_trial::FindFullName("WebRTC-IPv6Default") ==
2121 "Disabled") {
2122 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
2123 }
2124
2125 if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) {
2126 portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP;
2127 LOG(LS_INFO) << "TCP candidates are disabled.";
2128 }
2129
honghaiz60347052016-05-31 18:29:12 -07002130 if (configuration.candidate_network_policy ==
2131 kCandidateNetworkPolicyLowCost) {
2132 portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_COSTLY_NETWORKS;
2133 LOG(LS_INFO) << "Do not gather candidates on high-cost networks";
2134 }
2135
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002136 port_allocator_->set_flags(portallocator_flags);
2137 // No step delay is used while allocating ports.
2138 port_allocator_->set_step_delay(cricket::kMinimumStepDelay);
2139 port_allocator_->set_candidate_filter(
2140 ConvertIceTransportTypeToCandidateFilter(configuration.type));
2141
2142 // Call this last since it may create pooled allocator sessions using the
2143 // properties set above.
2144 port_allocator_->SetConfiguration(stun_servers, turn_servers,
2145 configuration.ice_candidate_pool_size);
2146 return true;
2147}
2148
deadbeef91dd5672016-05-18 16:55:30 -07002149bool PeerConnection::ReconfigurePortAllocator_n(
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002150 const RTCConfiguration& configuration) {
2151 cricket::ServerAddresses stun_servers;
2152 std::vector<cricket::RelayServerConfig> turn_servers;
2153 if (!ParseIceServers(configuration.servers, &stun_servers, &turn_servers)) {
2154 return false;
2155 }
2156 port_allocator_->set_candidate_filter(
2157 ConvertIceTransportTypeToCandidateFilter(configuration.type));
2158 // Call this last since it may create pooled allocator sessions using the
2159 // candidate filter set above.
2160 port_allocator_->SetConfiguration(stun_servers, turn_servers,
2161 configuration.ice_candidate_pool_size);
2162 return true;
2163}
2164
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002165} // namespace webrtc