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

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: 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 68c46d6a74da4c3553cbcfc0877535a611aa9c7d..98773699d3cef33bd475c239fc2124711011edf7 100644
--- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc
+++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc
@@ -1884,3 +1884,184 @@ TEST_F(P2PTransportChannelPingTest, TestReceivingStateChange) {
EXPECT_TRUE_WAIT(ch.receiving(), 1000);
EXPECT_TRUE_WAIT(!ch.receiving(), 1000);
}
+
+// When the p2p transport channel with a controlled role received a candidate,
pthatcher1 2015/08/07 22:50:22 You could just shorten this to 'The controlled sid
honghaiz3 2015/08/10 20:15:43 Done.
+// it should set up the best connection if the best connection was not nominated
+// by the controlling side (via use_candidate attribute). If the best connection
+// was nominated by the controlling side, the connection receiving a new
+// candidate will not be set as the best connection.
+TEST_F(P2PTransportChannelPingTest, TestPassiveAggressiveNomination) {
pthatcher1 2015/08/07 22:50:22 It's not yet passive aggressive nomination. It's
honghaiz3 2015/08/10 20:15:43 Done. Shortened the name a little bit.
+ 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->SignalUseCandidate(conn3);
pthatcher1 2015/08/07 22:50:22 Maybe we should just fire SignalNominated within s
honghaiz3 2015/08/10 20:15:43 That's what I did in a previous patch. But Justin
+ 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->SignalUseCandidate(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());
+}
+
+// For the controlled side, when a stun request with an unknown address is
+// received, it will be selected as the best connection if the best connection
+// is not nominated by the controlling side and vice versa. If the received
+// stun request with an unknown address contains a use_candidate attribute, it
+// will be treated as a nomination from the controlling side.
pthatcher1 2015/08/07 22:50:22 I think you could shorten this to "The controlled
honghaiz3 2015/08/10 20:15:43 Done. Thanks!
+TEST_F(P2PTransportChannelPingTest, TestReceivingUnknownAddress) {
pthatcher1 2015/08/07 22:50:22 This is kind of two tests in one: SelectConnectio
honghaiz3 2015/08/10 20:15:43 I think this is more on nominations from Unknown A
+ 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->SignalUseCandidate(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());
+}
+
+// For the controlled side, if a data packet is received on a connection,
+// the sending path will mirror the receiving path if it is writable and
+// the current best connection is not nominated by the controlling side.
+// If the current best connection is already nominated by the controlling side,
+// it will not switch the best connection (the sending path).
pthatcher1 2015/08/07 22:50:22 This could be shortened to 'The controlled side wi
honghaiz3 2015/08/10 20:15:43 Done.
+TEST_F(P2PTransportChannelPingTest, TestSendingPathMirrorReceivingPath) {
pthatcher1 2015/08/07 22:50:22 This might be called SelectConnectionBeforeNominat
honghaiz3 2015/08/10 20:15:43 Shortened a little bit. Since the comments have de
+ 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