1 /* 2 * libjingle 3 * Copyright 2009 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 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. 15 * 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. 26 */ 27 28 #include "talk/base/gunit.h" 29 #include "talk/base/helpers.h" 30 #include "talk/base/socketaddress.h" 31 #include "talk/p2p/base/basicpacketsocketfactory.h" 32 #include "talk/p2p/base/stunport.h" 33 #include "talk/p2p/base/teststunserver.h" 34 35 using talk_base::SocketAddress; 36 37 static const SocketAddress kLocalAddr("127.0.0.1", 0); 38 static const SocketAddress kStunAddr("127.0.0.1", 5000); 39 static const SocketAddress kBadAddr("0.0.0.1", 5000); 40 static const SocketAddress kStunHostnameAddr("localhost", 5000); 41 static const SocketAddress kBadHostnameAddr("not-a-real-hostname", 5000); 42 static const int kTimeoutMs = 10000; 43 44 // Tests connecting a StunPort to a fake STUN server (cricket::StunServer) 45 // TODO: Use a VirtualSocketServer here. We have to use a 46 // PhysicalSocketServer right now since DNS is not part of SocketServer yet. 47 class StunPortTest : public testing::Test, 48 public sigslot::has_slots<> { 49 public: 50 StunPortTest() 51 : network_("unittest", "unittest", talk_base::IPAddress(INADDR_ANY), 32), 52 socket_factory_(talk_base::Thread::Current()), 53 stun_server_(new cricket::TestStunServer( 54 talk_base::Thread::Current(), kStunAddr)), 55 done_(false), error_(false), stun_keepalive_delay_(0) { 56 } 57 58 const cricket::Port* port() const { return stun_port_.get(); } 59 bool done() const { return done_; } 60 bool error() const { return error_; } 61 62 void CreateStunPort(const talk_base::SocketAddress& server_addr) { 63 stun_port_.reset(cricket::StunPort::Create( 64 talk_base::Thread::Current(), &socket_factory_, &network_, 65 kLocalAddr.ipaddr(), 0, 0, talk_base::CreateRandomString(16), 66 talk_base::CreateRandomString(22), server_addr)); 67 stun_port_->set_stun_keepalive_delay(stun_keepalive_delay_); 68 stun_port_->SignalPortComplete.connect(this, 69 &StunPortTest::OnPortComplete); 70 stun_port_->SignalPortError.connect(this, 71 &StunPortTest::OnPortError); 72 } 73 74 void PrepareAddress() { 75 stun_port_->PrepareAddress(); 76 } 77 78 protected: 79 static void SetUpTestCase() { 80 // Ensure the RNG is inited. 81 talk_base::InitRandom(NULL, 0); 82 } 83 84 void OnPortComplete(cricket::Port* port) { 85 done_ = true; 86 error_ = false; 87 } 88 void OnPortError(cricket::Port* port) { 89 done_ = true; 90 error_ = true; 91 } 92 void SetKeepaliveDelay(int delay) { 93 stun_keepalive_delay_ = delay; 94 } 95 96 private: 97 talk_base::Network network_; 98 talk_base::BasicPacketSocketFactory socket_factory_; 99 talk_base::scoped_ptr<cricket::StunPort> stun_port_; 100 talk_base::scoped_ptr<cricket::TestStunServer> stun_server_; 101 bool done_; 102 bool error_; 103 int stun_keepalive_delay_; 104 }; 105 106 // Test that we can create a STUN port 107 TEST_F(StunPortTest, TestBasic) { 108 CreateStunPort(kStunAddr); 109 EXPECT_EQ("stun", port()->Type()); 110 EXPECT_EQ(0U, port()->Candidates().size()); 111 } 112 113 // Test that we can get an address from a STUN server. 114 TEST_F(StunPortTest, TestPrepareAddress) { 115 CreateStunPort(kStunAddr); 116 PrepareAddress(); 117 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 118 ASSERT_EQ(1U, port()->Candidates().size()); 119 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address())); 120 121 // TODO: Add IPv6 tests here, once either physicalsocketserver supports 122 // IPv6, or this test is changed to use VirtualSocketServer. 123 } 124 125 // Test that we fail properly if we can't get an address. 126 TEST_F(StunPortTest, TestPrepareAddressFail) { 127 CreateStunPort(kBadAddr); 128 PrepareAddress(); 129 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 130 EXPECT_TRUE(error()); 131 EXPECT_EQ(0U, port()->Candidates().size()); 132 } 133 134 // Test that we can get an address from a STUN server specified by a hostname. 135 TEST_F(StunPortTest, TestPrepareAddressHostname) { 136 CreateStunPort(kStunHostnameAddr); 137 PrepareAddress(); 138 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 139 ASSERT_EQ(1U, port()->Candidates().size()); 140 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address())); 141 } 142 143 // Test that we handle hostname lookup failures properly. 144 TEST_F(StunPortTest, TestPrepareAddressHostnameFail) { 145 CreateStunPort(kBadHostnameAddr); 146 PrepareAddress(); 147 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 148 EXPECT_TRUE(error()); 149 EXPECT_EQ(0U, port()->Candidates().size()); 150 } 151 152 // This test verifies keepalive response messages don't result in 153 // additional candidate generation. 154 TEST_F(StunPortTest, TestKeepAliveResponse) { 155 SetKeepaliveDelay(500); // 500ms of keepalive delay. 156 CreateStunPort(kStunHostnameAddr); 157 PrepareAddress(); 158 EXPECT_TRUE_WAIT(done(), kTimeoutMs); 159 ASSERT_EQ(1U, port()->Candidates().size()); 160 EXPECT_TRUE(kLocalAddr.EqualIPs(port()->Candidates()[0].address())); 161 // Waiting for 1 seond, which will allow us to process 162 // response for keepalive binding request. 500 ms is the keepalive delay. 163 talk_base::Thread::Current()->ProcessMessages(1000); 164 ASSERT_EQ(1U, port()->Candidates().size()); 165 } 166 167