Add support of multiple STUN servers in UDPPort.

Now UDPPort signals PortComplete or PortError when the Bind requests for all STUN servers are responded or failed. If any STUN bind is successful, PortComplete is signaled; otherwise, PortError is signaled.

I discovered a bug in SocketAddress while working on this. It didn't consider two addresses unequal if they have unresolved IP and different hosts. It's fixed now.

BUG=3310
R=mallinath@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/13879004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6707 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
jiayl@webrtc.org
2014-07-16 20:55:31 +00:00
parent 2e3c97ddf5
commit 46fb331bc5
15 changed files with 386 additions and 149 deletions

View File

@@ -30,15 +30,18 @@
#include "talk/base/physicalsocketserver.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/socketaddress.h"
#include "talk/base/ssladapter.h"
#include "talk/base/virtualsocketserver.h"
#include "talk/p2p/base/basicpacketsocketfactory.h"
#include "talk/p2p/base/stunport.h"
#include "talk/p2p/base/teststunserver.h"
using cricket::ServerAddresses;
using talk_base::SocketAddress;
static const SocketAddress kLocalAddr("127.0.0.1", 0);
static const SocketAddress kStunAddr("127.0.0.1", 5000);
static const SocketAddress kStunAddr1("127.0.0.1", 5000);
static const SocketAddress kStunAddr2("127.0.0.1", 4000);
static const SocketAddress kBadAddr("0.0.0.1", 5000);
static const SocketAddress kStunHostnameAddr("localhost", 5000);
static const SocketAddress kBadHostnameAddr("not-a-real-hostname", 5000);
@@ -58,8 +61,10 @@ class StunPortTest : public testing::Test,
ss_scope_(ss_.get()),
network_("unittest", "unittest", talk_base::IPAddress(INADDR_ANY), 32),
socket_factory_(talk_base::Thread::Current()),
stun_server_(new cricket::TestStunServer(
talk_base::Thread::Current(), kStunAddr)),
stun_server_1_(new cricket::TestStunServer(
talk_base::Thread::Current(), kStunAddr1)),
stun_server_2_(new cricket::TestStunServer(
talk_base::Thread::Current(), kStunAddr2)),
done_(false), error_(false), stun_keepalive_delay_(0) {
}
@@ -68,10 +73,16 @@ class StunPortTest : public testing::Test,
bool error() const { return error_; }
void CreateStunPort(const talk_base::SocketAddress& server_addr) {
ServerAddresses stun_servers;
stun_servers.insert(server_addr);
CreateStunPort(stun_servers);
}
void CreateStunPort(const ServerAddresses& stun_servers) {
stun_port_.reset(cricket::StunPort::Create(
talk_base::Thread::Current(), &socket_factory_, &network_,
kLocalAddr.ipaddr(), 0, 0, talk_base::CreateRandomString(16),
talk_base::CreateRandomString(22), server_addr));
talk_base::CreateRandomString(22), stun_servers));
stun_port_->set_stun_keepalive_delay(stun_keepalive_delay_);
stun_port_->SignalPortComplete.connect(this,
&StunPortTest::OnPortComplete);
@@ -89,7 +100,9 @@ class StunPortTest : public testing::Test,
&network_, socket_.get(),
talk_base::CreateRandomString(16), talk_base::CreateRandomString(22)));
ASSERT_TRUE(stun_port_ != NULL);
stun_port_->set_server_addr(server_addr);
ServerAddresses stun_servers;
stun_servers.insert(server_addr);
stun_port_->set_server_addresses(stun_servers);
stun_port_->SignalPortComplete.connect(this,
&StunPortTest::OnPortComplete);
stun_port_->SignalPortError.connect(this,
@@ -115,11 +128,17 @@ class StunPortTest : public testing::Test,
protected:
static void SetUpTestCase() {
talk_base::InitializeSSL();
// Ensure the RNG is inited.
talk_base::InitRandom(NULL, 0);
}
static void TearDownTestCase() {
talk_base::CleanupSSL();
}
void OnPortComplete(cricket::Port* port) {
ASSERT_FALSE(done_);
done_ = true;
error_ = false;
}
@@ -138,7 +157,8 @@ class StunPortTest : public testing::Test,
talk_base::Network network_;
talk_base::BasicPacketSocketFactory socket_factory_;
talk_base::scoped_ptr<cricket::UDPPort> stun_port_;
talk_base::scoped_ptr<cricket::TestStunServer> stun_server_;
talk_base::scoped_ptr<cricket::TestStunServer> stun_server_1_;
talk_base::scoped_ptr<cricket::TestStunServer> stun_server_2_;
talk_base::scoped_ptr<talk_base::AsyncPacketSocket> socket_;
bool done_;
bool error_;
@@ -147,14 +167,14 @@ class StunPortTest : public testing::Test,
// Test that we can create a STUN port
TEST_F(StunPortTest, TestBasic) {
CreateStunPort(kStunAddr);
CreateStunPort(kStunAddr1);
EXPECT_EQ("stun", port()->Type());
EXPECT_EQ(0U, port()->Candidates().size());
}
// Test that we can get an address from a STUN server.
TEST_F(StunPortTest, TestPrepareAddress) {
CreateStunPort(kStunAddr);
CreateStunPort(kStunAddr1);
PrepareAddress();
EXPECT_TRUE_WAIT(done(), kTimeoutMs);
ASSERT_EQ(1U, port()->Candidates().size());
@@ -209,7 +229,7 @@ TEST_F(StunPortTest, TestKeepAliveResponse) {
// Test that a local candidate can be generated using a shared socket.
TEST_F(StunPortTest, TestSharedSocketPrepareAddress) {
CreateSharedStunPort(kStunAddr);
CreateSharedStunPort(kStunAddr1);
PrepareAddress();
EXPECT_TRUE_WAIT(done(), kTimeoutMs);
ASSERT_EQ(1U, port()->Candidates().size());
@@ -232,3 +252,28 @@ TEST_F(StunPortTest, TestSharedSocketPrepareAddressInvalidHostname) {
SendData(data.c_str(), data.length());
// No crash is success.
}
// Test that candidates can be allocated for multiple STUN servers.
TEST_F(StunPortTest, TestMultipleGoodStunServers) {
ServerAddresses stun_servers;
stun_servers.insert(kStunAddr1);
stun_servers.insert(kStunAddr2);
CreateStunPort(stun_servers);
EXPECT_EQ("stun", port()->Type());
PrepareAddress();
EXPECT_TRUE_WAIT(done(), kTimeoutMs);
EXPECT_EQ(2U, port()->Candidates().size());
}
// Test that candidates can be allocated for multiple STUN servers, one of which
// is not reachable.
TEST_F(StunPortTest, TestMultipleStunServersWithBadServer) {
ServerAddresses stun_servers;
stun_servers.insert(kStunAddr1);
stun_servers.insert(kBadAddr);
CreateStunPort(stun_servers);
EXPECT_EQ("stun", port()->Type());
PrepareAddress();
EXPECT_TRUE_WAIT(done(), kTimeoutMs);
EXPECT_EQ(1U, port()->Candidates().size());
}