| Index: webrtc/p2p/base/tcpport_unittest.cc
|
| diff --git a/webrtc/p2p/base/tcpport_unittest.cc b/webrtc/p2p/base/tcpport_unittest.cc
|
| index 0f7bd1f79dab9881db2a71cb3ff548567d0d15e1..884488efc34aaa19ac57a6bae76497523a2d209a 100644
|
| --- a/webrtc/p2p/base/tcpport_unittest.cc
|
| +++ b/webrtc/p2p/base/tcpport_unittest.cc
|
| @@ -8,6 +8,7 @@
|
| * be found in the AUTHORS file in the root of the source tree.
|
| */
|
|
|
| +#include <list>
|
| #include <memory>
|
|
|
| #include "webrtc/p2p/base/basicpacketsocketfactory.h"
|
| @@ -24,61 +25,134 @@ using cricket::ICE_UFRAG_LENGTH;
|
| using cricket::ICE_PWD_LENGTH;
|
|
|
| static int kTimeout = 1000;
|
| -static const SocketAddress kLocalAddr("11.11.11.11", 1);
|
| -static const SocketAddress kRemoteAddr("22.22.22.22", 2);
|
| +static const SocketAddress kLocalAddr("11.11.11.11", 0);
|
| +static const SocketAddress kAlternateLocalAddr("1.2.3.4", 0);
|
| +static const SocketAddress kRemoteAddr("22.22.22.22", 0);
|
| +
|
| +class ConnectionObserver : public sigslot::has_slots<> {
|
| + public:
|
| + ConnectionObserver(Connection* conn) {
|
| + conn->SignalDestroyed.connect(this, &ConnectionObserver::OnDestroyed);
|
| + }
|
| +
|
| + bool connection_destroyed() { return connection_destroyed_; }
|
| +
|
| + private:
|
| + void OnDestroyed(Connection*) { connection_destroyed_ = true; }
|
| +
|
| + bool connection_destroyed_ = false;
|
| +};
|
|
|
| class TCPPortTest : public testing::Test, public sigslot::has_slots<> {
|
| public:
|
| TCPPortTest()
|
| : ss_(new rtc::VirtualSocketServer()),
|
| main_(ss_.get()),
|
| - network_("unittest", "unittest", rtc::IPAddress(INADDR_ANY), 32),
|
| socket_factory_(rtc::Thread::Current()),
|
| username_(rtc::CreateRandomString(ICE_UFRAG_LENGTH)),
|
| password_(rtc::CreateRandomString(ICE_PWD_LENGTH)) {
|
| - network_.AddIP(rtc::IPAddress(INADDR_ANY));
|
| }
|
|
|
| - void ConnectSignalSocketCreated() {
|
| - ss_->SignalSocketCreated.connect(this, &TCPPortTest::OnSocketCreated);
|
| + rtc::Network* MakeNetwork(const SocketAddress& addr) {
|
| + networks_.emplace_back("unittest", "unittest", addr.ipaddr(), 32);
|
| + networks_.back().AddIP(addr.ipaddr());
|
| + return &networks_.back();
|
| }
|
|
|
| - void OnSocketCreated(rtc::VirtualSocket* socket) {
|
| - LOG(LS_INFO) << "socket created ";
|
| - socket->SignalAddressReady.connect(
|
| - this, &TCPPortTest::SetLocalhostAsAlternativeLocalAddress);
|
| + std::unique_ptr<TCPPort> CreateTCPPort(const SocketAddress& addr) {
|
| + return std::unique_ptr<TCPPort>(
|
| + TCPPort::Create(&main_, &socket_factory_, MakeNetwork(addr), 0, 0,
|
| + username_, password_, true));
|
| }
|
|
|
| - void SetLocalhostAsAlternativeLocalAddress(rtc::VirtualSocket* socket,
|
| - const SocketAddress& address) {
|
| - SocketAddress local_address("127.0.0.1", 2000);
|
| - socket->SetAlternativeLocalAddress(local_address);
|
| - }
|
| -
|
| - TCPPort* CreateTCPPort(const SocketAddress& addr) {
|
| - return TCPPort::Create(&main_, &socket_factory_, &network_, addr.ipaddr(),
|
| - 0, 0, username_, password_, true);
|
| + std::unique_ptr<TCPPort> CreateTCPPort(rtc::Network* network) {
|
| + return std::unique_ptr<TCPPort>(TCPPort::Create(
|
| + &main_, &socket_factory_, network, 0, 0, username_, password_, true));
|
| }
|
|
|
| protected:
|
| + // When a "create port" helper method is called with an IP, we create a
|
| + // Network with that IP and add it to this list. Using a list instead of a
|
| + // vector so that when it grows, pointers aren't invalidated.
|
| + std::list<rtc::Network> networks_;
|
| std::unique_ptr<rtc::VirtualSocketServer> ss_;
|
| rtc::AutoSocketServerThread main_;
|
| - rtc::Network network_;
|
| rtc::BasicPacketSocketFactory socket_factory_;
|
| std::string username_;
|
| std::string password_;
|
| };
|
|
|
| TEST_F(TCPPortTest, TestTCPPortWithLocalhostAddress) {
|
| - std::unique_ptr<TCPPort> lport(CreateTCPPort(kLocalAddr));
|
| - std::unique_ptr<TCPPort> rport(CreateTCPPort(kRemoteAddr));
|
| - lport->PrepareAddress();
|
| - rport->PrepareAddress();
|
| - // Start to listen to new socket creation event.
|
| - ConnectSignalSocketCreated();
|
| - Connection* conn =
|
| - lport->CreateConnection(rport->Candidates()[0], Port::ORIGIN_MESSAGE);
|
| + SocketAddress local_address("127.0.0.1", 0);
|
| + // After calling this, when TCPPort attempts to get a socket bound to
|
| + // kLocalAddr, it will end up using localhost instead.
|
| + ss_->SetAlternativeLocalAddress(kLocalAddr.ipaddr(), local_address.ipaddr());
|
| + auto local_port = CreateTCPPort(kLocalAddr);
|
| + auto remote_port = CreateTCPPort(kRemoteAddr);
|
| + local_port->PrepareAddress();
|
| + remote_port->PrepareAddress();
|
| + Connection* conn = local_port->CreateConnection(remote_port->Candidates()[0],
|
| + Port::ORIGIN_MESSAGE);
|
| + EXPECT_TRUE_WAIT(conn->connected(), kTimeout);
|
| + // Verify that the socket actually used localhost, otherwise this test isn't
|
| + // doing what it meant to.
|
| + ASSERT_EQ(local_address.ipaddr(),
|
| + local_port->Candidates()[0].address().ipaddr());
|
| +}
|
| +
|
| +// If the address the socket ends up bound to does not match any address of the
|
| +// TCPPort's Network, then the socket should be discarded and no candidates
|
| +// should be signaled. In the context of ICE, where one TCPPort is created for
|
| +// each Network, when this happens it's likely that the unexpected address is
|
| +// associated with some other Network, which another TCPPort is already
|
| +// covering.
|
| +TEST_F(TCPPortTest, TCPPortDiscardedIfBoundAddressDoesNotMatchNetwork) {
|
| + // Sockets bound to kLocalAddr will actually end up with kAlternateLocalAddr.
|
| + ss_->SetAlternativeLocalAddress(kLocalAddr.ipaddr(),
|
| + kAlternateLocalAddr.ipaddr());
|
| +
|
| + // Create ports (local_port is the one whose IP will end up reassigned).
|
| + auto local_port = CreateTCPPort(kLocalAddr);
|
| + auto remote_port = CreateTCPPort(kRemoteAddr);
|
| + local_port->PrepareAddress();
|
| + remote_port->PrepareAddress();
|
| +
|
| + // Tell port to create a connection; it should be destroyed when it's
|
| + // realized that it's using an unexpected address.
|
| + Connection* conn = local_port->CreateConnection(remote_port->Candidates()[0],
|
| + Port::ORIGIN_MESSAGE);
|
| + ConnectionObserver observer(conn);
|
| + EXPECT_TRUE_WAIT(observer.connection_destroyed(), kTimeout);
|
| +}
|
| +
|
| +// A caveat for the above logic: if the socket ends up bound to one of the IPs
|
| +// associated with the Network, just not the "best" one, this is ok.
|
| +TEST_F(TCPPortTest, TCPPortNotDiscardedIfNotBoundToBestIP) {
|
| + // Sockets bound to kLocalAddr will actually end up with kAlternateLocalAddr.
|
| + ss_->SetAlternativeLocalAddress(kLocalAddr.ipaddr(),
|
| + kAlternateLocalAddr.ipaddr());
|
| +
|
| + // Set up a network with kLocalAddr1 as the "best" IP, and kAlternateLocalAddr
|
| + // as an alternate.
|
| + rtc::Network* network = MakeNetwork(kLocalAddr);
|
| + network->AddIP(kAlternateLocalAddr.ipaddr());
|
| + ASSERT_EQ(kLocalAddr.ipaddr(), network->GetBestIP());
|
| +
|
| + // Create ports (using our special 2-IP Network for local_port).
|
| + auto local_port = CreateTCPPort(network);
|
| + auto remote_port = CreateTCPPort(kRemoteAddr);
|
| + local_port->PrepareAddress();
|
| + remote_port->PrepareAddress();
|
| +
|
| + // Expect connection to succeed.
|
| + Connection* conn = local_port->CreateConnection(remote_port->Candidates()[0],
|
| + Port::ORIGIN_MESSAGE);
|
| EXPECT_TRUE_WAIT(conn->connected(), kTimeout);
|
| +
|
| + // Verify that the socket actually used the alternate address, otherwise this
|
| + // test isn't doing what it meant to.
|
| + ASSERT_EQ(kAlternateLocalAddr.ipaddr(),
|
| + local_port->Candidates()[0].address().ipaddr());
|
| }
|
|
|
| class SentPacketCounter : public sigslot::has_slots<> {
|
|
|