3 * Copyright 2009 Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
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,
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
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "webrtc/p2p/base/basicpacketsocketfactory.h"
29 #include "webrtc/p2p/base/stunport.h"
30 #include "webrtc/p2p/base/teststunserver.h"
31 #include "webrtc/base/gunit.h"
32 #include "webrtc/base/helpers.h"
33 #include "webrtc/base/physicalsocketserver.h"
34 #include "webrtc/base/scoped_ptr.h"
35 #include "webrtc/base/socketaddress.h"
36 #include "webrtc/base/ssladapter.h"
37 #include "webrtc/base/virtualsocketserver.h"
39 using cricket::ServerAddresses;
40 using rtc::SocketAddress;
42 static const SocketAddress kLocalAddr("127.0.0.1", 0);
43 static const SocketAddress kStunAddr1("127.0.0.1", 5000);
44 static const SocketAddress kStunAddr2("127.0.0.1", 4000);
45 static const SocketAddress kBadAddr("0.0.0.1", 5000);
46 static const SocketAddress kStunHostnameAddr("localhost", 5000);
47 static const SocketAddress kBadHostnameAddr("not-a-real-hostname", 5000);
48 static const int kTimeoutMs = 10000;
49 // stun prio = 100 << 24 | 30 (IPV4) << 8 | 256 - 0
50 static const uint32 kStunCandidatePriority = 1677729535;
52 // Tests connecting a StunPort to a fake STUN server (cricket::StunServer)
53 // TODO: Use a VirtualSocketServer here. We have to use a
54 // PhysicalSocketServer right now since DNS is not part of SocketServer yet.
55 class StunPortTest : public testing::Test,
56 public sigslot::has_slots<> {
59 : pss_(new rtc::PhysicalSocketServer),
60 ss_(new rtc::VirtualSocketServer(pss_.get())),
62 network_("unittest", "unittest", rtc::IPAddress(INADDR_ANY), 32),
63 socket_factory_(rtc::Thread::Current()),
64 stun_server_1_(cricket::TestStunServer::Create(
65 rtc::Thread::Current(), kStunAddr1)),
66 stun_server_2_(cricket::TestStunServer::Create(
67 rtc::Thread::Current(), kStunAddr2)),
68 done_(false), error_(false), stun_keepalive_delay_(0) {
71 const cricket::Port* port() const { return stun_port_.get(); }
72 bool done() const { return done_; }
73 bool error() const { return error_; }
75 void CreateStunPort(const rtc::SocketAddress& server_addr) {
76 ServerAddresses stun_servers;
77 stun_servers.insert(server_addr);
78 CreateStunPort(stun_servers);
81 void CreateStunPort(const ServerAddresses& stun_servers) {
82 stun_port_.reset(cricket::StunPort::Create(
83 rtc::Thread::Current(), &socket_factory_, &network_,
84 kLocalAddr.ipaddr(), 0, 0, rtc::CreateRandomString(16),
85 rtc::CreateRandomString(22), stun_servers));
86 stun_port_->set_stun_keepalive_delay(stun_keepalive_delay_);
87 stun_port_->SignalPortComplete.connect(this,
88 &StunPortTest::OnPortComplete);
89 stun_port_->SignalPortError.connect(this,
90 &StunPortTest::OnPortError);
93 void CreateSharedStunPort(const rtc::SocketAddress& server_addr) {
94 socket_.reset(socket_factory_.CreateUdpSocket(
95 rtc::SocketAddress(kLocalAddr.ipaddr(), 0), 0, 0));
96 ASSERT_TRUE(socket_ != NULL);
97 socket_->SignalReadPacket.connect(this, &StunPortTest::OnReadPacket);
98 stun_port_.reset(cricket::UDPPort::Create(
99 rtc::Thread::Current(), &socket_factory_,
100 &network_, socket_.get(),
101 rtc::CreateRandomString(16), rtc::CreateRandomString(22)));
102 ASSERT_TRUE(stun_port_ != NULL);
103 ServerAddresses stun_servers;
104 stun_servers.insert(server_addr);
105 stun_port_->set_server_addresses(stun_servers);
106 stun_port_->SignalPortComplete.connect(this,
107 &StunPortTest::OnPortComplete);
108 stun_port_->SignalPortError.connect(this,
109 &StunPortTest::OnPortError);
112 void PrepareAddress() {
113 stun_port_->PrepareAddress();
116 void OnReadPacket(rtc::AsyncPacketSocket* socket, const char* data,
117 size_t size, const rtc::SocketAddress& remote_addr,
118 const rtc::PacketTime& packet_time) {
119 stun_port_->HandleIncomingPacket(
120 socket, data, size, remote_addr, rtc::PacketTime());
123 void SendData(const char* data, size_t len) {
124 stun_port_->HandleIncomingPacket(
125 socket_.get(), data, len, rtc::SocketAddress("22.22.22.22", 0),
130 static void SetUpTestCase() {
131 // Ensure the RNG is inited.
132 rtc::InitRandom(NULL, 0);
136 void OnPortComplete(cricket::Port* port) {
141 void OnPortError(cricket::Port* port) {
145 void SetKeepaliveDelay(int delay) {
146 stun_keepalive_delay_ = delay;
149 cricket::TestStunServer* stun_server_1() {
150 return stun_server_1_.get();
152 cricket::TestStunServer* stun_server_2() {
153 return stun_server_2_.get();
157 rtc::scoped_ptr<rtc::PhysicalSocketServer> pss_;
158 rtc::scoped_ptr<rtc::VirtualSocketServer> ss_;
159 rtc::SocketServerScope ss_scope_;
160 rtc::Network network_;
161 rtc::BasicPacketSocketFactory socket_factory_;
162 rtc::scoped_ptr<cricket::UDPPort> stun_port_;
163 rtc::scoped_ptr<cricket::TestStunServer> stun_server_1_;
164 rtc::scoped_ptr<cricket::TestStunServer> stun_server_2_;
165 rtc::scoped_ptr<rtc::AsyncPacketSocket> socket_;
168 int stun_keepalive_delay_;
171 // Test that we can create a STUN port
172 TEST_F(StunPortTest, TestBasic) {
173 CreateStunPort(kStunAddr1);
174 EXPECT_EQ("stun", port()->Type());
175 EXPECT_EQ(0U, port()->Candidates().size());
178 // Test that we can get an address from a STUN server.
179 TEST_F(StunPortTest, TestPrepareAddress) {
180 CreateStunPort(kStunAddr1);
182 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
183 ASSERT_EQ(1U, port()->Candidates().size());
184 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
186 // TODO: Add IPv6 tests here, once either physicalsocketserver supports
187 // IPv6, or this test is changed to use VirtualSocketServer.
190 // Test that we fail properly if we can't get an address.
191 TEST_F(StunPortTest, TestPrepareAddressFail) {
192 CreateStunPort(kBadAddr);
194 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
195 EXPECT_TRUE(error());
196 EXPECT_EQ(0U, port()->Candidates().size());
199 // Test that we can get an address from a STUN server specified by a hostname.
200 TEST_F(StunPortTest, TestPrepareAddressHostname) {
201 CreateStunPort(kStunHostnameAddr);
203 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
204 ASSERT_EQ(1U, port()->Candidates().size());
205 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
206 EXPECT_EQ(kStunCandidatePriority, port()->Candidates()[0].priority());
209 // Test that we handle hostname lookup failures properly.
210 TEST_F(StunPortTest, TestPrepareAddressHostnameFail) {
211 CreateStunPort(kBadHostnameAddr);
213 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
214 EXPECT_TRUE(error());
215 EXPECT_EQ(0U, port()->Candidates().size());
218 // This test verifies keepalive response messages don't result in
219 // additional candidate generation.
220 TEST_F(StunPortTest, TestKeepAliveResponse) {
221 SetKeepaliveDelay(500); // 500ms of keepalive delay.
222 CreateStunPort(kStunHostnameAddr);
224 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
225 ASSERT_EQ(1U, port()->Candidates().size());
226 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
227 // Waiting for 1 seond, which will allow us to process
228 // response for keepalive binding request. 500 ms is the keepalive delay.
229 rtc::Thread::Current()->ProcessMessages(1000);
230 ASSERT_EQ(1U, port()->Candidates().size());
233 // Test that a local candidate can be generated using a shared socket.
234 TEST_F(StunPortTest, TestSharedSocketPrepareAddress) {
235 CreateSharedStunPort(kStunAddr1);
237 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
238 ASSERT_EQ(1U, port()->Candidates().size());
239 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
242 // Test that we still a get a local candidate with invalid stun server hostname.
243 // Also verifing that UDPPort can receive packets when stun address can't be
245 TEST_F(StunPortTest, TestSharedSocketPrepareAddressInvalidHostname) {
246 CreateSharedStunPort(kBadHostnameAddr);
248 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
249 ASSERT_EQ(1U, port()->Candidates().size());
250 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address()));
252 // Send data to port after it's ready. This is to make sure, UDP port can
253 // handle data with unresolved stun server address.
254 std::string data = "some random data, sending to cricket::Port.";
255 SendData(data.c_str(), data.length());
256 // No crash is success.
259 // Test that the same address is added only once if two STUN servers are in use.
260 TEST_F(StunPortTest, TestNoDuplicatedAddressWithTwoStunServers) {
261 ServerAddresses stun_servers;
262 stun_servers.insert(kStunAddr1);
263 stun_servers.insert(kStunAddr2);
264 CreateStunPort(stun_servers);
265 EXPECT_EQ("stun", port()->Type());
267 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
268 EXPECT_EQ(1U, port()->Candidates().size());
271 // Test that candidates can be allocated for multiple STUN servers, one of which
273 TEST_F(StunPortTest, TestMultipleStunServersWithBadServer) {
274 ServerAddresses stun_servers;
275 stun_servers.insert(kStunAddr1);
276 stun_servers.insert(kBadAddr);
277 CreateStunPort(stun_servers);
278 EXPECT_EQ("stun", port()->Type());
280 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
281 EXPECT_EQ(1U, port()->Candidates().size());
284 // Test that two candidates are allocated if the two STUN servers return
285 // different mapped addresses.
286 TEST_F(StunPortTest, TestTwoCandidatesWithTwoStunServersAcrossNat) {
287 const SocketAddress kStunMappedAddr1("77.77.77.77", 0);
288 const SocketAddress kStunMappedAddr2("88.77.77.77", 0);
289 stun_server_1()->set_fake_stun_addr(kStunMappedAddr1);
290 stun_server_2()->set_fake_stun_addr(kStunMappedAddr2);
292 ServerAddresses stun_servers;
293 stun_servers.insert(kStunAddr1);
294 stun_servers.insert(kStunAddr2);
295 CreateStunPort(stun_servers);
296 EXPECT_EQ("stun", port()->Type());
298 EXPECT_TRUE_WAIT(done(), kTimeoutMs);
299 EXPECT_EQ(2U, port()->Candidates().size());