| Index: webrtc/p2p/base/p2ptransportchannel_unittest.cc
|
| diff --git a/webrtc/p2p/base/p2ptransportchannel_unittest.cc b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
|
| index d367d269d969dc1eb5270d03ddb96d143d4b44ce..313bdbd3712bfa6ceab33d67135c0a4a848ba777 100644
|
| --- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc
|
| +++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
|
| @@ -54,11 +54,13 @@ static const SocketAddress kPublicAddrs[2] =
|
| // IPv6 Addresses on the public internet.
|
| static const SocketAddress kIPv6PublicAddrs[2] = {
|
| SocketAddress("2400:4030:1:2c00:be30:abcd:efab:cdef", 0),
|
| - SocketAddress("2620:0:1000:1b03:2e41:38ff:fea6:f2a4", 0)
|
| -};
|
| + SocketAddress("2600:0:1000:1b03:2e41:38ff:fea6:f2a4", 0)};
|
| // For configuring multihomed clients.
|
| static const SocketAddress kAlternateAddrs[2] = {
|
| SocketAddress("101.101.101.101", 0), SocketAddress("202.202.202.202", 0)};
|
| +static const SocketAddress kIPv6AlternateAddrs[2] = {
|
| + SocketAddress("2401:4030:1:2c00:be30:abcd:efab:cdef", 0),
|
| + SocketAddress("2601:0:1000:1b03:2e41:38ff:fea6:f2a4", 0)};
|
| // Addresses for HTTP proxy servers.
|
| static const SocketAddress kHttpsProxyAddrs[2] =
|
| { SocketAddress("11.11.11.1", 443), SocketAddress("22.22.22.1", 443) };
|
| @@ -427,7 +429,7 @@ class P2PTransportChannelTestBase : public testing::Test,
|
| return NULL;
|
| }
|
| }
|
| - PortAllocator* GetAllocator(int endpoint) {
|
| + BasicPortAllocator* GetAllocator(int endpoint) {
|
| return GetEndpoint(endpoint)->allocator_.get();
|
| }
|
| webrtc::FakeMetricsObserver* GetMetricsObserver(int endpoint) {
|
| @@ -2062,10 +2064,10 @@ TEST_F(P2PTransportChannelSameNatTest, TestConesBehindSameCone) {
|
| // 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 Connection* GetConnectionWithRemoteAddress(
|
| + P2PTransportChannel* channel,
|
| const SocketAddress& address) {
|
| - for (cricket::Connection* conn : channel->connections()) {
|
| + for (Connection* conn : channel->connections()) {
|
| if (conn->remote_candidate().address().EqualIPs(address)) {
|
| return conn;
|
| }
|
| @@ -2073,10 +2075,9 @@ class P2PTransportChannelMultihomedTest : public P2PTransportChannelTestBase {
|
| return nullptr;
|
| }
|
|
|
| - cricket::Connection* GetConnectionWithLocalAddress(
|
| - cricket::P2PTransportChannel* channel,
|
| - const SocketAddress& address) {
|
| - for (cricket::Connection* conn : channel->connections()) {
|
| + Connection* GetConnectionWithLocalAddress(P2PTransportChannel* channel,
|
| + const SocketAddress& address) {
|
| + for (Connection* conn : channel->connections()) {
|
| if (conn->local_candidate().address().EqualIPs(address)) {
|
| return conn;
|
| }
|
| @@ -2084,10 +2085,21 @@ class P2PTransportChannelMultihomedTest : public P2PTransportChannelTestBase {
|
| return nullptr;
|
| }
|
|
|
| - void DestroyAllButBestConnection(cricket::P2PTransportChannel* channel) {
|
| - const cricket::Connection* selected_connection =
|
| - channel->selected_connection();
|
| - for (cricket::Connection* conn : channel->connections()) {
|
| + Connection* GetConnection(P2PTransportChannel* channel,
|
| + const SocketAddress& local,
|
| + const SocketAddress& remote) {
|
| + for (Connection* conn : channel->connections()) {
|
| + if (conn->local_candidate().address().EqualIPs(local) &&
|
| + conn->remote_candidate().address().EqualIPs(remote)) {
|
| + return conn;
|
| + }
|
| + }
|
| + return nullptr;
|
| + }
|
| +
|
| + void DestroyAllButBestConnection(P2PTransportChannel* channel) {
|
| + const Connection* selected_connection = channel->selected_connection();
|
| + for (Connection* conn : channel->connections()) {
|
| if (conn != selected_connection) {
|
| conn->Destroy();
|
| }
|
| @@ -2209,6 +2221,99 @@ TEST_F(P2PTransportChannelMultihomedTest, TestFailoverControllingSide) {
|
| DestroyChannels();
|
| }
|
|
|
| +// Tests that we can quickly switch links if an interface goes down when
|
| +// there are many connections.
|
| +TEST_F(P2PTransportChannelMultihomedTest, TestFailoverWithManyConnections) {
|
| + rtc::ScopedFakeClock clock;
|
| + test_turn_server()->AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP);
|
| + RelayServerConfig turn_server(RELAY_TURN);
|
| + turn_server.credentials = kRelayCredentials;
|
| + turn_server.ports.push_back(
|
| + ProtocolAddress(kTurnTcpIntAddr, PROTO_TCP, false));
|
| + GetAllocator(0)->AddTurnServer(turn_server);
|
| + GetAllocator(1)->AddTurnServer(turn_server);
|
| + // Enable IPv6
|
| + SetAllocatorFlags(0, PORTALLOCATOR_ENABLE_IPV6);
|
| + SetAllocatorFlags(1, PORTALLOCATOR_ENABLE_IPV6);
|
| + SetAllocationStepDelay(0, kMinimumStepDelay);
|
| + SetAllocationStepDelay(1, kMinimumStepDelay);
|
| +
|
| + auto& wifi = kPublicAddrs;
|
| + auto& cellular = kAlternateAddrs;
|
| + auto& wifiIpv6 = kIPv6PublicAddrs;
|
| + auto& cellularIpv6 = kIPv6AlternateAddrs;
|
| + AddAddress(0, wifi[0], "wifi0", rtc::ADAPTER_TYPE_WIFI);
|
| + AddAddress(0, wifiIpv6[0], "wifi0", rtc::ADAPTER_TYPE_WIFI);
|
| + AddAddress(0, cellular[0], "cellular0", rtc::ADAPTER_TYPE_CELLULAR);
|
| + AddAddress(0, cellularIpv6[0], "cellular0", rtc::ADAPTER_TYPE_CELLULAR);
|
| + AddAddress(1, wifi[1], "wifi1", rtc::ADAPTER_TYPE_WIFI);
|
| + AddAddress(1, wifiIpv6[1], "wifi1", rtc::ADAPTER_TYPE_WIFI);
|
| + AddAddress(1, cellular[1], "cellular1", rtc::ADAPTER_TYPE_CELLULAR);
|
| + AddAddress(1, cellularIpv6[1], "cellular1", rtc::ADAPTER_TYPE_CELLULAR);
|
| +
|
| + // Set smaller delay on the TCP TURN server so that TCP TURN candidates
|
| + // will be created in time.
|
| + virtual_socket_server()->SetDelayOnAddress(kTurnTcpIntAddr, 1);
|
| + virtual_socket_server()->SetDelayOnAddress(kTurnUdpExtAddr, 1);
|
| + virtual_socket_server()->set_delay_mean(500);
|
| + virtual_socket_server()->UpdateDelayDistribution();
|
| +
|
| + // Make the receiving timeout shorter for testing.
|
| + IceConfig config = CreateIceConfig(1000, GATHER_CONTINUALLY);
|
| + // Create channels and let them go writable, as usual.
|
| + CreateChannels(config, config, true /* ice_renomination */);
|
| + EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() &&
|
| + ep2_ch1()->receiving() &&
|
| + ep2_ch1()->writable(),
|
| + kMediumTimeout, clock);
|
| + EXPECT_TRUE_SIMULATED_WAIT(
|
| + ep1_ch1()->selected_connection() && ep2_ch1()->selected_connection() &&
|
| + LocalCandidate(ep1_ch1())->address().EqualIPs(wifiIpv6[0]) &&
|
| + RemoteCandidate(ep1_ch1())->address().EqualIPs(wifiIpv6[1]),
|
| + kMediumTimeout, clock);
|
| +
|
| + // Blackhole any traffic to or from the wifi on endpoint 1.
|
| + LOG(LS_INFO) << "Failing over...";
|
| + fw()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, wifi[0]);
|
| + fw()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, wifiIpv6[0]);
|
| +
|
| + // The selected connections may switch, so keep references to them.
|
| + const Connection* selected_connection1 = ep1_ch1()->selected_connection();
|
| + const Connection* selected_connection2 = ep2_ch1()->selected_connection();
|
| + EXPECT_TRUE_SIMULATED_WAIT(
|
| + !selected_connection1->receiving() && !selected_connection2->receiving(),
|
| + kMediumTimeout, clock);
|
| +
|
| + // Premier connections will be pinged at relatively higher rate when the
|
| + // selected connection becomes not receiving.
|
| + Connection* premier_connection1 =
|
| + GetConnection(ep1_ch1(), cellularIpv6[0], wifiIpv6[1]);
|
| + ASSERT_NE(nullptr, premier_connection1);
|
| + int64_t last_ping_sent1 = premier_connection1->last_ping_sent();
|
| + int num_pings_sent1 = premier_connection1->num_pings_sent();
|
| + EXPECT_TRUE_SIMULATED_WAIT(
|
| + num_pings_sent1 < premier_connection1->num_pings_sent(), kMediumTimeout,
|
| + clock);
|
| + int64_t ping_interval1 =
|
| + (premier_connection1->last_ping_sent() - last_ping_sent1) /
|
| + (premier_connection1->num_pings_sent() - num_pings_sent1);
|
| + constexpr int SCHEDULING_DELAY = 200;
|
| + EXPECT_LT(
|
| + ping_interval1,
|
| + WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_DELAY);
|
| +
|
| + // It should switch over to use the cellular IPv6 addr on endpoint 1 before
|
| + // it timed out on writing.
|
| + EXPECT_TRUE_SIMULATED_WAIT(
|
| + ep1_ch1()->selected_connection()->receiving() &&
|
| + ep2_ch1()->selected_connection()->receiving() &&
|
| + RemoteCandidate(ep2_ch1())->address().EqualIPs(cellularIpv6[0]) &&
|
| + LocalCandidate(ep1_ch1())->address().EqualIPs(cellularIpv6[0]),
|
| + kMediumTimeout, clock);
|
| +
|
| + DestroyChannels();
|
| +}
|
| +
|
| // Test that when the controlling side switches the selected connection,
|
| // the nomination of the selected connection on the controlled side will
|
| // increase.
|
| @@ -2625,7 +2730,7 @@ TEST_F(P2PTransportChannelMultihomedTest,
|
| // 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;
|
| + const Connection* conn;
|
| EXPECT_TRUE_WAIT((conn = ep1_ch1()->selected_connection()) != nullptr &&
|
| conn->remote_candidate().address().EqualIPs(wifi[1]),
|
| kDefaultTimeout);
|
| @@ -2637,13 +2742,13 @@ TEST_F(P2PTransportChannelMultihomedTest,
|
| // 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 &&
|
| + ep1_ch1()->GetState() == STATE_COMPLETED &&
|
| (conn = GetConnectionWithLocalAddress(ep1_ch1(), cellular[0])) !=
|
| nullptr &&
|
| conn != ep1_ch1()->selected_connection() && conn->writable(),
|
| kDefaultTimeout);
|
| EXPECT_TRUE_WAIT(
|
| - ep2_ch1()->GetState() == cricket::STATE_COMPLETED &&
|
| + ep2_ch1()->GetState() == STATE_COMPLETED &&
|
| (conn = GetConnectionWithRemoteAddress(ep2_ch1(), cellular[0])) !=
|
| nullptr &&
|
| conn != ep2_ch1()->selected_connection() && conn->receiving(),
|
| @@ -2780,7 +2885,7 @@ TEST_F(P2PTransportChannelMultihomedTest, TestRestoreBackupConnection) {
|
| EXPECT_TRUE_SIMULATED_WAIT(
|
| GetConnectionWithLocalAddress(ep1_ch1(), cellular[0]) == nullptr,
|
| kDefaultTimeout, clock);
|
| - const cricket::Connection* conn;
|
| + const Connection* conn;
|
| EXPECT_TRUE_SIMULATED_WAIT(
|
| (conn = GetConnectionWithLocalAddress(ep1_ch1(), cellular[0])) !=
|
| nullptr &&
|
| @@ -3038,9 +3143,11 @@ TEST_F(P2PTransportChannelPingTest, TestStunPingIntervals) {
|
| SIMULATED_WAIT(conn->num_pings_sent() == ping_sent_before + 1, kMediumTimeout,
|
| clock);
|
| ping_interval_ms = (clock.TimeNanos() - start) / rtc::kNumNanosecsPerMillisec;
|
| - EXPECT_GE(ping_interval_ms, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL);
|
| - EXPECT_LE(ping_interval_ms,
|
| - STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE);
|
| + EXPECT_GE(ping_interval_ms,
|
| + WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL);
|
| + EXPECT_LE(
|
| + ping_interval_ms,
|
| + WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE);
|
|
|
| // Stabilized.
|
|
|
| @@ -3054,9 +3161,11 @@ TEST_F(P2PTransportChannelPingTest, TestStunPingIntervals) {
|
| SIMULATED_WAIT(conn->num_pings_sent() == ping_sent_before + 1, kMediumTimeout,
|
| clock);
|
| ping_interval_ms = (clock.TimeNanos() - start) / rtc::kNumNanosecsPerMillisec;
|
| - EXPECT_GE(ping_interval_ms, STABLE_WRITABLE_CONNECTION_PING_INTERVAL);
|
| - EXPECT_LE(ping_interval_ms,
|
| - STABLE_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE);
|
| + EXPECT_GE(ping_interval_ms,
|
| + STRONG_AND_STABLE_WRITABLE_CONNECTION_PING_INTERVAL);
|
| + EXPECT_LE(
|
| + ping_interval_ms,
|
| + STRONG_AND_STABLE_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE);
|
|
|
| // Destabilized.
|
|
|
| @@ -3077,15 +3186,17 @@ TEST_F(P2PTransportChannelPingTest, TestStunPingIntervals) {
|
| SIMULATED_WAIT(conn->num_pings_sent() == ping_sent_before + 1, kMediumTimeout,
|
| clock);
|
| // The interval is expected to be
|
| - // STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL.
|
| + // WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL.
|
| start = clock.TimeNanos();
|
| ping_sent_before = conn->num_pings_sent();
|
| SIMULATED_WAIT(conn->num_pings_sent() == ping_sent_before + 1, kMediumTimeout,
|
| clock);
|
| ping_interval_ms = (clock.TimeNanos() - start) / rtc::kNumNanosecsPerMillisec;
|
| - EXPECT_GE(ping_interval_ms, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL);
|
| - EXPECT_LE(ping_interval_ms,
|
| - STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE);
|
| + EXPECT_GE(ping_interval_ms,
|
| + WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL);
|
| + EXPECT_LE(
|
| + ping_interval_ms,
|
| + WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE);
|
| }
|
|
|
| // Test that we start pinging as soon as we have a connection and remote ICE
|
|
|