diff --git a/webrtc/p2p/base/port.cc b/webrtc/p2p/base/port.cc index 9dd5c83fed..7993cc02bc 100644 --- a/webrtc/p2p/base/port.cc +++ b/webrtc/p2p/base/port.cc @@ -120,12 +120,12 @@ const char TCPTYPE_SIMOPEN_STR[] = "so"; // then the foundation will be different. Two candidate pairs with // the same foundation pairs are likely to have similar network // characteristics. Foundations are used in the frozen algorithm. -static std::string ComputeFoundation( - const std::string& type, - const std::string& protocol, - const rtc::SocketAddress& base_address) { +static std::string ComputeFoundation(const std::string& type, + const std::string& protocol, + const std::string& relay_protocol, + const rtc::SocketAddress& base_address) { std::ostringstream ost; - ost << type << base_address.ipaddr().ToString() << protocol; + ost << type << base_address.ipaddr().ToString() << protocol << relay_protocol; return rtc::ToString(rtc::ComputeCrc32(ost.str())); } @@ -252,7 +252,8 @@ void Port::AddAddress(const rtc::SocketAddress& address, c.set_network_type(network_->type()); c.set_generation(generation_); c.set_related_address(related_address); - c.set_foundation(ComputeFoundation(type, protocol, base_address)); + c.set_foundation( + ComputeFoundation(type, protocol, relay_protocol, base_address)); candidates_.push_back(c); SignalCandidateReady(this, c); @@ -1389,9 +1390,9 @@ void Connection::MaybeAddPrflxCandidate(ConnectionRequest* request, new_local_candidate.set_network_name(local_candidate().network_name()); new_local_candidate.set_network_type(local_candidate().network_type()); new_local_candidate.set_related_address(local_candidate().address()); - new_local_candidate.set_foundation( - ComputeFoundation(PRFLX_PORT_TYPE, local_candidate().protocol(), - local_candidate().address())); + new_local_candidate.set_foundation(ComputeFoundation( + PRFLX_PORT_TYPE, local_candidate().protocol(), + local_candidate().relay_protocol(), local_candidate().address())); // Change the local candidate of this Connection to the new prflx candidate. local_candidate_index_ = port_->AddPrflxCandidate(new_local_candidate); diff --git a/webrtc/p2p/base/port_unittest.cc b/webrtc/p2p/base/port_unittest.cc index 449021ad9f..4caa326a85 100644 --- a/webrtc/p2p/base/port_unittest.cc +++ b/webrtc/p2p/base/port_unittest.cc @@ -58,6 +58,7 @@ static const SocketAddress kRelayTcpExtAddr("99.99.99.3", 5003); static const SocketAddress kRelaySslTcpIntAddr("99.99.99.2", 5004); static const SocketAddress kRelaySslTcpExtAddr("99.99.99.3", 5005); static const SocketAddress kTurnUdpIntAddr("99.99.99.4", STUN_SERVER_PORT); +static const SocketAddress kTurnTcpIntAddr("99.99.99.4", 5010); static const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0); static const RelayCredentials kRelayCredentials("test", "test"); @@ -497,19 +498,19 @@ class PortTest : public testing::Test, public sigslot::has_slots<> { TurnPort* CreateTurnPort(const SocketAddress& addr, PacketSocketFactory* socket_factory, ProtocolType int_proto, ProtocolType ext_proto) { - return CreateTurnPort(addr, socket_factory, - int_proto, ext_proto, kTurnUdpIntAddr); + SocketAddress server_addr = + int_proto == PROTO_TCP ? kTurnTcpIntAddr : kTurnUdpIntAddr; + return CreateTurnPort(addr, socket_factory, int_proto, ext_proto, + server_addr); } TurnPort* CreateTurnPort(const SocketAddress& addr, PacketSocketFactory* socket_factory, ProtocolType int_proto, ProtocolType ext_proto, const rtc::SocketAddress& server_addr) { - return TurnPort::Create(main_, socket_factory, &network_, - addr.ipaddr(), 0, 0, - username_, password_, ProtocolAddress( - server_addr, PROTO_UDP), - kRelayCredentials, 0, - std::string()); + return TurnPort::Create(main_, socket_factory, &network_, addr.ipaddr(), 0, + 0, username_, password_, + ProtocolAddress(server_addr, int_proto), + kRelayCredentials, 0, std::string()); } RelayPort* CreateGturnPort(const SocketAddress& addr, ProtocolType int_proto, ProtocolType ext_proto) { @@ -2162,6 +2163,17 @@ TEST_F(PortTest, TestCandidateFoundation) { ASSERT_EQ_WAIT(1U, turnport3->Candidates().size(), kTimeout); EXPECT_NE(turnport3->Candidates()[0].foundation(), turnport2->Candidates()[0].foundation()); + + // Start a TCP turn server, and check that two turn candidates have + // different foundations if their relay protocols are different. + TestTurnServer turn_server3(rtc::Thread::Current(), kTurnTcpIntAddr, + kTurnUdpExtAddr, PROTO_TCP); + rtc::scoped_ptr turnport4( + CreateTurnPort(kLocalAddr1, nat_socket_factory1(), PROTO_TCP, PROTO_UDP)); + turnport4->PrepareAddress(); + ASSERT_EQ_WAIT(1U, turnport4->Candidates().size(), kTimeout); + EXPECT_NE(turnport2->Candidates()[0].foundation(), + turnport4->Candidates()[0].foundation()); } // This test verifies the related addresses of different types of diff --git a/webrtc/p2p/base/testturnserver.h b/webrtc/p2p/base/testturnserver.h index 7be35e5340..8660ae1ff2 100644 --- a/webrtc/p2p/base/testturnserver.h +++ b/webrtc/p2p/base/testturnserver.h @@ -49,10 +49,11 @@ class TestTurnRedirector : public TurnRedirectInterface { class TestTurnServer : public TurnAuthInterface { public: TestTurnServer(rtc::Thread* thread, - const rtc::SocketAddress& udp_int_addr, - const rtc::SocketAddress& udp_ext_addr) + const rtc::SocketAddress& int_addr, + const rtc::SocketAddress& udp_ext_addr, + ProtocolType int_protocol = PROTO_UDP) : server_(thread) { - AddInternalSocket(udp_int_addr, cricket::PROTO_UDP); + AddInternalSocket(int_addr, int_protocol); server_.SetExternalSocketFactory(new rtc::BasicPacketSocketFactory(), udp_ext_addr); server_.set_realm(kTestRealm);