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

Side by Side Diff: webrtc/pc/peerconnection.cc

Issue 2738353003: Rewrite PeerConnection integration tests using better testing practices. (Closed)
Patch Set: Fixing issues caught by trybots. Created 3 years, 8 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 | « webrtc/pc/peerconnection.h ('k') | webrtc/pc/peerconnection_integrationtest.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 * Copyright 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/pc/peerconnection.h" 11 #include "webrtc/pc/peerconnection.h"
12 12
13 #include <algorithm> 13 #include <algorithm>
14 #include <cctype> // for isdigit
15 #include <utility> 14 #include <utility>
16 #include <vector> 15 #include <vector>
17 16
18 #include "webrtc/api/jsepicecandidate.h" 17 #include "webrtc/api/jsepicecandidate.h"
19 #include "webrtc/api/jsepsessiondescription.h" 18 #include "webrtc/api/jsepsessiondescription.h"
20 #include "webrtc/api/mediaconstraintsinterface.h" 19 #include "webrtc/api/mediaconstraintsinterface.h"
21 #include "webrtc/api/mediastreamproxy.h" 20 #include "webrtc/api/mediastreamproxy.h"
22 #include "webrtc/api/mediastreamtrackproxy.h" 21 #include "webrtc/api/mediastreamtrackproxy.h"
23 #include "webrtc/base/arraysize.h"
24 #include "webrtc/base/bind.h" 22 #include "webrtc/base/bind.h"
25 #include "webrtc/base/checks.h" 23 #include "webrtc/base/checks.h"
26 #include "webrtc/base/logging.h" 24 #include "webrtc/base/logging.h"
27 #include "webrtc/base/stringencode.h" 25 #include "webrtc/base/stringencode.h"
28 #include "webrtc/base/stringutils.h" 26 #include "webrtc/base/stringutils.h"
29 #include "webrtc/base/trace_event.h" 27 #include "webrtc/base/trace_event.h"
30 #include "webrtc/call/call.h" 28 #include "webrtc/call/call.h"
31 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" 29 #include "webrtc/logging/rtc_event_log/rtc_event_log.h"
32 #include "webrtc/media/sctp/sctptransport.h" 30 #include "webrtc/media/sctp/sctptransport.h"
33 #include "webrtc/pc/audiotrack.h" 31 #include "webrtc/pc/audiotrack.h"
(...skipping 21 matching lines...) Expand all
55 using webrtc::RtpSenderInternal; 53 using webrtc::RtpSenderInternal;
56 using webrtc::RtpSenderInterface; 54 using webrtc::RtpSenderInterface;
57 using webrtc::RtpSenderProxy; 55 using webrtc::RtpSenderProxy;
58 using webrtc::RtpSenderProxyWithInternal; 56 using webrtc::RtpSenderProxyWithInternal;
59 using webrtc::StreamCollection; 57 using webrtc::StreamCollection;
60 58
61 static const char kDefaultStreamLabel[] = "default"; 59 static const char kDefaultStreamLabel[] = "default";
62 static const char kDefaultAudioTrackLabel[] = "defaulta0"; 60 static const char kDefaultAudioTrackLabel[] = "defaulta0";
63 static const char kDefaultVideoTrackLabel[] = "defaultv0"; 61 static const char kDefaultVideoTrackLabel[] = "defaultv0";
64 62
65 // The min number of tokens must present in Turn host uri.
66 // e.g. user@turn.example.org
67 static const size_t kTurnHostTokensNum = 2;
68 // Number of tokens must be preset when TURN uri has transport param.
69 static const size_t kTurnTransportTokensNum = 2;
70 // The default stun port.
71 static const int kDefaultStunPort = 3478;
72 static const int kDefaultStunTlsPort = 5349;
73 static const char kTransport[] = "transport";
74
75 // NOTE: Must be in the same order as the ServiceType enum.
76 static const char* kValidIceServiceTypes[] = {"stun", "stuns", "turn", "turns"};
77
78 // The length of RTCP CNAMEs. 63 // The length of RTCP CNAMEs.
79 static const int kRtcpCnameLength = 16; 64 static const int kRtcpCnameLength = 16;
80 65
81 // NOTE: A loop below assumes that the first value of this enum is 0 and all
82 // other values are incremental.
83 enum ServiceType {
84 STUN = 0, // Indicates a STUN server.
85 STUNS, // Indicates a STUN server used with a TLS session.
86 TURN, // Indicates a TURN server
87 TURNS, // Indicates a TURN server used with a TLS session.
88 INVALID, // Unknown.
89 };
90 static_assert(INVALID == arraysize(kValidIceServiceTypes),
91 "kValidIceServiceTypes must have as many strings as ServiceType "
92 "has values.");
93
94 enum { 66 enum {
95 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0, 67 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0,
96 MSG_SET_SESSIONDESCRIPTION_FAILED, 68 MSG_SET_SESSIONDESCRIPTION_FAILED,
97 MSG_CREATE_SESSIONDESCRIPTION_FAILED, 69 MSG_CREATE_SESSIONDESCRIPTION_FAILED,
98 MSG_GETSTATS, 70 MSG_GETSTATS,
99 MSG_FREE_DATACHANNELS, 71 MSG_FREE_DATACHANNELS,
100 }; 72 };
101 73
102 struct SetSessionDescriptionMsg : public rtc::MessageData { 74 struct SetSessionDescriptionMsg : public rtc::MessageData {
103 explicit SetSessionDescriptionMsg( 75 explicit SetSessionDescriptionMsg(
(...skipping 16 matching lines...) Expand all
120 92
121 struct GetStatsMsg : public rtc::MessageData { 93 struct GetStatsMsg : public rtc::MessageData {
122 GetStatsMsg(webrtc::StatsObserver* observer, 94 GetStatsMsg(webrtc::StatsObserver* observer,
123 webrtc::MediaStreamTrackInterface* track) 95 webrtc::MediaStreamTrackInterface* track)
124 : observer(observer), track(track) { 96 : observer(observer), track(track) {
125 } 97 }
126 rtc::scoped_refptr<webrtc::StatsObserver> observer; 98 rtc::scoped_refptr<webrtc::StatsObserver> observer;
127 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track; 99 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track;
128 }; 100 };
129 101
130 // |in_str| should be of format
131 // stunURI = scheme ":" stun-host [ ":" stun-port ]
132 // scheme = "stun" / "stuns"
133 // stun-host = IP-literal / IPv4address / reg-name
134 // stun-port = *DIGIT
135 //
136 // draft-petithuguenin-behave-turn-uris-01
137 // turnURI = scheme ":" turn-host [ ":" turn-port ]
138 // turn-host = username@IP-literal / IPv4address / reg-name
139 bool GetServiceTypeAndHostnameFromUri(const std::string& in_str,
140 ServiceType* service_type,
141 std::string* hostname) {
142 const std::string::size_type colonpos = in_str.find(':');
143 if (colonpos == std::string::npos) {
144 LOG(LS_WARNING) << "Missing ':' in ICE URI: " << in_str;
145 return false;
146 }
147 if ((colonpos + 1) == in_str.length()) {
148 LOG(LS_WARNING) << "Empty hostname in ICE URI: " << in_str;
149 return false;
150 }
151 *service_type = INVALID;
152 for (size_t i = 0; i < arraysize(kValidIceServiceTypes); ++i) {
153 if (in_str.compare(0, colonpos, kValidIceServiceTypes[i]) == 0) {
154 *service_type = static_cast<ServiceType>(i);
155 break;
156 }
157 }
158 if (*service_type == INVALID) {
159 return false;
160 }
161 *hostname = in_str.substr(colonpos + 1, std::string::npos);
162 return true;
163 }
164
165 bool ParsePort(const std::string& in_str, int* port) {
166 // Make sure port only contains digits. FromString doesn't check this.
167 for (const char& c : in_str) {
168 if (!std::isdigit(c)) {
169 return false;
170 }
171 }
172 return rtc::FromString(in_str, port);
173 }
174
175 // This method parses IPv6 and IPv4 literal strings, along with hostnames in
176 // standard hostname:port format.
177 // Consider following formats as correct.
178 // |hostname:port|, |[IPV6 address]:port|, |IPv4 address|:port,
179 // |hostname|, |[IPv6 address]|, |IPv4 address|.
180 bool ParseHostnameAndPortFromString(const std::string& in_str,
181 std::string* host,
182 int* port) {
183 RTC_DCHECK(host->empty());
184 if (in_str.at(0) == '[') {
185 std::string::size_type closebracket = in_str.rfind(']');
186 if (closebracket != std::string::npos) {
187 std::string::size_type colonpos = in_str.find(':', closebracket);
188 if (std::string::npos != colonpos) {
189 if (!ParsePort(in_str.substr(closebracket + 2, std::string::npos),
190 port)) {
191 return false;
192 }
193 }
194 *host = in_str.substr(1, closebracket - 1);
195 } else {
196 return false;
197 }
198 } else {
199 std::string::size_type colonpos = in_str.find(':');
200 if (std::string::npos != colonpos) {
201 if (!ParsePort(in_str.substr(colonpos + 1, std::string::npos), port)) {
202 return false;
203 }
204 *host = in_str.substr(0, colonpos);
205 } else {
206 *host = in_str;
207 }
208 }
209 return !host->empty();
210 }
211
212 // Adds a STUN or TURN server to the appropriate list,
213 // by parsing |url| and using the username/password in |server|.
214 RTCErrorType ParseIceServerUrl(
215 const PeerConnectionInterface::IceServer& server,
216 const std::string& url,
217 cricket::ServerAddresses* stun_servers,
218 std::vector<cricket::RelayServerConfig>* turn_servers) {
219 // draft-nandakumar-rtcweb-stun-uri-01
220 // stunURI = scheme ":" stun-host [ ":" stun-port ]
221 // scheme = "stun" / "stuns"
222 // stun-host = IP-literal / IPv4address / reg-name
223 // stun-port = *DIGIT
224
225 // draft-petithuguenin-behave-turn-uris-01
226 // turnURI = scheme ":" turn-host [ ":" turn-port ]
227 // [ "?transport=" transport ]
228 // scheme = "turn" / "turns"
229 // transport = "udp" / "tcp" / transport-ext
230 // transport-ext = 1*unreserved
231 // turn-host = IP-literal / IPv4address / reg-name
232 // turn-port = *DIGIT
233 RTC_DCHECK(stun_servers != nullptr);
234 RTC_DCHECK(turn_servers != nullptr);
235 std::vector<std::string> tokens;
236 cricket::ProtocolType turn_transport_type = cricket::PROTO_UDP;
237 RTC_DCHECK(!url.empty());
238 rtc::tokenize_with_empty_tokens(url, '?', &tokens);
239 std::string uri_without_transport = tokens[0];
240 // Let's look into transport= param, if it exists.
241 if (tokens.size() == kTurnTransportTokensNum) { // ?transport= is present.
242 std::string uri_transport_param = tokens[1];
243 rtc::tokenize_with_empty_tokens(uri_transport_param, '=', &tokens);
244 if (tokens[0] != kTransport) {
245 LOG(LS_WARNING) << "Invalid transport parameter key.";
246 return RTCErrorType::SYNTAX_ERROR;
247 }
248 if (tokens.size() < 2) {
249 LOG(LS_WARNING) << "Transport parameter missing value.";
250 return RTCErrorType::SYNTAX_ERROR;
251 }
252 if (!cricket::StringToProto(tokens[1].c_str(), &turn_transport_type) ||
253 (turn_transport_type != cricket::PROTO_UDP &&
254 turn_transport_type != cricket::PROTO_TCP)) {
255 LOG(LS_WARNING) << "Transport parameter should always be udp or tcp.";
256 return RTCErrorType::SYNTAX_ERROR;
257 }
258 }
259
260 std::string hoststring;
261 ServiceType service_type;
262 if (!GetServiceTypeAndHostnameFromUri(uri_without_transport,
263 &service_type,
264 &hoststring)) {
265 LOG(LS_WARNING) << "Invalid transport parameter in ICE URI: " << url;
266 return RTCErrorType::SYNTAX_ERROR;
267 }
268
269 // GetServiceTypeAndHostnameFromUri should never give an empty hoststring
270 RTC_DCHECK(!hoststring.empty());
271
272 // Let's break hostname.
273 tokens.clear();
274 rtc::tokenize_with_empty_tokens(hoststring, '@', &tokens);
275
276 std::string username(server.username);
277 if (tokens.size() > kTurnHostTokensNum) {
278 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring;
279 return RTCErrorType::SYNTAX_ERROR;
280 }
281 if (tokens.size() == kTurnHostTokensNum) {
282 if (tokens[0].empty() || tokens[1].empty()) {
283 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring;
284 return RTCErrorType::SYNTAX_ERROR;
285 }
286 username.assign(rtc::s_url_decode(tokens[0]));
287 hoststring = tokens[1];
288 } else {
289 hoststring = tokens[0];
290 }
291
292 int port = kDefaultStunPort;
293 if (service_type == TURNS) {
294 port = kDefaultStunTlsPort;
295 turn_transport_type = cricket::PROTO_TLS;
296 }
297
298 std::string address;
299 if (!ParseHostnameAndPortFromString(hoststring, &address, &port)) {
300 LOG(WARNING) << "Invalid hostname format: " << uri_without_transport;
301 return RTCErrorType::SYNTAX_ERROR;
302 }
303
304 if (port <= 0 || port > 0xffff) {
305 LOG(WARNING) << "Invalid port: " << port;
306 return RTCErrorType::SYNTAX_ERROR;
307 }
308
309 switch (service_type) {
310 case STUN:
311 case STUNS:
312 stun_servers->insert(rtc::SocketAddress(address, port));
313 break;
314 case TURN:
315 case TURNS: {
316 if (username.empty() || server.password.empty()) {
317 // The WebRTC spec requires throwing an InvalidAccessError when username
318 // or credential are ommitted; this is the native equivalent.
319 return RTCErrorType::INVALID_PARAMETER;
320 }
321 cricket::RelayServerConfig config = cricket::RelayServerConfig(
322 address, port, username, server.password, turn_transport_type);
323 if (server.tls_cert_policy ==
324 PeerConnectionInterface::kTlsCertPolicyInsecureNoCheck) {
325 config.tls_cert_policy =
326 cricket::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK;
327 }
328 turn_servers->push_back(config);
329 break;
330 }
331 default:
332 // We shouldn't get to this point with an invalid service_type, we should
333 // have returned an error already.
334 RTC_NOTREACHED() << "Unexpected service type";
335 return RTCErrorType::INTERNAL_ERROR;
336 }
337 return RTCErrorType::NONE;
338 }
339
340 // Check if we can send |new_stream| on a PeerConnection. 102 // Check if we can send |new_stream| on a PeerConnection.
341 bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams, 103 bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams,
342 webrtc::MediaStreamInterface* new_stream) { 104 webrtc::MediaStreamInterface* new_stream) {
343 if (!new_stream || !current_streams) { 105 if (!new_stream || !current_streams) {
344 return false; 106 return false;
345 } 107 }
346 if (current_streams->find(new_stream->label()) != nullptr) { 108 if (current_streams->find(new_stream->label()) != nullptr) {
347 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label() 109 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label()
348 << " is already added."; 110 << " is already added.";
349 return false; 111 return false;
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 for (auto& kv : session_options->transport_options) { 384 for (auto& kv : session_options->transport_options) {
623 kv.second.ice_restart = ice_restart; 385 kv.second.ice_restart = ice_restart;
624 } 386 }
625 387
626 if (!constraints) { 388 if (!constraints) {
627 return true; 389 return true;
628 } 390 }
629 return mandatory_constraints_satisfied == constraints->GetMandatory().size(); 391 return mandatory_constraints_satisfied == constraints->GetMandatory().size();
630 } 392 }
631 393
632 RTCErrorType ParseIceServers(
633 const PeerConnectionInterface::IceServers& servers,
634 cricket::ServerAddresses* stun_servers,
635 std::vector<cricket::RelayServerConfig>* turn_servers) {
636 for (const webrtc::PeerConnectionInterface::IceServer& server : servers) {
637 if (!server.urls.empty()) {
638 for (const std::string& url : server.urls) {
639 if (url.empty()) {
640 LOG(LS_ERROR) << "Empty uri.";
641 return RTCErrorType::SYNTAX_ERROR;
642 }
643 RTCErrorType err =
644 ParseIceServerUrl(server, url, stun_servers, turn_servers);
645 if (err != RTCErrorType::NONE) {
646 return err;
647 }
648 }
649 } else if (!server.uri.empty()) {
650 // Fallback to old .uri if new .urls isn't present.
651 RTCErrorType err =
652 ParseIceServerUrl(server, server.uri, stun_servers, turn_servers);
653 if (err != RTCErrorType::NONE) {
654 return err;
655 }
656 } else {
657 LOG(LS_ERROR) << "Empty uri.";
658 return RTCErrorType::SYNTAX_ERROR;
659 }
660 }
661 // Candidates must have unique priorities, so that connectivity checks
662 // are performed in a well-defined order.
663 int priority = static_cast<int>(turn_servers->size() - 1);
664 for (cricket::RelayServerConfig& turn_server : *turn_servers) {
665 // First in the list gets highest priority.
666 turn_server.priority = priority--;
667 }
668 return RTCErrorType::NONE;
669 }
670
671 PeerConnection::PeerConnection(PeerConnectionFactory* factory) 394 PeerConnection::PeerConnection(PeerConnectionFactory* factory)
672 : factory_(factory), 395 : factory_(factory),
673 observer_(NULL), 396 observer_(NULL),
674 uma_observer_(NULL), 397 uma_observer_(NULL),
675 signaling_state_(kStable), 398 signaling_state_(kStable),
676 ice_connection_state_(kIceConnectionNew), 399 ice_connection_state_(kIceConnectionNew),
677 ice_gathering_state_(kIceGatheringNew), 400 ice_gathering_state_(kIceGatheringNew),
678 event_log_(RtcEventLog::Create()), 401 event_log_(RtcEventLog::Create()),
679 rtcp_cname_(GenerateRtcpCname()), 402 rtcp_cname_(GenerateRtcpCname()),
680 local_streams_(StreamCollection::Create()), 403 local_streams_(StreamCollection::Create()),
(...skipping 1904 matching lines...) Expand 10 before | Expand all | Expand 10 after
2585 } 2308 }
2586 return event_log_->StartLogging(file, max_size_bytes); 2309 return event_log_->StartLogging(file, max_size_bytes);
2587 } 2310 }
2588 2311
2589 void PeerConnection::StopRtcEventLog_w() { 2312 void PeerConnection::StopRtcEventLog_w() {
2590 if (event_log_) { 2313 if (event_log_) {
2591 event_log_->StopLogging(); 2314 event_log_->StopLogging();
2592 } 2315 }
2593 } 2316 }
2594 } // namespace webrtc 2317 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/pc/peerconnection.h ('k') | webrtc/pc/peerconnection_integrationtest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698