| Index: webrtc/p2p/base/p2ptransportchannel_unittest.cc
|
| diff --git a/webrtc/p2p/base/p2ptransportchannel_unittest.cc b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
|
| index 68543a5f39ed3af006541bfdcdd747c84a2d5df9..1b0ac6f40c55aa2df681e3d8212025d655d01aae 100644
|
| --- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc
|
| +++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
|
| @@ -388,6 +388,7 @@ class P2PTransportChannelTestBase : public testing::Test,
|
| }
|
| void RemoveAddress(int endpoint, const SocketAddress& addr) {
|
| GetEndpoint(endpoint)->network_manager_.RemoveInterface(addr);
|
| + fw()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, addr);
|
| }
|
| void SetProxy(int endpoint, rtc::ProxyType type) {
|
| rtc::ProxyInfo info;
|
| @@ -1583,6 +1584,37 @@ TEST_F(P2PTransportChannelSameNatTest, TestConesBehindSameCone) {
|
| // In the future we will try different RTTs and configs for the different
|
| // interfaces, so that we can simulate a user with Ethernet and VPN networks.
|
| class P2PTransportChannelMultihomedTest : public P2PTransportChannelTestBase {
|
| + public:
|
| + const cricket::Connection* GetConnectionWithRemoteAddress(
|
| + cricket::P2PTransportChannel* channel,
|
| + const SocketAddress& address) {
|
| + for (cricket::Connection* conn : channel->connections()) {
|
| + if (conn->remote_candidate().address().EqualIPs(address)) {
|
| + return conn;
|
| + }
|
| + }
|
| + return nullptr;
|
| + }
|
| +
|
| + const cricket::Connection* GetConnectionWithLocalAddress(
|
| + cricket::P2PTransportChannel* channel,
|
| + const SocketAddress& address) {
|
| + for (cricket::Connection* conn : channel->connections()) {
|
| + if (conn->local_candidate().address().EqualIPs(address)) {
|
| + return conn;
|
| + }
|
| + }
|
| + return nullptr;
|
| + }
|
| +
|
| + void DestroyAllButBestConnection(cricket::P2PTransportChannel* channel) {
|
| + const cricket::Connection* best_connection = channel->best_connection();
|
| + for (cricket::Connection* conn : channel->connections()) {
|
| + if (conn != best_connection) {
|
| + conn->Destroy();
|
| + }
|
| + }
|
| + }
|
| };
|
|
|
| // Test that we can establish connectivity when both peers are multihomed.
|
| @@ -1729,6 +1761,7 @@ TEST_F(P2PTransportChannelMultihomedTest, TestPreferWifiToWifiConnection) {
|
| LocalCandidate(ep2_ch1())->address().EqualIPs(wifi[1]) &&
|
| RemoteCandidate(ep2_ch1())->address().EqualIPs(wifi[0]),
|
| 1000);
|
| + DestroyChannels();
|
| }
|
|
|
| // Tests that a Wifi-Cellular connection has higher precedence than
|
| @@ -1759,6 +1792,7 @@ TEST_F(P2PTransportChannelMultihomedTest, TestPreferWifiOverCellularNetwork) {
|
| EXPECT_TRUE_WAIT(ep2_ch1()->best_connection() &&
|
| LocalCandidate(ep2_ch1())->address().EqualIPs(wifi[1]),
|
| 1000);
|
| + DestroyChannels();
|
| }
|
|
|
| // Test that the backup connection is pinged at a rate no faster than
|
| @@ -1796,6 +1830,8 @@ TEST_F(P2PTransportChannelMultihomedTest, TestPingBackupConnectionRate) {
|
| backup_conn->last_ping_response_received() - last_ping_response_ms;
|
| LOG(LS_INFO) << "Time elapsed: " << time_elapsed;
|
| EXPECT_GE(time_elapsed, backup_ping_interval);
|
| +
|
| + DestroyChannels();
|
| }
|
|
|
| TEST_F(P2PTransportChannelMultihomedTest, TestGetState) {
|
| @@ -1810,6 +1846,8 @@ TEST_F(P2PTransportChannelMultihomedTest, TestGetState) {
|
| ep1_ch1()->GetState(), 1000);
|
| EXPECT_EQ_WAIT(cricket::TransportChannelState::STATE_COMPLETED,
|
| ep2_ch1()->GetState(), 1000);
|
| +
|
| + DestroyChannels();
|
| }
|
|
|
| // Tests that when a network interface becomes inactive, if and only if
|
| @@ -1848,17 +1886,58 @@ TEST_F(P2PTransportChannelMultihomedTest, TestNetworkBecomesInactive) {
|
| rtc::Thread::Current()->ProcessMessages(500);
|
| EXPECT_EQ(num_ports, ep2_ch1()->ports().size());
|
| EXPECT_EQ(num_remote_candidates, ep1_ch1()->remote_candidates().size());
|
| +
|
| + DestroyChannels();
|
| }
|
|
|
| -/*
|
| +// Tests that continual gathering will create new connections when a new
|
| +// interface is added.
|
| +TEST_F(P2PTransportChannelMultihomedTest,
|
| + TestContinualGatheringOnNewInterface) {
|
| + auto& wifi = kAlternateAddrs;
|
| + auto& cellular = kPublicAddrs;
|
| + AddAddress(0, wifi[0], "test_wifi0", rtc::ADAPTER_TYPE_WIFI);
|
| + AddAddress(1, cellular[1], "test_cell1", rtc::ADAPTER_TYPE_CELLULAR);
|
| + CreateChannels(1);
|
| + // Enable continual gathering.
|
| + ep1_ch1()->SetIceConfig(CreateIceConfig(1000, true));
|
| + ep2_ch1()->SetIceConfig(CreateIceConfig(1000, true));
|
| + SetAllocatorFlags(0, kOnlyLocalPorts);
|
| + SetAllocatorFlags(1, kOnlyLocalPorts);
|
| + EXPECT_TRUE_WAIT_MARGIN(ep1_ch1()->receiving() && ep1_ch1()->writable() &&
|
| + ep2_ch1()->receiving() && ep2_ch1()->writable(),
|
| + kDefaultTimeout, kDefaultTimeout);
|
| +
|
| + // Add a new wifi interface on end point 2. We should expect a new connection
|
| + // to be created and the new one will be the best connection.
|
| + AddAddress(1, wifi[1], "test_wifi1", rtc::ADAPTER_TYPE_WIFI);
|
| + const cricket::Connection* conn;
|
| + EXPECT_TRUE_WAIT((conn = ep1_ch1()->best_connection()) != nullptr &&
|
| + conn->remote_candidate().address().EqualIPs(wifi[1]),
|
| + kDefaultTimeout);
|
| + EXPECT_TRUE_WAIT((conn = ep2_ch1()->best_connection()) != nullptr &&
|
| + conn->local_candidate().address().EqualIPs(wifi[1]),
|
| + kDefaultTimeout);
|
| +
|
| + // Add a new cellular interface on end point 1, we should expect a new
|
| + // backup connection created using this new interface.
|
| + AddAddress(0, cellular[0], "test_cellular0", rtc::ADAPTER_TYPE_CELLULAR);
|
| + EXPECT_TRUE_WAIT(
|
| + ep1_ch1()->GetState() == cricket::STATE_COMPLETED &&
|
| + (conn = GetConnectionWithLocalAddress(ep1_ch1(), cellular[0])) &&
|
| + conn != ep1_ch1()->best_connection() && conn->writable(),
|
| + kDefaultTimeout);
|
| + EXPECT_TRUE_WAIT(
|
| + ep2_ch1()->GetState() == cricket::STATE_COMPLETED &&
|
| + (conn = GetConnectionWithRemoteAddress(ep2_ch1(), cellular[0])) &&
|
| + conn != ep2_ch1()->best_connection() && conn->receiving(),
|
| + kDefaultTimeout);
|
|
|
| -TODO(pthatcher): Once have a way to handle network interfaces changes
|
| -without signalling an ICE restart, put a test like this back. In the
|
| -mean time, this test only worked for GICE. With ICE, it's currently
|
| -not possible without an ICE restart.
|
| + DestroyChannels();
|
| +}
|
|
|
| -// Test that we can switch links in a coordinated fashion.
|
| -TEST_F(P2PTransportChannelMultihomedTest, TestDrain) {
|
| +// Tests that we can switch links via continual gathering.
|
| +TEST_F(P2PTransportChannelMultihomedTest, TestContinualGatheringSwitchLinks) {
|
| AddAddress(0, kPublicAddrs[0]);
|
| AddAddress(1, kPublicAddrs[1]);
|
| // Use only local ports for simplicity.
|
| @@ -1867,35 +1946,119 @@ TEST_F(P2PTransportChannelMultihomedTest, TestDrain) {
|
|
|
| // Create channels and let them go writable, as usual.
|
| CreateChannels(1);
|
| - EXPECT_TRUE_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() &&
|
| - ep2_ch1()->receiving() && ep2_ch1()->writable(),
|
| - 1000);
|
| + // Enable continual gathering.
|
| + ep1_ch1()->SetIceConfig(CreateIceConfig(1000, true));
|
| + ep2_ch1()->SetIceConfig(CreateIceConfig(1000, true));
|
| + EXPECT_TRUE_WAIT_MARGIN(ep1_ch1()->receiving() && ep1_ch1()->writable() &&
|
| + ep2_ch1()->receiving() && ep2_ch1()->writable(),
|
| + kDefaultTimeout, kDefaultTimeout);
|
| EXPECT_TRUE(
|
| ep1_ch1()->best_connection() && ep2_ch1()->best_connection() &&
|
| LocalCandidate(ep1_ch1())->address().EqualIPs(kPublicAddrs[0]) &&
|
| RemoteCandidate(ep1_ch1())->address().EqualIPs(kPublicAddrs[1]));
|
|
|
| -
|
| - // Remove the public interface, add the alternate interface, and allocate
|
| - // a new generation of candidates for the new interface (via
|
| - // MaybeStartGathering()).
|
| + // Add the new address first and then remove the other one.
|
| LOG(LS_INFO) << "Draining...";
|
| AddAddress(1, kAlternateAddrs[1]);
|
| RemoveAddress(1, kPublicAddrs[1]);
|
| - ep2_ch1()->MaybeStartGathering();
|
| -
|
| - // We should switch over to use the alternate address after
|
| - // an exchange of pings.
|
| + // We should switch to use the alternate address after an exchange of pings.
|
| EXPECT_TRUE_WAIT(
|
| ep1_ch1()->best_connection() && ep2_ch1()->best_connection() &&
|
| LocalCandidate(ep1_ch1())->address().EqualIPs(kPublicAddrs[0]) &&
|
| RemoteCandidate(ep1_ch1())->address().EqualIPs(kAlternateAddrs[1]),
|
| 3000);
|
|
|
| + // Remove one address first and then add another address.
|
| + LOG(LS_INFO) << "Draining again...";
|
| + RemoveAddress(1, kAlternateAddrs[1]);
|
| + AddAddress(1, kAlternateAddrs[0]);
|
| + EXPECT_TRUE_WAIT(
|
| + ep1_ch1()->best_connection() && ep2_ch1()->best_connection() &&
|
| + LocalCandidate(ep1_ch1())->address().EqualIPs(kPublicAddrs[0]) &&
|
| + RemoteCandidate(ep1_ch1())->address().EqualIPs(kAlternateAddrs[0]),
|
| + 3000);
|
| +
|
| + DestroyChannels();
|
| +}
|
| +
|
| +// Tests that if the backup connections are lost and then the interface with the
|
| +// selected connection is gone, continual gathering will restore the
|
| +// connectivity.
|
| +TEST_F(P2PTransportChannelMultihomedTest,
|
| + TestBackupConnectionLostThenContinualGathering) {
|
| + auto& wifi = kAlternateAddrs;
|
| + auto& cellular = kPublicAddrs;
|
| + AddAddress(0, wifi[0], "test_wifi0", rtc::ADAPTER_TYPE_WIFI);
|
| + AddAddress(0, cellular[0], "test_cell0", rtc::ADAPTER_TYPE_CELLULAR);
|
| + AddAddress(1, wifi[1], "test_wifi1", rtc::ADAPTER_TYPE_WIFI);
|
| + AddAddress(1, cellular[1], "test_cell1", rtc::ADAPTER_TYPE_CELLULAR);
|
| + // Use only local ports for simplicity.
|
| + SetAllocatorFlags(0, kOnlyLocalPorts);
|
| + SetAllocatorFlags(1, kOnlyLocalPorts);
|
| +
|
| + // Create channels and let them go writable, as usual.
|
| + CreateChannels(1);
|
| + // Enable continual gathering.
|
| + ep1_ch1()->SetIceConfig(CreateIceConfig(1000, true));
|
| + ep2_ch1()->SetIceConfig(CreateIceConfig(1000, true));
|
| + EXPECT_TRUE_WAIT_MARGIN(ep1_ch1()->receiving() && ep1_ch1()->writable() &&
|
| + ep2_ch1()->receiving() && ep2_ch1()->writable(),
|
| + kDefaultTimeout, kDefaultTimeout);
|
| + EXPECT_TRUE(ep1_ch1()->best_connection() && ep2_ch1()->best_connection() &&
|
| + LocalCandidate(ep1_ch1())->address().EqualIPs(wifi[0]) &&
|
| + RemoteCandidate(ep1_ch1())->address().EqualIPs(wifi[1]));
|
| +
|
| + // First destroy all backup connection.
|
| + DestroyAllButBestConnection(ep1_ch1());
|
| + // Then the interface of the best connection goes away.
|
| + RemoveAddress(0, wifi[0]);
|
| + EXPECT_TRUE_WAIT(
|
| + ep1_ch1()->best_connection() && ep2_ch1()->best_connection() &&
|
| + LocalCandidate(ep1_ch1())->address().EqualIPs(cellular[0]) &&
|
| + RemoteCandidate(ep1_ch1())->address().EqualIPs(wifi[1]),
|
| + kDefaultTimeout);
|
| +
|
| DestroyChannels();
|
| }
|
|
|
| -*/
|
| +// Tests that the backup connection will be restored after it is destroyed.
|
| +TEST_F(P2PTransportChannelMultihomedTest, TestRestoreBackupConnection) {
|
| + auto& wifi = kAlternateAddrs;
|
| + auto& cellular = kPublicAddrs;
|
| + AddAddress(0, wifi[0], "test_wifi0", rtc::ADAPTER_TYPE_WIFI);
|
| + AddAddress(0, cellular[0], "test_cell0", rtc::ADAPTER_TYPE_CELLULAR);
|
| + AddAddress(1, wifi[1], "test_wifi1", rtc::ADAPTER_TYPE_WIFI);
|
| + AddAddress(1, cellular[1], "test_cell1", rtc::ADAPTER_TYPE_CELLULAR);
|
| + // Use only local ports for simplicity.
|
| + SetAllocatorFlags(0, kOnlyLocalPorts);
|
| + SetAllocatorFlags(1, kOnlyLocalPorts);
|
| +
|
| + // Create channels and let them go writable, as usual.
|
| + CreateChannels(1);
|
| + ep1_ch1()->SetIceConfig(CreateIceConfig(1000, true));
|
| + ep2_ch1()->SetIceConfig(CreateIceConfig(1000, true));
|
| + EXPECT_TRUE_WAIT_MARGIN(ep1_ch1()->receiving() && ep1_ch1()->writable() &&
|
| + ep2_ch1()->receiving() && ep2_ch1()->writable(),
|
| + kDefaultTimeout, kDefaultTimeout);
|
| + EXPECT_TRUE(ep1_ch1()->best_connection() && ep2_ch1()->best_connection() &&
|
| + LocalCandidate(ep1_ch1())->address().EqualIPs(wifi[0]) &&
|
| + RemoteCandidate(ep1_ch1())->address().EqualIPs(wifi[1]));
|
| +
|
| + // Destroy all backup connections.
|
| + ep1_ch1()->set_check_restore_backup_connection_interval(2000);
|
| + DestroyAllButBestConnection(ep1_ch1());
|
| + // Ensure the backup connection is removed first.
|
| + EXPECT_TRUE_WAIT(
|
| + GetConnectionWithLocalAddress(ep1_ch1(), cellular[0]) == nullptr,
|
| + kDefaultTimeout);
|
| + const cricket::Connection* conn;
|
| + EXPECT_TRUE_WAIT(
|
| + (conn = GetConnectionWithLocalAddress(ep1_ch1(), cellular[0])) &&
|
| + conn != ep1_ch1()->best_connection() && conn->writable(),
|
| + 5000);
|
| +
|
| + DestroyChannels();
|
| +}
|
|
|
| // A collection of tests which tests a single P2PTransportChannel by sending
|
| // pings.
|
|
|