Chromium Code Reviews| 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()); |
| +} |