Home | History | Annotate | Download | only in base
      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