1/* 2 * Copyright 2009 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 "webrtc/p2p/base/basicpacketsocketfactory.h" 12#include "webrtc/p2p/base/stunport.h" 13#include "webrtc/p2p/base/teststunserver.h" 14#include "webrtc/base/gunit.h" 15#include "webrtc/base/helpers.h" 16#include "webrtc/base/physicalsocketserver.h" 17#include "webrtc/base/scoped_ptr.h" 18#include "webrtc/base/socketaddress.h" 19#include "webrtc/base/ssladapter.h" 20#include "webrtc/base/virtualsocketserver.h" 21 22using cricket::ServerAddresses; 23using rtc::SocketAddress; 24 25static const SocketAddress kLocalAddr("127.0.0.1", 0); 26static const SocketAddress kStunAddr1("127.0.0.1", 5000); 27static const SocketAddress kStunAddr2("127.0.0.1", 4000); 28static const SocketAddress kBadAddr("0.0.0.1", 5000); 29static const SocketAddress kStunHostnameAddr("localhost", 5000); 30static const SocketAddress kBadHostnameAddr("not-a-real-hostname", 5000); 31static const int kTimeoutMs = 10000; 32// stun prio = 100 << 24 | 30 (IPV4) << 8 | 256 - 0 33static const uint32_t kStunCandidatePriority = 1677729535; 34 35// Tests connecting a StunPort to a fake STUN server (cricket::StunServer) 36// TODO: Use a VirtualSocketServer here. We have to use a 37// PhysicalSocketServer right now since DNS is not part of SocketServer yet. 38class StunPortTest : public testing::Test, 39 public sigslot::has_slots<> { 40 public: 41 StunPortTest() 42 : pss_(new rtc::PhysicalSocketServer), 43 ss_(new rtc::VirtualSocketServer(pss_.get())), 44 ss_scope_(ss_.get()), 45 network_("unittest", "unittest", rtc::IPAddress(INADDR_ANY), 32), 46 socket_factory_(rtc::Thread::Current()), 47 stun_server_1_(cricket::TestStunServer::Create( 48 rtc::Thread::Current(), kStunAddr1)), 49 stun_server_2_(cricket::TestStunServer::Create( 50 rtc::Thread::Current(), kStunAddr2)), 51 done_(false), error_(false), stun_keepalive_delay_(0) { 52 } 53 54 const cricket::Port* port() const { return stun_port_.get(); } 55 bool done() const { return done_; } 56 bool error() const { return error_; } 57 58 void CreateStunPort(const rtc::SocketAddress& server_addr) { 59 ServerAddresses stun_servers; 60 stun_servers.insert(server_addr); 61 CreateStunPort(stun_servers); 62 } 63 64 void CreateStunPort(const ServerAddresses& stun_servers) { 65 stun_port_.reset(cricket::StunPort::Create( 66 rtc::Thread::Current(), &socket_factory_, &network_, 67 kLocalAddr.ipaddr(), 0, 0, rtc::CreateRandomString(16), 68 rtc::CreateRandomString(22), stun_servers, std::string())); 69 stun_port_->set_stun_keepalive_delay(stun_keepalive_delay_); 70 stun_port_->SignalPortComplete.connect(this, 71 &StunPortTest::OnPortComplete); 72 stun_port_->SignalPortError.connect(this, 73 &StunPortTest::OnPortError); 74 } 75 76 void CreateSharedStunPort(const rtc::SocketAddress& server_addr) { 77 socket_.reset(socket_factory_.CreateUdpSocket( 78 rtc::SocketAddress(kLocalAddr.ipaddr(), 0), 0, 0)); 79 ASSERT_TRUE(socket_ != NULL); 80 socket_->SignalReadPacket.connect(this, &StunPortTest::OnReadPacket); 81 stun_port_.reset(cricket::UDPPort::Create( 82 rtc::Thread::Current(), &socket_factory_, 83 &network_, socket_.get(), 84 rtc::CreateRandomString(16), rtc::CreateRandomString(22), 85 std::string(), false)); 86 ASSERT_TRUE(stun_port_ != NULL); 87 ServerAddresses stun_servers; 88 stun_servers.insert(server_addr); 89 stun_port_->set_server_addresses(stun_servers); 90 stun_port_->SignalPortComplete.connect(this, 91 &StunPortTest::OnPortComplete); 92 stun_port_->SignalPortError.connect(this, 93 &StunPortTest::OnPortError); 94 } 95 96 void PrepareAddress() { 97 stun_port_->PrepareAddress(); 98 } 99 100 void OnReadPacket(rtc::AsyncPacketSocket* socket, const char* data, 101 size_t size, const rtc::SocketAddress& remote_addr, 102 const rtc::PacketTime& packet_time) { 103 stun_port_->HandleIncomingPacket( 104 socket, data, size, remote_addr, rtc::PacketTime()); 105 } 106 107 void SendData(const char* data, size_t len) { 108 stun_port_->HandleIncomingPacket( 109 socket_.get(), data, len, rtc::SocketAddress("22.22.22.22", 0), 110 rtc::PacketTime()); 111 } 112 113 protected: 114 static void SetUpTestCase() { 115 // Ensure the RNG is inited. 116 rtc::InitRandom(NULL, 0); 117 118 } 119 120 void OnPortComplete(cricket::Port* port) { 121 ASSERT_FALSE(done_); 122 done_ = true; 123 error_ = false; 124 } 125 void OnPortError(cricket::Port* port) { 126 done_ = true; 127 error_ = true; 128 } 129 void SetKeepaliveDelay(int delay) { 130 stun_keepalive_delay_ = delay; 131 } 132 133 cricket::TestStunServer* stun_server_1() { 134 return stun_server_1_.get(); 135 } 136 cricket::TestStunServer* stun_server_2() { 137 return stun_server_2_.get(); 138 } 139 140 private: 141 rtc::scoped_ptr<rtc::PhysicalSocketServer> pss_; 142 rtc::scoped_ptr<rtc::VirtualSocketServer> ss_; 143 rtc::SocketServerScope ss_scope_; 144 rtc::Network network_; 145 rtc::BasicPacketSocketFactory socket_factory_; 146 rtc::scoped_ptr<cricket::UDPPort> stun_port_; 147 rtc::scoped_ptr<cricket::TestStunServer> stun_server_1_; 148 rtc::scoped_ptr<cricket::TestStunServer> stun_server_2_; 149 rtc::scoped_ptr<rtc::AsyncPacketSocket> socket_; 150 bool done_; 151 bool error_; 152 int stun_keepalive_delay_; 153}; 154 155// Test that we can create a STUN port 156TEST_F(StunPortTest, TestBasic) { 157 CreateStunPort(kStunAddr1); 158 EXPECT_EQ("stun", port()->Type()); 159 EXPECT_EQ(0U, port()->Candidates().size()); 160} 161 162// Test that we can get an address from a STUN server. 163TEST_F(StunPortTest, TestPrepareAddress) { 164 CreateStunPort(kStunAddr1); 165 PrepareAddress(); 166 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 167 ASSERT_EQ(1U, port()->Candidates().size()); 168 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address())); 169 170 // TODO: Add IPv6 tests here, once either physicalsocketserver supports 171 // IPv6, or this test is changed to use VirtualSocketServer. 172} 173 174// Test that we fail properly if we can't get an address. 175TEST_F(StunPortTest, TestPrepareAddressFail) { 176 CreateStunPort(kBadAddr); 177 PrepareAddress(); 178 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 179 EXPECT_TRUE(error()); 180 EXPECT_EQ(0U, port()->Candidates().size()); 181} 182 183// Test that we can get an address from a STUN server specified by a hostname. 184TEST_F(StunPortTest, TestPrepareAddressHostname) { 185 CreateStunPort(kStunHostnameAddr); 186 PrepareAddress(); 187 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 188 ASSERT_EQ(1U, port()->Candidates().size()); 189 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address())); 190 EXPECT_EQ(kStunCandidatePriority, port()->Candidates()[0].priority()); 191} 192 193// Test that we handle hostname lookup failures properly. 194TEST_F(StunPortTest, TestPrepareAddressHostnameFail) { 195 CreateStunPort(kBadHostnameAddr); 196 PrepareAddress(); 197 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 198 EXPECT_TRUE(error()); 199 EXPECT_EQ(0U, port()->Candidates().size()); 200} 201 202// This test verifies keepalive response messages don't result in 203// additional candidate generation. 204TEST_F(StunPortTest, TestKeepAliveResponse) { 205 SetKeepaliveDelay(500); // 500ms of keepalive delay. 206 CreateStunPort(kStunHostnameAddr); 207 PrepareAddress(); 208 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 209 ASSERT_EQ(1U, port()->Candidates().size()); 210 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address())); 211 // Waiting for 1 seond, which will allow us to process 212 // response for keepalive binding request. 500 ms is the keepalive delay. 213 rtc::Thread::Current()->ProcessMessages(1000); 214 ASSERT_EQ(1U, port()->Candidates().size()); 215} 216 217// Test that a local candidate can be generated using a shared socket. 218TEST_F(StunPortTest, TestSharedSocketPrepareAddress) { 219 CreateSharedStunPort(kStunAddr1); 220 PrepareAddress(); 221 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 222 ASSERT_EQ(1U, port()->Candidates().size()); 223 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address())); 224} 225 226// Test that we still a get a local candidate with invalid stun server hostname. 227// Also verifing that UDPPort can receive packets when stun address can't be 228// resolved. 229TEST_F(StunPortTest, TestSharedSocketPrepareAddressInvalidHostname) { 230 CreateSharedStunPort(kBadHostnameAddr); 231 PrepareAddress(); 232 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 233 ASSERT_EQ(1U, port()->Candidates().size()); 234 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address())); 235 236 // Send data to port after it's ready. This is to make sure, UDP port can 237 // handle data with unresolved stun server address. 238 std::string data = "some random data, sending to cricket::Port."; 239 SendData(data.c_str(), data.length()); 240 // No crash is success. 241} 242 243// Test that the same address is added only once if two STUN servers are in use. 244TEST_F(StunPortTest, TestNoDuplicatedAddressWithTwoStunServers) { 245 ServerAddresses stun_servers; 246 stun_servers.insert(kStunAddr1); 247 stun_servers.insert(kStunAddr2); 248 CreateStunPort(stun_servers); 249 EXPECT_EQ("stun", port()->Type()); 250 PrepareAddress(); 251 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 252 EXPECT_EQ(1U, port()->Candidates().size()); 253 EXPECT_EQ(port()->Candidates()[0].relay_protocol(), ""); 254} 255 256// Test that candidates can be allocated for multiple STUN servers, one of which 257// is not reachable. 258TEST_F(StunPortTest, TestMultipleStunServersWithBadServer) { 259 ServerAddresses stun_servers; 260 stun_servers.insert(kStunAddr1); 261 stun_servers.insert(kBadAddr); 262 CreateStunPort(stun_servers); 263 EXPECT_EQ("stun", port()->Type()); 264 PrepareAddress(); 265 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 266 EXPECT_EQ(1U, port()->Candidates().size()); 267} 268 269// Test that two candidates are allocated if the two STUN servers return 270// different mapped addresses. 271TEST_F(StunPortTest, TestTwoCandidatesWithTwoStunServersAcrossNat) { 272 const SocketAddress kStunMappedAddr1("77.77.77.77", 0); 273 const SocketAddress kStunMappedAddr2("88.77.77.77", 0); 274 stun_server_1()->set_fake_stun_addr(kStunMappedAddr1); 275 stun_server_2()->set_fake_stun_addr(kStunMappedAddr2); 276 277 ServerAddresses stun_servers; 278 stun_servers.insert(kStunAddr1); 279 stun_servers.insert(kStunAddr2); 280 CreateStunPort(stun_servers); 281 EXPECT_EQ("stun", port()->Type()); 282 PrepareAddress(); 283 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 284 EXPECT_EQ(2U, port()->Candidates().size()); 285 EXPECT_EQ(port()->Candidates()[0].relay_protocol(), ""); 286 EXPECT_EQ(port()->Candidates()[1].relay_protocol(), ""); 287} 288