• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2012 The WebRTC project authors. All Rights Reserved.
3  *
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
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.
9  */
10 
11 #include "pc/ice_server_parsing.h"
12 
13 #include <string>
14 #include <vector>
15 
16 #include "p2p/base/port_interface.h"
17 #include "rtc_base/ip_address.h"
18 #include "rtc_base/socket_address.h"
19 #include "test/gtest.h"
20 
21 namespace webrtc {
22 
23 class IceServerParsingTest : public ::testing::Test {
24  public:
25   // Convenience functions for parsing a single URL. Result is stored in
26   // |stun_servers_| and |turn_servers_|.
ParseUrl(const std::string & url)27   bool ParseUrl(const std::string& url) {
28     return ParseUrl(url, std::string(), std::string());
29   }
30 
ParseTurnUrl(const std::string & url)31   bool ParseTurnUrl(const std::string& url) {
32     return ParseUrl(url, "username", "password");
33   }
34 
ParseUrl(const std::string & url,const std::string & username,const std::string & password)35   bool ParseUrl(const std::string& url,
36                 const std::string& username,
37                 const std::string& password) {
38     return ParseUrl(
39         url, username, password,
40         PeerConnectionInterface::TlsCertPolicy::kTlsCertPolicySecure);
41   }
42 
ParseUrl(const std::string & url,const std::string & username,const std::string & password,PeerConnectionInterface::TlsCertPolicy tls_certificate_policy)43   bool ParseUrl(const std::string& url,
44                 const std::string& username,
45                 const std::string& password,
46                 PeerConnectionInterface::TlsCertPolicy tls_certificate_policy) {
47     return ParseUrl(url, username, password, tls_certificate_policy, "");
48   }
49 
ParseUrl(const std::string & url,const std::string & username,const std::string & password,PeerConnectionInterface::TlsCertPolicy tls_certificate_policy,const std::string & hostname)50   bool ParseUrl(const std::string& url,
51                 const std::string& username,
52                 const std::string& password,
53                 PeerConnectionInterface::TlsCertPolicy tls_certificate_policy,
54                 const std::string& hostname) {
55     stun_servers_.clear();
56     turn_servers_.clear();
57     PeerConnectionInterface::IceServers servers;
58     PeerConnectionInterface::IceServer server;
59     server.urls.push_back(url);
60     server.username = username;
61     server.password = password;
62     server.tls_cert_policy = tls_certificate_policy;
63     server.hostname = hostname;
64     servers.push_back(server);
65     return webrtc::ParseIceServers(servers, &stun_servers_, &turn_servers_) ==
66            webrtc::RTCErrorType::NONE;
67   }
68 
69  protected:
70   cricket::ServerAddresses stun_servers_;
71   std::vector<cricket::RelayServerConfig> turn_servers_;
72 };
73 
74 // Make sure all STUN/TURN prefixes are parsed correctly.
TEST_F(IceServerParsingTest,ParseStunPrefixes)75 TEST_F(IceServerParsingTest, ParseStunPrefixes) {
76   EXPECT_TRUE(ParseUrl("stun:hostname"));
77   EXPECT_EQ(1U, stun_servers_.size());
78   EXPECT_EQ(0U, turn_servers_.size());
79 
80   EXPECT_TRUE(ParseUrl("stuns:hostname"));
81   EXPECT_EQ(1U, stun_servers_.size());
82   EXPECT_EQ(0U, turn_servers_.size());
83 
84   EXPECT_TRUE(ParseTurnUrl("turn:hostname"));
85   EXPECT_EQ(0U, stun_servers_.size());
86   EXPECT_EQ(1U, turn_servers_.size());
87   EXPECT_EQ(cricket::PROTO_UDP, turn_servers_[0].ports[0].proto);
88 
89   EXPECT_TRUE(ParseTurnUrl("turns:hostname"));
90   EXPECT_EQ(0U, stun_servers_.size());
91   EXPECT_EQ(1U, turn_servers_.size());
92   EXPECT_EQ(cricket::PROTO_TLS, turn_servers_[0].ports[0].proto);
93   EXPECT_TRUE(turn_servers_[0].tls_cert_policy ==
94               cricket::TlsCertPolicy::TLS_CERT_POLICY_SECURE);
95 
96   EXPECT_TRUE(ParseUrl(
97       "turns:hostname", "username", "password",
98       PeerConnectionInterface::TlsCertPolicy::kTlsCertPolicyInsecureNoCheck));
99   EXPECT_EQ(0U, stun_servers_.size());
100   EXPECT_EQ(1U, turn_servers_.size());
101   EXPECT_TRUE(turn_servers_[0].tls_cert_policy ==
102               cricket::TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK);
103   EXPECT_EQ(cricket::PROTO_TLS, turn_servers_[0].ports[0].proto);
104 
105   // invalid prefixes
106   EXPECT_FALSE(ParseUrl("stunn:hostname"));
107   EXPECT_FALSE(ParseUrl(":hostname"));
108   EXPECT_FALSE(ParseUrl(":"));
109   EXPECT_FALSE(ParseUrl(""));
110 }
111 
TEST_F(IceServerParsingTest,VerifyDefaults)112 TEST_F(IceServerParsingTest, VerifyDefaults) {
113   // TURNS defaults
114   EXPECT_TRUE(ParseTurnUrl("turns:hostname"));
115   EXPECT_EQ(1U, turn_servers_.size());
116   EXPECT_EQ(5349, turn_servers_[0].ports[0].address.port());
117   EXPECT_EQ(cricket::PROTO_TLS, turn_servers_[0].ports[0].proto);
118 
119   // TURN defaults
120   EXPECT_TRUE(ParseTurnUrl("turn:hostname"));
121   EXPECT_EQ(1U, turn_servers_.size());
122   EXPECT_EQ(3478, turn_servers_[0].ports[0].address.port());
123   EXPECT_EQ(cricket::PROTO_UDP, turn_servers_[0].ports[0].proto);
124 
125   // STUN defaults
126   EXPECT_TRUE(ParseUrl("stun:hostname"));
127   EXPECT_EQ(1U, stun_servers_.size());
128   EXPECT_EQ(3478, stun_servers_.begin()->port());
129 }
130 
131 // Check that the 6 combinations of IPv4/IPv6/hostname and with/without port
132 // can be parsed correctly.
TEST_F(IceServerParsingTest,ParseHostnameAndPort)133 TEST_F(IceServerParsingTest, ParseHostnameAndPort) {
134   EXPECT_TRUE(ParseUrl("stun:1.2.3.4:1234"));
135   EXPECT_EQ(1U, stun_servers_.size());
136   EXPECT_EQ("1.2.3.4", stun_servers_.begin()->hostname());
137   EXPECT_EQ(1234, stun_servers_.begin()->port());
138 
139   EXPECT_TRUE(ParseUrl("stun:[1:2:3:4:5:6:7:8]:4321"));
140   EXPECT_EQ(1U, stun_servers_.size());
141   EXPECT_EQ("1:2:3:4:5:6:7:8", stun_servers_.begin()->hostname());
142   EXPECT_EQ(4321, stun_servers_.begin()->port());
143 
144   EXPECT_TRUE(ParseUrl("stun:hostname:9999"));
145   EXPECT_EQ(1U, stun_servers_.size());
146   EXPECT_EQ("hostname", stun_servers_.begin()->hostname());
147   EXPECT_EQ(9999, stun_servers_.begin()->port());
148 
149   EXPECT_TRUE(ParseUrl("stun:1.2.3.4"));
150   EXPECT_EQ(1U, stun_servers_.size());
151   EXPECT_EQ("1.2.3.4", stun_servers_.begin()->hostname());
152   EXPECT_EQ(3478, stun_servers_.begin()->port());
153 
154   EXPECT_TRUE(ParseUrl("stun:[1:2:3:4:5:6:7:8]"));
155   EXPECT_EQ(1U, stun_servers_.size());
156   EXPECT_EQ("1:2:3:4:5:6:7:8", stun_servers_.begin()->hostname());
157   EXPECT_EQ(3478, stun_servers_.begin()->port());
158 
159   EXPECT_TRUE(ParseUrl("stun:hostname"));
160   EXPECT_EQ(1U, stun_servers_.size());
161   EXPECT_EQ("hostname", stun_servers_.begin()->hostname());
162   EXPECT_EQ(3478, stun_servers_.begin()->port());
163 
164   // Both TURN IP and host exist
165   EXPECT_TRUE(
166       ParseUrl("turn:1.2.3.4:1234", "username", "password",
167                PeerConnectionInterface::TlsCertPolicy::kTlsCertPolicySecure,
168                "hostname"));
169   EXPECT_EQ(1U, turn_servers_.size());
170   rtc::SocketAddress address = turn_servers_[0].ports[0].address;
171   EXPECT_EQ("hostname", address.hostname());
172   EXPECT_EQ(1234, address.port());
173   EXPECT_FALSE(address.IsUnresolvedIP());
174   EXPECT_EQ("1.2.3.4", address.ipaddr().ToString());
175 
176   // Try some invalid hostname:port strings.
177   EXPECT_FALSE(ParseUrl("stun:hostname:99a99"));
178   EXPECT_FALSE(ParseUrl("stun:hostname:-1"));
179   EXPECT_FALSE(ParseUrl("stun:hostname:port:more"));
180   EXPECT_FALSE(ParseUrl("stun:hostname:port more"));
181   EXPECT_FALSE(ParseUrl("stun:hostname:"));
182   EXPECT_FALSE(ParseUrl("stun:[1:2:3:4:5:6:7:8]junk:1000"));
183   EXPECT_FALSE(ParseUrl("stun::5555"));
184   EXPECT_FALSE(ParseUrl("stun:"));
185 }
186 
187 // Test parsing the "?transport=xxx" part of the URL.
TEST_F(IceServerParsingTest,ParseTransport)188 TEST_F(IceServerParsingTest, ParseTransport) {
189   EXPECT_TRUE(ParseTurnUrl("turn:hostname:1234?transport=tcp"));
190   EXPECT_EQ(1U, turn_servers_.size());
191   EXPECT_EQ(cricket::PROTO_TCP, turn_servers_[0].ports[0].proto);
192 
193   EXPECT_TRUE(ParseTurnUrl("turn:hostname?transport=udp"));
194   EXPECT_EQ(1U, turn_servers_.size());
195   EXPECT_EQ(cricket::PROTO_UDP, turn_servers_[0].ports[0].proto);
196 
197   EXPECT_FALSE(ParseTurnUrl("turn:hostname?transport=invalid"));
198   EXPECT_FALSE(ParseTurnUrl("turn:hostname?transport="));
199   EXPECT_FALSE(ParseTurnUrl("turn:hostname?="));
200   EXPECT_FALSE(ParseTurnUrl("turn:hostname?"));
201   EXPECT_FALSE(ParseTurnUrl("?"));
202 }
203 
204 // Reject pre-RFC 7065 syntax with ICE username contained in URL.
TEST_F(IceServerParsingTest,ParseRejectsUsername)205 TEST_F(IceServerParsingTest, ParseRejectsUsername) {
206   EXPECT_FALSE(ParseTurnUrl("turn:user@hostname"));
207 }
208 
209 // Test that username and password from IceServer is copied into the resulting
210 // RelayServerConfig.
TEST_F(IceServerParsingTest,CopyUsernameAndPasswordFromIceServer)211 TEST_F(IceServerParsingTest, CopyUsernameAndPasswordFromIceServer) {
212   EXPECT_TRUE(ParseUrl("turn:hostname", "username", "password"));
213   EXPECT_EQ(1U, turn_servers_.size());
214   EXPECT_EQ("username", turn_servers_[0].credentials.username);
215   EXPECT_EQ("password", turn_servers_[0].credentials.password);
216 }
217 
218 // Ensure that if a server has multiple URLs, each one is parsed.
TEST_F(IceServerParsingTest,ParseMultipleUrls)219 TEST_F(IceServerParsingTest, ParseMultipleUrls) {
220   PeerConnectionInterface::IceServers servers;
221   PeerConnectionInterface::IceServer server;
222   server.urls.push_back("stun:hostname");
223   server.urls.push_back("turn:hostname");
224   server.username = "foo";
225   server.password = "bar";
226   servers.push_back(server);
227   EXPECT_EQ(webrtc::RTCErrorType::NONE,
228             webrtc::ParseIceServers(servers, &stun_servers_, &turn_servers_));
229   EXPECT_EQ(1U, stun_servers_.size());
230   EXPECT_EQ(1U, turn_servers_.size());
231 }
232 
233 // Ensure that TURN servers are given unique priorities,
234 // so that their resulting candidates have unique priorities.
TEST_F(IceServerParsingTest,TurnServerPrioritiesUnique)235 TEST_F(IceServerParsingTest, TurnServerPrioritiesUnique) {
236   PeerConnectionInterface::IceServers servers;
237   PeerConnectionInterface::IceServer server;
238   server.urls.push_back("turn:hostname");
239   server.urls.push_back("turn:hostname2");
240   server.username = "foo";
241   server.password = "bar";
242   servers.push_back(server);
243   EXPECT_EQ(webrtc::RTCErrorType::NONE,
244             webrtc::ParseIceServers(servers, &stun_servers_, &turn_servers_));
245   EXPECT_EQ(2U, turn_servers_.size());
246   EXPECT_NE(turn_servers_[0].priority, turn_servers_[1].priority);
247 }
248 
249 }  // namespace webrtc
250