Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Unified Diff: webrtc/p2p/base/p2ptransportchannel_unittest.cc

Issue 1270613006: First step of passive aggressive nomination. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Addressed comments Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/p2p/base/p2ptransportchannel_unittest.cc
diff --git a/webrtc/p2p/base/p2ptransportchannel_unittest.cc b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
index f2c7de5b442be0e97d192396cc2e854fe25a8cda..d2a3e5c5cfa17bba98731bfb8187c0ce33b90216 100644
--- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc
+++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
@@ -1750,3 +1750,181 @@ TEST_F(P2PTransportChannelPingTest, TestReceivingStateChange) {
EXPECT_TRUE_WAIT(ch.receiving(), 1000);
EXPECT_TRUE_WAIT(!ch.receiving(), 1000);
}
+
+// The controlled side will select a connection as the "best connection" based
+// on priority until the controlling side nominates a connection, at which
+// point the controlled side will select that connection as the
+// "best connection".
+TEST_F(P2PTransportChannelPingTest, TestSelectConnectionBeforeNomination) {
+ cricket::FakePortAllocator pa(rtc::Thread::Current(), nullptr);
+ cricket::P2PTransportChannel ch("receiving state change", 1, nullptr, &pa);
+ PrepareChannel(&ch);
+ ch.SetIceRole(cricket::ICEROLE_CONTROLLED);
+ ch.Connect();
+ ch.OnCandidate(CreateCandidate("1.1.1.1", 1, 1));
+ cricket::Connection* conn1 = WaitForConnectionTo(&ch, "1.1.1.1", 1);
+ ASSERT_TRUE(conn1 != nullptr);
+ EXPECT_EQ(conn1, ch.best_connection());
+
+ // When a higher priority candidate comes in, the new connection is chosen
+ // as the best connection.
+ ch.OnCandidate(CreateCandidate("2.2.2.2", 2, 10));
+ cricket::Connection* conn2 = WaitForConnectionTo(&ch, "2.2.2.2", 2);
+ ASSERT_TRUE(conn1 != nullptr);
+ EXPECT_EQ(conn2, ch.best_connection());
+
+ // If a stun request with use-candidate attribute arrives, the receiving
+ // connection will be set as the best connection, even though
+ // its priority is lower.
+ ch.OnCandidate(CreateCandidate("3.3.3.3", 3, 1));
+ cricket::Connection* conn3 = WaitForConnectionTo(&ch, "3.3.3.3", 3);
+ ASSERT_TRUE(conn3 != nullptr);
+ // Because it has a lower priority, the best connection is still conn2.
+ EXPECT_EQ(conn2, ch.best_connection());
+ conn3->ReceivedPingResponse(); // Become writable.
+ // But if it is nominated via use_candidate, it is chosen as the best
+ // connection.
+ conn3->set_nominated(true);
+ conn3->SignalNominated(conn3);
+ EXPECT_EQ(conn3, ch.best_connection());
+
+ // Even if another higher priority candidate arrives,
+ // it will not be set as the best connection because the best connection
+ // is nominated by the controlling side.
+ ch.OnCandidate(CreateCandidate("4.4.4.4", 4, 100));
+ cricket::Connection* conn4 = WaitForConnectionTo(&ch, "4.4.4.4", 4);
+ ASSERT_TRUE(conn4 != nullptr);
+ EXPECT_EQ(conn3, ch.best_connection());
+ // But if it is nominated via use_candidate and writable, it will be set as
+ // the best connection.
+ conn4->set_nominated(true);
+ conn4->SignalNominated(conn4);
+ // Not switched yet because conn4 is not writable.
+ EXPECT_EQ(conn3, ch.best_connection());
+ // The best connection switches after conn4 becomes writable.
+ conn4->ReceivedPingResponse();
+ EXPECT_EQ(conn4, ch.best_connection());
+}
+
+// The controlled side will select a connection as the "best connection" based
+// on requests from an unknown address before the controlling side nominates
+// a connection, and will nominate a connection from an unknown address if the
+// request contains the use_candidate attribute.
+TEST_F(P2PTransportChannelPingTest, TestSelectConnectionFromUnknownAddress) {
+ cricket::FakePortAllocator pa(rtc::Thread::Current(), nullptr);
+ cricket::P2PTransportChannel ch("receiving state change", 1, nullptr, &pa);
+ PrepareChannel(&ch);
+ ch.SetIceRole(cricket::ICEROLE_CONTROLLED);
+ ch.Connect();
+ // A minimal STUN message with prflx priority.
+ cricket::IceMessage request;
+ request.SetType(cricket::STUN_BINDING_REQUEST);
+ request.AddAttribute(new cricket::StunByteStringAttribute(
+ cricket::STUN_ATTR_USERNAME, kIceUfrag[1]));
+ uint32 prflx_priority = cricket::ICE_TYPE_PREFERENCE_PRFLX << 24;
+ request.AddAttribute(new cricket::StunUInt32Attribute(
+ cricket::STUN_ATTR_PRIORITY, prflx_priority));
+ cricket::Port* port = GetPort(&ch);
+ port->SignalUnknownAddress(port, rtc::SocketAddress("1.1.1.1", 1),
+ cricket::PROTO_UDP, &request, kIceUfrag[1], false);
+ cricket::Connection* conn1 = WaitForConnectionTo(&ch, "1.1.1.1", 1);
+ ASSERT_TRUE(conn1 != nullptr);
+ EXPECT_EQ(conn1, ch.best_connection());
+ conn1->ReceivedPingResponse();
+ EXPECT_EQ(conn1, ch.best_connection());
+
+ // Another connection is nominated via use_candidate.
+ ch.OnCandidate(CreateCandidate("2.2.2.2", 2, 1));
+ cricket::Connection* conn2 = WaitForConnectionTo(&ch, "2.2.2.2", 2);
+ ASSERT_TRUE(conn2 != nullptr);
+ // Because it has a lower priority, the best connection is still conn1.
+ EXPECT_EQ(conn1, ch.best_connection());
+ // When it is nominated via use_candidate and writable, it is chosen as the
+ // best connection.
+ conn2->ReceivedPingResponse(); // Become writable.
+ conn2->set_nominated(true);
+ conn2->SignalNominated(conn2);
+ EXPECT_EQ(conn2, ch.best_connection());
+
+ // Another request with unknown address, it will not be set as the best
+ // connection because the best connection was nominated by the controlling
+ // side.
+ port->SignalUnknownAddress(port, rtc::SocketAddress("3.3.3.3", 3),
+ cricket::PROTO_UDP, &request, kIceUfrag[1], false);
+ cricket::Connection* conn3 = WaitForConnectionTo(&ch, "3.3.3.3", 3);
+ ASSERT_TRUE(conn3 != nullptr);
+ conn3->ReceivedPingResponse(); // Become writable.
+ EXPECT_EQ(conn2, ch.best_connection());
+
+ // However if the request contains use_candidate attribute, it will be
+ // selected as the best connection.
+ request.AddAttribute(
+ new cricket::StunByteStringAttribute(cricket::STUN_ATTR_USE_CANDIDATE));
+ port->SignalUnknownAddress(port, rtc::SocketAddress("4.4.4.4", 4),
+ cricket::PROTO_UDP, &request, kIceUfrag[1], false);
+ cricket::Connection* conn4 = WaitForConnectionTo(&ch, "4.4.4.4", 4);
+ ASSERT_TRUE(conn4 != nullptr);
+ // conn4 is not the best connection yet because it is not writable.
+ EXPECT_EQ(conn2, ch.best_connection());
+ conn4->ReceivedPingResponse(); // Become writable.
+ EXPECT_EQ(conn4, ch.best_connection());
+}
+
+// The controlled side will select a connection as the "best connection"
+// based on media received until the controlling side nominates a connection,
+// at which point the controlled side will select that connection as
+// the "best connection".
+TEST_F(P2PTransportChannelPingTest, TestSelectConnectionBasedOnMediaReceived) {
+ cricket::FakePortAllocator pa(rtc::Thread::Current(), nullptr);
+ cricket::P2PTransportChannel ch("receiving state change", 1, nullptr, &pa);
+ PrepareChannel(&ch);
+ ch.SetIceRole(cricket::ICEROLE_CONTROLLED);
+ ch.Connect();
+ ch.OnCandidate(CreateCandidate("1.1.1.1", 1, 10));
+ cricket::Connection* conn1 = WaitForConnectionTo(&ch, "1.1.1.1", 1);
+ ASSERT_TRUE(conn1 != nullptr);
+ EXPECT_EQ(conn1, ch.best_connection());
+
+ // If a data packet is received on conn2, the best connection should
+ // switch to conn2 because the controlled side must mirror the media path
+ // chosen by the controlling side.
+ ch.OnCandidate(CreateCandidate("2.2.2.2", 2, 1));
+ cricket::Connection* conn2 = WaitForConnectionTo(&ch, "2.2.2.2", 2);
+ ASSERT_TRUE(conn2 != nullptr);
+ conn2->ReceivedPing(); // Become readable.
+ // Do not switch because it is not writable.
+ conn2->OnReadPacket("ABC", 3, rtc::CreatePacketTime(0));
+ EXPECT_EQ(conn1, ch.best_connection());
+
+ conn2->ReceivedPingResponse(); // Become writable.
+ // Switch because it is writable.
+ conn2->OnReadPacket("DEF", 3, rtc::CreatePacketTime(0));
+ EXPECT_EQ(conn2, ch.best_connection());
+
+ // Now another STUN message with an unknown address and use_candidate will
+ // nominate the best connection.
+ cricket::IceMessage request;
+ request.SetType(cricket::STUN_BINDING_REQUEST);
+ request.AddAttribute(new cricket::StunByteStringAttribute(
+ cricket::STUN_ATTR_USERNAME, kIceUfrag[1]));
+ uint32 prflx_priority = cricket::ICE_TYPE_PREFERENCE_PRFLX << 24;
+ request.AddAttribute(new cricket::StunUInt32Attribute(
+ cricket::STUN_ATTR_PRIORITY, prflx_priority));
+ request.AddAttribute(
+ new cricket::StunByteStringAttribute(cricket::STUN_ATTR_USE_CANDIDATE));
+ cricket::Port* port = GetPort(&ch);
+ port->SignalUnknownAddress(port, rtc::SocketAddress("3.3.3.3", 3),
+ cricket::PROTO_UDP, &request, kIceUfrag[1], false);
+ cricket::Connection* conn3 = WaitForConnectionTo(&ch, "3.3.3.3", 3);
+ ASSERT_TRUE(conn3 != nullptr);
+ EXPECT_EQ(conn2, ch.best_connection()); // Not writable yet.
+ conn3->ReceivedPingResponse(); // Become writable.
+ EXPECT_EQ(conn3, ch.best_connection());
+
+ // Now another data packet will not switch the best connection because the
+ // best connection was nominated by the controlling side.
+ conn2->ReceivedPing();
+ conn2->ReceivedPingResponse();
+ conn2->OnReadPacket("XYZ", 3, rtc::CreatePacketTime(0));
+ EXPECT_EQ(conn3, ch.best_connection());
+}

Powered by Google App Engine
This is Rietveld 408576698