Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Side by Side Diff: talk/app/webrtc/peerconnection.cc

Issue 1344143002: Catching more errors when parsing ICE server URLs. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Merging with master. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « talk/app/webrtc/peerconnection.h ('k') | talk/app/webrtc/peerconnection_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2012 Google Inc. 3 * Copyright 2012 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 10 matching lines...) Expand all
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28 #include "talk/app/webrtc/peerconnection.h" 28 #include "talk/app/webrtc/peerconnection.h"
29 29
30 #include <vector> 30 #include <vector>
31 #include <cctype> // for isdigit
31 32
32 #include "talk/app/webrtc/dtmfsender.h" 33 #include "talk/app/webrtc/dtmfsender.h"
33 #include "talk/app/webrtc/jsepicecandidate.h" 34 #include "talk/app/webrtc/jsepicecandidate.h"
34 #include "talk/app/webrtc/jsepsessiondescription.h" 35 #include "talk/app/webrtc/jsepsessiondescription.h"
35 #include "talk/app/webrtc/mediaconstraintsinterface.h" 36 #include "talk/app/webrtc/mediaconstraintsinterface.h"
36 #include "talk/app/webrtc/rtpreceiver.h" 37 #include "talk/app/webrtc/rtpreceiver.h"
37 #include "talk/app/webrtc/rtpsender.h" 38 #include "talk/app/webrtc/rtpsender.h"
38 #include "talk/app/webrtc/streamcollection.h" 39 #include "talk/app/webrtc/streamcollection.h"
39 #include "webrtc/p2p/client/basicportallocator.h" 40 #include "webrtc/p2p/client/basicportallocator.h"
40 #include "talk/session/media/channelmanager.h" 41 #include "talk/session/media/channelmanager.h"
41 #include "webrtc/base/logging.h" 42 #include "webrtc/base/logging.h"
42 #include "webrtc/base/stringencode.h" 43 #include "webrtc/base/stringencode.h"
43 #include "webrtc/system_wrappers/interface/field_trial.h" 44 #include "webrtc/system_wrappers/interface/field_trial.h"
44 45
45 namespace { 46 namespace {
46 47
47 using webrtc::PeerConnectionInterface; 48 using webrtc::PeerConnectionInterface;
49 using webrtc::StunConfigurations;
50 using webrtc::TurnConfigurations;
51 typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration
52 StunConfiguration;
53 typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration
54 TurnConfiguration;
48 55
49 // The min number of tokens must present in Turn host uri. 56 // The min number of tokens must present in Turn host uri.
50 // e.g. user@turn.example.org 57 // e.g. user@turn.example.org
51 static const size_t kTurnHostTokensNum = 2; 58 static const size_t kTurnHostTokensNum = 2;
52 // Number of tokens must be preset when TURN uri has transport param. 59 // Number of tokens must be preset when TURN uri has transport param.
53 static const size_t kTurnTransportTokensNum = 2; 60 static const size_t kTurnTransportTokensNum = 2;
54 // The default stun port. 61 // The default stun port.
55 static const int kDefaultStunPort = 3478; 62 static const int kDefaultStunPort = 3478;
56 static const int kDefaultStunTlsPort = 5349; 63 static const int kDefaultStunTlsPort = 5349;
57 static const char kTransport[] = "transport"; 64 static const char kTransport[] = "transport";
58 static const char kUdpTransportType[] = "udp"; 65 static const char kUdpTransportType[] = "udp";
59 static const char kTcpTransportType[] = "tcp"; 66 static const char kTcpTransportType[] = "tcp";
60 67
61 // NOTE: Must be in the same order as the ServiceType enum. 68 // NOTE: Must be in the same order as the ServiceType enum.
62 static const char* kValidIceServiceTypes[] = { 69 static const char* kValidIceServiceTypes[] = {"stun", "stuns", "turn", "turns"};
63 "stun", "stuns", "turn", "turns", "invalid" };
64 70
71 // NOTE: A loop below assumes that the first value of this enum is 0 and all
72 // other values are incremental.
65 enum ServiceType { 73 enum ServiceType {
66 STUN, // Indicates a STUN server. 74 STUN = 0, // Indicates a STUN server.
67 STUNS, // Indicates a STUN server used with a TLS session. 75 STUNS, // Indicates a STUN server used with a TLS session.
68 TURN, // Indicates a TURN server 76 TURN, // Indicates a TURN server
69 TURNS, // Indicates a TURN server used with a TLS session. 77 TURNS, // Indicates a TURN server used with a TLS session.
70 INVALID, // Unknown. 78 INVALID, // Unknown.
71 }; 79 };
80 static_assert(INVALID == ARRAY_SIZE(kValidIceServiceTypes),
81 "kValidIceServiceTypes must have as many strings as ServiceType "
82 "has values.");
72 83
73 enum { 84 enum {
74 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0, 85 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0,
75 MSG_SET_SESSIONDESCRIPTION_FAILED, 86 MSG_SET_SESSIONDESCRIPTION_FAILED,
76 MSG_GETSTATS, 87 MSG_GETSTATS,
77 }; 88 };
78 89
79 struct SetSessionDescriptionMsg : public rtc::MessageData { 90 struct SetSessionDescriptionMsg : public rtc::MessageData {
80 explicit SetSessionDescriptionMsg( 91 explicit SetSessionDescriptionMsg(
81 webrtc::SetSessionDescriptionObserver* observer) 92 webrtc::SetSessionDescriptionObserver* observer)
(...skipping 11 matching lines...) Expand all
93 } 104 }
94 rtc::scoped_refptr<webrtc::StatsObserver> observer; 105 rtc::scoped_refptr<webrtc::StatsObserver> observer;
95 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track; 106 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track;
96 }; 107 };
97 108
98 // |in_str| should be of format 109 // |in_str| should be of format
99 // stunURI = scheme ":" stun-host [ ":" stun-port ] 110 // stunURI = scheme ":" stun-host [ ":" stun-port ]
100 // scheme = "stun" / "stuns" 111 // scheme = "stun" / "stuns"
101 // stun-host = IP-literal / IPv4address / reg-name 112 // stun-host = IP-literal / IPv4address / reg-name
102 // stun-port = *DIGIT 113 // stun-port = *DIGIT
103 114 //
104 // draft-petithuguenin-behave-turn-uris-01 115 // draft-petithuguenin-behave-turn-uris-01
105 // turnURI = scheme ":" turn-host [ ":" turn-port ] 116 // turnURI = scheme ":" turn-host [ ":" turn-port ]
106 // turn-host = username@IP-literal / IPv4address / reg-name 117 // turn-host = username@IP-literal / IPv4address / reg-name
107 bool GetServiceTypeAndHostnameFromUri(const std::string& in_str, 118 bool GetServiceTypeAndHostnameFromUri(const std::string& in_str,
108 ServiceType* service_type, 119 ServiceType* service_type,
109 std::string* hostname) { 120 std::string* hostname) {
110 const std::string::size_type colonpos = in_str.find(':'); 121 const std::string::size_type colonpos = in_str.find(':');
111 if (colonpos == std::string::npos || (colonpos + 1) == in_str.length()) { 122 if (colonpos == std::string::npos) {
123 LOG(LS_WARNING) << "Missing ':' in ICE URI: " << in_str;
112 return false; 124 return false;
113 } 125 }
114 std::string type = in_str.substr(0, colonpos); 126 if ((colonpos + 1) == in_str.length()) {
127 LOG(LS_WARNING) << "Empty hostname in ICE URI: " << in_str;
128 return false;
129 }
130 *service_type = INVALID;
115 for (size_t i = 0; i < ARRAY_SIZE(kValidIceServiceTypes); ++i) { 131 for (size_t i = 0; i < ARRAY_SIZE(kValidIceServiceTypes); ++i) {
116 if (type.compare(kValidIceServiceTypes[i]) == 0) { 132 if (in_str.compare(0, colonpos, kValidIceServiceTypes[i]) == 0) {
117 *service_type = static_cast<ServiceType>(i); 133 *service_type = static_cast<ServiceType>(i);
118 break; 134 break;
119 } 135 }
120 } 136 }
121 if (*service_type == INVALID) { 137 if (*service_type == INVALID) {
122 return false; 138 return false;
123 } 139 }
124 *hostname = in_str.substr(colonpos + 1, std::string::npos); 140 *hostname = in_str.substr(colonpos + 1, std::string::npos);
125 return true; 141 return true;
126 } 142 }
127 143
144 bool ParsePort(const std::string& in_str, int* port) {
145 // Make sure port only contains digits. FromString doesn't check this.
146 for (const char& c : in_str) {
147 if (!std::isdigit(c)) {
148 return false;
149 }
150 }
151 return rtc::FromString(in_str, port);
152 }
153
128 // This method parses IPv6 and IPv4 literal strings, along with hostnames in 154 // This method parses IPv6 and IPv4 literal strings, along with hostnames in
129 // standard hostname:port format. 155 // standard hostname:port format.
130 // Consider following formats as correct. 156 // Consider following formats as correct.
131 // |hostname:port|, |[IPV6 address]:port|, |IPv4 address|:port, 157 // |hostname:port|, |[IPV6 address]:port|, |IPv4 address|:port,
132 // |hostname|, |[IPv6 address]|, |IPv4 address| 158 // |hostname|, |[IPv6 address]|, |IPv4 address|.
133 bool ParseHostnameAndPortFromString(const std::string& in_str, 159 bool ParseHostnameAndPortFromString(const std::string& in_str,
134 std::string* host, 160 std::string* host,
135 int* port) { 161 int* port) {
162 RTC_DCHECK(host->empty());
136 if (in_str.at(0) == '[') { 163 if (in_str.at(0) == '[') {
137 std::string::size_type closebracket = in_str.rfind(']'); 164 std::string::size_type closebracket = in_str.rfind(']');
138 if (closebracket != std::string::npos) { 165 if (closebracket != std::string::npos) {
139 *host = in_str.substr(1, closebracket - 1);
140 std::string::size_type colonpos = in_str.find(':', closebracket); 166 std::string::size_type colonpos = in_str.find(':', closebracket);
141 if (std::string::npos != colonpos) { 167 if (std::string::npos != colonpos) {
142 if (!rtc::FromString( 168 if (!ParsePort(in_str.substr(closebracket + 2, std::string::npos),
143 in_str.substr(closebracket + 2, std::string::npos), port)) { 169 port)) {
144 return false; 170 return false;
145 } 171 }
146 } 172 }
173 *host = in_str.substr(1, closebracket - 1);
147 } else { 174 } else {
148 return false; 175 return false;
149 } 176 }
150 } else { 177 } else {
151 std::string::size_type colonpos = in_str.find(':'); 178 std::string::size_type colonpos = in_str.find(':');
152 if (std::string::npos != colonpos) { 179 if (std::string::npos != colonpos) {
153 *host = in_str.substr(0, colonpos); 180 if (!ParsePort(in_str.substr(colonpos + 1, std::string::npos), port)) {
154 if (!rtc::FromString(
155 in_str.substr(colonpos + 1, std::string::npos), port)) {
156 return false; 181 return false;
157 } 182 }
183 *host = in_str.substr(0, colonpos);
158 } else { 184 } else {
159 *host = in_str; 185 *host = in_str;
160 } 186 }
161 } 187 }
162 return true; 188 return !host->empty();
163 } 189 }
164 190
165 typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration 191 // Adds a StunConfiguration or TurnConfiguration to the appropriate list,
166 StunConfiguration; 192 // by parsing |url| and using the username/password in |server|.
167 typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration
168 TurnConfiguration;
169
170 bool ParseIceServerUrl(const PeerConnectionInterface::IceServer& server, 193 bool ParseIceServerUrl(const PeerConnectionInterface::IceServer& server,
171 const std::string& url, 194 const std::string& url,
172 std::vector<StunConfiguration>* stun_config, 195 StunConfigurations* stun_config,
173 std::vector<TurnConfiguration>* turn_config) { 196 TurnConfigurations* turn_config) {
174 // draft-nandakumar-rtcweb-stun-uri-01 197 // draft-nandakumar-rtcweb-stun-uri-01
175 // stunURI = scheme ":" stun-host [ ":" stun-port ] 198 // stunURI = scheme ":" stun-host [ ":" stun-port ]
176 // scheme = "stun" / "stuns" 199 // scheme = "stun" / "stuns"
177 // stun-host = IP-literal / IPv4address / reg-name 200 // stun-host = IP-literal / IPv4address / reg-name
178 // stun-port = *DIGIT 201 // stun-port = *DIGIT
179 202
180 // draft-petithuguenin-behave-turn-uris-01 203 // draft-petithuguenin-behave-turn-uris-01
181 // turnURI = scheme ":" turn-host [ ":" turn-port ] 204 // turnURI = scheme ":" turn-host [ ":" turn-port ]
182 // [ "?transport=" transport ] 205 // [ "?transport=" transport ]
183 // scheme = "turn" / "turns" 206 // scheme = "turn" / "turns"
184 // transport = "udp" / "tcp" / transport-ext 207 // transport = "udp" / "tcp" / transport-ext
185 // transport-ext = 1*unreserved 208 // transport-ext = 1*unreserved
186 // turn-host = IP-literal / IPv4address / reg-name 209 // turn-host = IP-literal / IPv4address / reg-name
187 // turn-port = *DIGIT 210 // turn-port = *DIGIT
211 RTC_DCHECK(stun_config != nullptr);
212 RTC_DCHECK(turn_config != nullptr);
188 std::vector<std::string> tokens; 213 std::vector<std::string> tokens;
189 std::string turn_transport_type = kUdpTransportType; 214 std::string turn_transport_type = kUdpTransportType;
190 ASSERT(!url.empty()); 215 RTC_DCHECK(!url.empty());
191 rtc::tokenize(url, '?', &tokens); 216 rtc::tokenize(url, '?', &tokens);
192 std::string uri_without_transport = tokens[0]; 217 std::string uri_without_transport = tokens[0];
193 // Let's look into transport= param, if it exists. 218 // Let's look into transport= param, if it exists.
194 if (tokens.size() == kTurnTransportTokensNum) { // ?transport= is present. 219 if (tokens.size() == kTurnTransportTokensNum) { // ?transport= is present.
195 std::string uri_transport_param = tokens[1]; 220 std::string uri_transport_param = tokens[1];
196 rtc::tokenize(uri_transport_param, '=', &tokens); 221 rtc::tokenize(uri_transport_param, '=', &tokens);
197 if (tokens[0] == kTransport) { 222 if (tokens[0] == kTransport) {
198 // As per above grammar transport param will be consist of lower case 223 // As per above grammar transport param will be consist of lower case
199 // letters. 224 // letters.
200 if (tokens[1] != kUdpTransportType && tokens[1] != kTcpTransportType) { 225 if (tokens[1] != kUdpTransportType && tokens[1] != kTcpTransportType) {
201 LOG(LS_WARNING) << "Transport param should always be udp or tcp."; 226 LOG(LS_WARNING) << "Transport param should always be udp or tcp.";
202 return true; 227 return false;
203 } 228 }
204 turn_transport_type = tokens[1]; 229 turn_transport_type = tokens[1];
205 } 230 }
206 } 231 }
207 232
208 std::string hoststring; 233 std::string hoststring;
209 ServiceType service_type = INVALID; 234 ServiceType service_type;
210 if (!GetServiceTypeAndHostnameFromUri(uri_without_transport, 235 if (!GetServiceTypeAndHostnameFromUri(uri_without_transport,
211 &service_type, 236 &service_type,
212 &hoststring)) { 237 &hoststring)) {
213 LOG(LS_WARNING) << "Invalid transport parameter in ICE URI: " 238 LOG(LS_WARNING) << "Invalid transport parameter in ICE URI: " << url;
214 << uri_without_transport; 239 return false;
215 return true;
216 } 240 }
217 241
218 ASSERT(!hoststring.empty()); 242 // GetServiceTypeAndHostnameFromUri should never give an empty hoststring
243 RTC_DCHECK(!hoststring.empty());
219 244
220 // Let's break hostname. 245 // Let's break hostname.
221 tokens.clear(); 246 tokens.clear();
222 rtc::tokenize(hoststring, '@', &tokens); 247 rtc::tokenize_with_empty_tokens(hoststring, '@', &tokens);
223 ASSERT(!tokens.empty()); 248
224 std::string username(server.username); 249 std::string username(server.username);
225 // TODO(pthatcher): What's the right thing to do if tokens.size() is >2? 250 if (tokens.size() > kTurnHostTokensNum) {
226 // E.g. a string like "foo@bar@bat". 251 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring;
227 if (tokens.size() >= kTurnHostTokensNum) { 252 return false;
253 }
254 if (tokens.size() == kTurnHostTokensNum) {
255 if (tokens[0].empty() || tokens[1].empty()) {
256 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring;
257 return false;
258 }
228 username.assign(rtc::s_url_decode(tokens[0])); 259 username.assign(rtc::s_url_decode(tokens[0]));
229 hoststring = tokens[1]; 260 hoststring = tokens[1];
230 } else { 261 } else {
231 hoststring = tokens[0]; 262 hoststring = tokens[0];
232 } 263 }
233 264
234 int port = kDefaultStunPort; 265 int port = kDefaultStunPort;
235 if (service_type == TURNS) { 266 if (service_type == TURNS) {
236 port = kDefaultStunTlsPort; 267 port = kDefaultStunTlsPort;
237 turn_transport_type = kTcpTransportType; 268 turn_transport_type = kTcpTransportType;
238 } 269 }
239 270
240 std::string address; 271 std::string address;
241 if (!ParseHostnameAndPortFromString(hoststring, &address, &port)) { 272 if (!ParseHostnameAndPortFromString(hoststring, &address, &port)) {
242 LOG(WARNING) << "Invalid Hostname format: " << uri_without_transport; 273 LOG(WARNING) << "Invalid hostname format: " << uri_without_transport;
243 return true; 274 return false;
244 } 275 }
245 276
246 if (port <= 0 || port > 0xffff) { 277 if (port <= 0 || port > 0xffff) {
247 LOG(WARNING) << "Invalid port: " << port; 278 LOG(WARNING) << "Invalid port: " << port;
248 return true; 279 return false;
249 } 280 }
250 281
251 switch (service_type) { 282 switch (service_type) {
252 case STUN: 283 case STUN:
253 case STUNS: 284 case STUNS:
254 stun_config->push_back(StunConfiguration(address, port)); 285 stun_config->push_back(StunConfiguration(address, port));
255 break; 286 break;
256 case TURN: 287 case TURN:
257 case TURNS: { 288 case TURNS: {
258 if (username.empty()) {
259 // Turn url example from the spec |url:"turn:user@turn.example.org"|.
260 std::vector<std::string> turn_tokens;
261 rtc::tokenize(address, '@', &turn_tokens);
262 if (turn_tokens.size() == kTurnHostTokensNum) {
263 username.assign(rtc::s_url_decode(turn_tokens[0]));
264 address = turn_tokens[1];
265 }
266 }
267
268 bool secure = (service_type == TURNS); 289 bool secure = (service_type == TURNS);
269
270 turn_config->push_back(TurnConfiguration(address, port, 290 turn_config->push_back(TurnConfiguration(address, port,
271 username, 291 username,
272 server.password, 292 server.password,
273 turn_transport_type, 293 turn_transport_type,
274 secure)); 294 secure));
275 break; 295 break;
276 } 296 }
277 case INVALID: 297 case INVALID:
278 default: 298 default:
279 LOG(WARNING) << "Configuration not supported: " << url; 299 LOG(WARNING) << "Configuration not supported: " << url;
280 return false; 300 return false;
281 } 301 }
282 return true; 302 return true;
283 } 303 }
284 304
305 } // namespace
306
307 namespace webrtc {
308
285 bool ParseIceServers(const PeerConnectionInterface::IceServers& servers, 309 bool ParseIceServers(const PeerConnectionInterface::IceServers& servers,
286 std::vector<StunConfiguration>* stun_config, 310 StunConfigurations* stun_config,
287 std::vector<TurnConfiguration>* turn_config) { 311 TurnConfigurations* turn_config) {
288 for (const webrtc::PeerConnectionInterface::IceServer& server : servers) { 312 for (const webrtc::PeerConnectionInterface::IceServer& server : servers) {
289 if (!server.urls.empty()) { 313 if (!server.urls.empty()) {
290 for (const std::string& url : server.urls) { 314 for (const std::string& url : server.urls) {
291 if (url.empty()) { 315 if (url.empty()) {
292 LOG(WARNING) << "Empty uri."; 316 LOG(LS_ERROR) << "Empty uri.";
293 continue; 317 return false;
294 } 318 }
295 if (!ParseIceServerUrl(server, url, stun_config, turn_config)) { 319 if (!ParseIceServerUrl(server, url, stun_config, turn_config)) {
296 return false; 320 return false;
297 } 321 }
298 } 322 }
299 } else if (!server.uri.empty()) { 323 } else if (!server.uri.empty()) {
300 // Fallback to old .uri if new .urls isn't present. 324 // Fallback to old .uri if new .urls isn't present.
301 if (!ParseIceServerUrl(server, server.uri, stun_config, turn_config)) { 325 if (!ParseIceServerUrl(server, server.uri, stun_config, turn_config)) {
302 return false; 326 return false;
303 } 327 }
304 } else { 328 } else {
305 LOG(WARNING) << "Empty uri."; 329 LOG(LS_ERROR) << "Empty uri.";
330 return false;
306 } 331 }
307 } 332 }
308 return true; 333 return true;
309 } 334 }
310 335
311 // Check if we can send |new_stream| on a PeerConnection. 336 // Check if we can send |new_stream| on a PeerConnection.
312 // Currently only one audio but multiple video track is supported per 337 // Currently only one audio but multiple video track is supported per
313 // PeerConnection. 338 // PeerConnection.
314 bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams, 339 bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams,
315 webrtc::MediaStreamInterface* new_stream) { 340 webrtc::MediaStreamInterface* new_stream) {
316 if (!new_stream || !current_streams) 341 if (!new_stream || !current_streams)
317 return false; 342 return false;
318 if (current_streams->find(new_stream->label()) != NULL) { 343 if (current_streams->find(new_stream->label()) != NULL) {
319 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label() 344 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label()
320 << " is already added."; 345 << " is already added.";
321 return false; 346 return false;
322 } 347 }
323 348
324 return true; 349 return true;
325 } 350 }
326 351
327 } // namespace
328
329 namespace webrtc {
330
331 PeerConnection::PeerConnection(PeerConnectionFactory* factory) 352 PeerConnection::PeerConnection(PeerConnectionFactory* factory)
332 : factory_(factory), 353 : factory_(factory),
333 observer_(NULL), 354 observer_(NULL),
334 uma_observer_(NULL), 355 uma_observer_(NULL),
335 signaling_state_(kStable), 356 signaling_state_(kStable),
336 ice_state_(kIceNew), 357 ice_state_(kIceNew),
337 ice_connection_state_(kIceConnectionNew), 358 ice_connection_state_(kIceConnectionNew),
338 ice_gathering_state_(kIceGatheringNew) { 359 ice_gathering_state_(kIceGatheringNew) {
339 } 360 }
340 361
341 PeerConnection::~PeerConnection() { 362 PeerConnection::~PeerConnection() {
342 ASSERT(signaling_thread()->IsCurrent()); 363 RTC_DCHECK(signaling_thread()->IsCurrent());
343 if (mediastream_signaling_) { 364 if (mediastream_signaling_) {
344 mediastream_signaling_->TearDown(); 365 mediastream_signaling_->TearDown();
345 } 366 }
346 // Need to detach RTP senders/receivers from WebRtcSession, 367 // Need to detach RTP senders/receivers from WebRtcSession,
347 // since it's about to be destroyed. 368 // since it's about to be destroyed.
348 for (const auto& sender : senders_) { 369 for (const auto& sender : senders_) {
349 sender->Stop(); 370 sender->Stop();
350 } 371 }
351 for (const auto& receiver : receivers_) { 372 for (const auto& receiver : receivers_) {
352 receiver->Stop(); 373 receiver->Stop();
353 } 374 }
354 } 375 }
355 376
356 bool PeerConnection::Initialize( 377 bool PeerConnection::Initialize(
357 const PeerConnectionInterface::RTCConfiguration& configuration, 378 const PeerConnectionInterface::RTCConfiguration& configuration,
358 const MediaConstraintsInterface* constraints, 379 const MediaConstraintsInterface* constraints,
359 PortAllocatorFactoryInterface* allocator_factory, 380 PortAllocatorFactoryInterface* allocator_factory,
360 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, 381 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
361 PeerConnectionObserver* observer) { 382 PeerConnectionObserver* observer) {
362 ASSERT(observer != NULL); 383 RTC_DCHECK(observer != NULL);
363 if (!observer) 384 if (!observer)
364 return false; 385 return false;
365 observer_ = observer; 386 observer_ = observer;
366 387
367 std::vector<PortAllocatorFactoryInterface::StunConfiguration> stun_config; 388 std::vector<PortAllocatorFactoryInterface::StunConfiguration> stun_config;
368 std::vector<PortAllocatorFactoryInterface::TurnConfiguration> turn_config; 389 std::vector<PortAllocatorFactoryInterface::TurnConfiguration> turn_config;
369 if (!ParseIceServers(configuration.servers, &stun_config, &turn_config)) { 390 if (!ParseIceServers(configuration.servers, &stun_config, &turn_config)) {
370 return false; 391 return false;
371 } 392 }
372 port_allocator_.reset( 393 port_allocator_.reset(
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 for (const auto& receiver : receivers_) { 512 for (const auto& receiver : receivers_) {
492 receivers.push_back( 513 receivers.push_back(
493 RtpReceiverProxy::Create(signaling_thread(), receiver.get())); 514 RtpReceiverProxy::Create(signaling_thread(), receiver.get()));
494 } 515 }
495 return receivers; 516 return receivers;
496 } 517 }
497 518
498 bool PeerConnection::GetStats(StatsObserver* observer, 519 bool PeerConnection::GetStats(StatsObserver* observer,
499 MediaStreamTrackInterface* track, 520 MediaStreamTrackInterface* track,
500 StatsOutputLevel level) { 521 StatsOutputLevel level) {
501 ASSERT(signaling_thread()->IsCurrent()); 522 RTC_DCHECK(signaling_thread()->IsCurrent());
502 if (!VERIFY(observer != NULL)) { 523 if (!VERIFY(observer != NULL)) {
503 LOG(LS_ERROR) << "GetStats - observer is NULL."; 524 LOG(LS_ERROR) << "GetStats - observer is NULL.";
504 return false; 525 return false;
505 } 526 }
506 527
507 stats_->UpdateStats(level); 528 stats_->UpdateStats(level);
508 signaling_thread()->Post(this, MSG_GETSTATS, 529 signaling_thread()->Post(this, MSG_GETSTATS,
509 new GetStatsMsg(observer, track)); 530 new GetStatsMsg(observer, track));
510 return true; 531 return true;
511 } 532 }
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 } 834 }
814 case MSG_GETSTATS: { 835 case MSG_GETSTATS: {
815 GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata); 836 GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata);
816 StatsReports reports; 837 StatsReports reports;
817 stats_->GetStats(param->track, &reports); 838 stats_->GetStats(param->track, &reports);
818 param->observer->OnComplete(reports); 839 param->observer->OnComplete(reports);
819 delete param; 840 delete param;
820 break; 841 break;
821 } 842 }
822 default: 843 default:
823 ASSERT(false && "Not implemented"); 844 RTC_DCHECK(false && "Not implemented");
824 break; 845 break;
825 } 846 }
826 } 847 }
827 848
828 void PeerConnection::OnAddRemoteStream(MediaStreamInterface* stream) { 849 void PeerConnection::OnAddRemoteStream(MediaStreamInterface* stream) {
829 stats_->AddStream(stream); 850 stats_->AddStream(stream);
830 observer_->OnAddStream(stream); 851 observer_->OnAddStream(stream);
831 } 852 }
832 853
833 void PeerConnection::OnRemoveRemoteStream(MediaStreamInterface* stream) { 854 void PeerConnection::OnRemoveRemoteStream(MediaStreamInterface* stream) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 (*it)->Stop(); 941 (*it)->Stop();
921 senders_.erase(it); 942 senders_.erase(it);
922 } 943 }
923 } 944 }
924 945
925 void PeerConnection::OnRemoveLocalStream(MediaStreamInterface* stream) { 946 void PeerConnection::OnRemoveLocalStream(MediaStreamInterface* stream) {
926 } 947 }
927 948
928 void PeerConnection::OnIceConnectionChange( 949 void PeerConnection::OnIceConnectionChange(
929 PeerConnectionInterface::IceConnectionState new_state) { 950 PeerConnectionInterface::IceConnectionState new_state) {
930 ASSERT(signaling_thread()->IsCurrent()); 951 RTC_DCHECK(signaling_thread()->IsCurrent());
931 // After transitioning to "closed", ignore any additional states from 952 // After transitioning to "closed", ignore any additional states from
932 // WebRtcSession (such as "disconnected"). 953 // WebRtcSession (such as "disconnected").
933 if (ice_connection_state_ == kIceConnectionClosed) { 954 if (ice_connection_state_ == kIceConnectionClosed) {
934 return; 955 return;
935 } 956 }
936 ice_connection_state_ = new_state; 957 ice_connection_state_ = new_state;
937 observer_->OnIceConnectionChange(ice_connection_state_); 958 observer_->OnIceConnectionChange(ice_connection_state_);
938 } 959 }
939 960
940 void PeerConnection::OnIceGatheringChange( 961 void PeerConnection::OnIceGatheringChange(
941 PeerConnectionInterface::IceGatheringState new_state) { 962 PeerConnectionInterface::IceGatheringState new_state) {
942 ASSERT(signaling_thread()->IsCurrent()); 963 RTC_DCHECK(signaling_thread()->IsCurrent());
943 if (IsClosed()) { 964 if (IsClosed()) {
944 return; 965 return;
945 } 966 }
946 ice_gathering_state_ = new_state; 967 ice_gathering_state_ = new_state;
947 observer_->OnIceGatheringChange(ice_gathering_state_); 968 observer_->OnIceGatheringChange(ice_gathering_state_);
948 } 969 }
949 970
950 void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) { 971 void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) {
951 ASSERT(signaling_thread()->IsCurrent()); 972 RTC_DCHECK(signaling_thread()->IsCurrent());
952 observer_->OnIceCandidate(candidate); 973 observer_->OnIceCandidate(candidate);
953 } 974 }
954 975
955 void PeerConnection::OnIceComplete() { 976 void PeerConnection::OnIceComplete() {
956 ASSERT(signaling_thread()->IsCurrent()); 977 RTC_DCHECK(signaling_thread()->IsCurrent());
957 observer_->OnIceComplete(); 978 observer_->OnIceComplete();
958 } 979 }
959 980
960 void PeerConnection::OnIceConnectionReceivingChange(bool receiving) { 981 void PeerConnection::OnIceConnectionReceivingChange(bool receiving) {
961 ASSERT(signaling_thread()->IsCurrent()); 982 RTC_DCHECK(signaling_thread()->IsCurrent());
962 observer_->OnIceConnectionReceivingChange(receiving); 983 observer_->OnIceConnectionReceivingChange(receiving);
963 } 984 }
964 985
965 void PeerConnection::ChangeSignalingState( 986 void PeerConnection::ChangeSignalingState(
966 PeerConnectionInterface::SignalingState signaling_state) { 987 PeerConnectionInterface::SignalingState signaling_state) {
967 signaling_state_ = signaling_state; 988 signaling_state_ = signaling_state;
968 if (signaling_state == kClosed) { 989 if (signaling_state == kClosed) {
969 ice_connection_state_ = kIceConnectionClosed; 990 ice_connection_state_ = kIceConnectionClosed;
970 observer_->OnIceConnectionChange(ice_connection_state_); 991 observer_->OnIceConnectionChange(ice_connection_state_);
971 if (ice_gathering_state_ != kIceGatheringComplete) { 992 if (ice_gathering_state_ != kIceGatheringComplete) {
(...skipping 17 matching lines...) Expand all
989 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator 1010 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator
990 PeerConnection::FindReceiverForTrack(MediaStreamTrackInterface* track) { 1011 PeerConnection::FindReceiverForTrack(MediaStreamTrackInterface* track) {
991 return std::find_if( 1012 return std::find_if(
992 receivers_.begin(), receivers_.end(), 1013 receivers_.begin(), receivers_.end(),
993 [track](const rtc::scoped_refptr<RtpReceiverInterface>& receiver) { 1014 [track](const rtc::scoped_refptr<RtpReceiverInterface>& receiver) {
994 return receiver->track() == track; 1015 return receiver->track() == track;
995 }); 1016 });
996 } 1017 }
997 1018
998 } // namespace webrtc 1019 } // namespace webrtc
OLDNEW
« no previous file with comments | « talk/app/webrtc/peerconnection.h ('k') | talk/app/webrtc/peerconnection_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698