diff options
Diffstat (limited to 'chromium/third_party/webrtc/p2p')
24 files changed, 389 insertions, 191 deletions
diff --git a/chromium/third_party/webrtc/p2p/BUILD.gn b/chromium/third_party/webrtc/p2p/BUILD.gn index ae49deb264d..98680f62d2b 100644 --- a/chromium/third_party/webrtc/p2p/BUILD.gn +++ b/chromium/third_party/webrtc/p2p/BUILD.gn @@ -99,7 +99,6 @@ rtc_library("rtc_p2p") { "../rtc_base:checks", "../rtc_base:rtc_numerics", "../rtc_base/experiments:field_trial_parser", - "//third_party/abseil-cpp/absl/memory", # Needed by pseudo_tcp, which should move to a separate target. "../rtc_base:safe_minmax", @@ -107,11 +106,15 @@ rtc_library("rtc_p2p") { "../rtc_base/memory:fifo_buffer", "../rtc_base/network:sent_packet", "../rtc_base/system:rtc_export", + "../rtc_base/task_utils:to_queued_task", "../rtc_base/third_party/base64", "../rtc_base/third_party/sigslot", "../system_wrappers:field_trial", "../system_wrappers:metrics", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/memory", "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/types:optional", ] @@ -127,6 +130,8 @@ if (rtc_include_tests) { "../api:libjingle_peerconnection_api", "../rtc_base", "../rtc_base:rtc_base_approved", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/types:optional", ] @@ -169,6 +174,8 @@ if (rtc_include_tests) { "../rtc_base:rtc_base_tests_utils", "../rtc_base/third_party/sigslot", "../test:test_support", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/types:optional", ] @@ -221,8 +228,11 @@ if (rtc_include_tests) { "../test:field_trial", "../test:test_support", "//testing/gtest", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/types:optional", ] } } @@ -243,8 +253,8 @@ rtc_library("p2p_server_utils") { "../rtc_base:checks", "../rtc_base:rtc_base_tests_utils", "../rtc_base/third_party/sigslot", - "//third_party/abseil-cpp/absl/algorithm:container", ] + absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container" ] } rtc_library("libstunprober") { diff --git a/chromium/third_party/webrtc/p2p/base/basic_async_resolver_factory_unittest.cc b/chromium/third_party/webrtc/p2p/base/basic_async_resolver_factory_unittest.cc index 0c21c682fbe..8242146bae6 100644 --- a/chromium/third_party/webrtc/p2p/base/basic_async_resolver_factory_unittest.cc +++ b/chromium/third_party/webrtc/p2p/base/basic_async_resolver_factory_unittest.cc @@ -30,6 +30,7 @@ class BasicAsyncResolverFactoryTest : public ::testing::Test, rtc::SocketAddress address("", 0); resolver->Start(address); ASSERT_TRUE_WAIT(address_resolved_, 10000 /*ms*/); + resolver->Destroy(false); } void SetAddressResolved(rtc::AsyncResolverInterface* resolver) { diff --git a/chromium/third_party/webrtc/p2p/base/connection.h b/chromium/third_party/webrtc/p2p/base/connection.h index 4b71a7da556..7c468bcff8e 100644 --- a/chromium/third_party/webrtc/p2p/base/connection.h +++ b/chromium/third_party/webrtc/p2p/base/connection.h @@ -71,7 +71,7 @@ class ConnectionRequest : public StunRequest { // Represents a communication link between a port on the local client and a // port on the remote client. class Connection : public CandidatePairInterface, - public rtc::MessageHandler, + public rtc::MessageHandlerAutoCleanup, public sigslot::has_slots<> { public: struct SentPing { diff --git a/chromium/third_party/webrtc/p2p/base/ice_controller_interface.h b/chromium/third_party/webrtc/p2p/base/ice_controller_interface.h index cc4cf4d0d78..d5dc29e7826 100644 --- a/chromium/third_party/webrtc/p2p/base/ice_controller_interface.h +++ b/chromium/third_party/webrtc/p2p/base/ice_controller_interface.h @@ -51,12 +51,20 @@ struct IceControllerEvent { // - which connection to ping // - which connection to use // - which connection to prune +// - which connection to forget learned state on // -// P2PTransportChannel creates a |Connection| and adds a const pointer -// to the IceController using |AddConnection|, i.e the IceController -// should not call any non-const methods on a Connection. +// The P2PTransportChannel owns (creates and destroys) Connections, +// but P2PTransportChannel gives const pointers to the the IceController using +// |AddConnection|, i.e the IceController should not call any non-const methods +// on a Connection but signal back in the interface if any mutable function +// shall be called. // -// The IceController shall keeps track of all connections added +// Current these are limited to: +// Connection::Ping - returned in PingResult +// Connection::Prune - retuned in PruneConnections +// Connection::ForgetLearnedState - return in SwitchResult +// +// The IceController shall keep track of all connections added // (and not destroyed) and give them back using the connections()-function- // // When a Connection gets destroyed @@ -71,6 +79,9 @@ class IceControllerInterface { // An optional recheck event for when a Switch() should be attempted again. absl::optional<IceControllerEvent> recheck_event; + + // A vector with connection to run ForgetLearnedState on. + std::vector<const Connection*> connections_to_forget_state_on; }; // This represents the result of a call to SelectConnectionToPing. diff --git a/chromium/third_party/webrtc/p2p/base/mock_async_resolver.h b/chromium/third_party/webrtc/p2p/base/mock_async_resolver.h index 7d3be5b0b04..8bc0eb9cff4 100644 --- a/chromium/third_party/webrtc/p2p/base/mock_async_resolver.h +++ b/chromium/third_party/webrtc/p2p/base/mock_async_resolver.h @@ -29,14 +29,17 @@ class MockAsyncResolver : public AsyncResolverInterface { } ~MockAsyncResolver() = default; - MOCK_METHOD1(Start, void(const rtc::SocketAddress&)); - MOCK_CONST_METHOD2(GetResolvedAddress, bool(int family, SocketAddress* addr)); - MOCK_CONST_METHOD0(GetError, int()); + MOCK_METHOD(void, Start, (const rtc::SocketAddress&), (override)); + MOCK_METHOD(bool, + GetResolvedAddress, + (int family, SocketAddress* addr), + (const, override)); + MOCK_METHOD(int, GetError, (), (const, override)); // Note that this won't delete the object like AsyncResolverInterface says in // order to avoid sanitizer failures caused by this being a synchronous // implementation. The test code should delete the object instead. - MOCK_METHOD1(Destroy, void(bool)); + MOCK_METHOD(void, Destroy, (bool), (override)); }; } // namespace rtc @@ -45,7 +48,7 @@ namespace webrtc { class MockAsyncResolverFactory : public AsyncResolverFactory { public: - MOCK_METHOD0(Create, rtc::AsyncResolverInterface*()); + MOCK_METHOD(rtc::AsyncResolverInterface*, Create, (), (override)); }; } // namespace webrtc diff --git a/chromium/third_party/webrtc/p2p/base/mock_ice_transport.h b/chromium/third_party/webrtc/p2p/base/mock_ice_transport.h index 1436cacb50d..ef9f1b18ea1 100644 --- a/chromium/third_party/webrtc/p2p/base/mock_ice_transport.h +++ b/chromium/third_party/webrtc/p2p/base/mock_ice_transport.h @@ -32,15 +32,20 @@ class MockIceTransport : public IceTransportInternal { SignalWritableState(this); } - MOCK_METHOD4(SendPacket, - int(const char* data, - size_t len, - const rtc::PacketOptions& options, - int flags)); - MOCK_METHOD2(SetOption, int(rtc::Socket::Option opt, int value)); - MOCK_METHOD0(GetError, int()); - MOCK_CONST_METHOD0(GetIceRole, cricket::IceRole()); - MOCK_METHOD1(GetStats, bool(cricket::IceTransportStats* ice_transport_stats)); + MOCK_METHOD(int, + SendPacket, + (const char* data, + size_t len, + const rtc::PacketOptions& options, + int flags), + (override)); + MOCK_METHOD(int, SetOption, (rtc::Socket::Option opt, int value), (override)); + MOCK_METHOD(int, GetError, (), (override)); + MOCK_METHOD(cricket::IceRole, GetIceRole, (), (const, override)); + MOCK_METHOD(bool, + GetStats, + (cricket::IceTransportStats * ice_transport_stats), + (override)); IceTransportState GetState() const override { return IceTransportState::STATE_INIT; diff --git a/chromium/third_party/webrtc/p2p/base/p2p_transport_channel.cc b/chromium/third_party/webrtc/p2p/base/p2p_transport_channel.cc index 73d12c77415..6f0df04150d 100644 --- a/chromium/third_party/webrtc/p2p/base/p2p_transport_channel.cc +++ b/chromium/third_party/webrtc/p2p/base/p2p_transport_channel.cc @@ -30,6 +30,7 @@ #include "rtc_base/net_helper.h" #include "rtc_base/net_helpers.h" #include "rtc_base/string_encode.h" +#include "rtc_base/task_utils/to_queued_task.h" #include "rtc_base/time_utils.h" #include "system_wrappers/include/field_trial.h" #include "system_wrappers/include/metrics.h" @@ -274,8 +275,7 @@ bool P2PTransportChannel::MaybeSwitchSelectedConnection( if (result.connection.has_value()) { RTC_LOG(LS_INFO) << "Switching selected connection due to: " << reason.ToString(); - SwitchSelectedConnection(const_cast<Connection*>(*result.connection), - reason); + SwitchSelectedConnection(FromIceController(*result.connection), reason); } if (result.recheck_event.has_value()) { @@ -290,6 +290,10 @@ bool P2PTransportChannel::MaybeSwitchSelectedConnection( result.recheck_event->recheck_delay_ms); } + for (const auto* con : result.connections_to_forget_state_on) { + FromIceController(con)->ForgetLearnedState(); + } + return result.connection.has_value(); } @@ -1194,7 +1198,12 @@ void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { } if (new_remote_candidate.address().IsUnresolvedIP()) { - ResolveHostnameCandidate(new_remote_candidate); + // Don't do DNS lookups if the IceTransportPolicy is "none" or "relay". + bool sharing_host = ((allocator_->candidate_filter() & CF_HOST) != 0); + bool sharing_stun = ((allocator_->candidate_filter() & CF_REFLEXIVE) != 0); + if (sharing_host || sharing_stun) { + ResolveHostnameCandidate(new_remote_candidate); + } return; } @@ -1223,9 +1232,8 @@ void P2PTransportChannel::OnCandidateResolved( Candidate candidate = p->candidate_; resolvers_.erase(p); AddRemoteCandidateWithResolver(candidate, resolver); - invoker_.AsyncInvoke<void>( - RTC_FROM_HERE, thread(), - rtc::Bind(&rtc::AsyncResolverInterface::Destroy, resolver, false)); + thread()->PostTask( + webrtc::ToQueuedTask([] {}, [resolver] { resolver->Destroy(false); })); } void P2PTransportChannel::AddRemoteCandidateWithResolver( @@ -1398,7 +1406,7 @@ bool P2PTransportChannel::CreateConnection(PortInterface* port, return false; } -bool P2PTransportChannel::FindConnection(Connection* connection) const { +bool P2PTransportChannel::FindConnection(const Connection* connection) const { RTC_DCHECK_RUN_ON(network_thread_); return absl::c_linear_search(connections(), connection); } @@ -1704,7 +1712,7 @@ void P2PTransportChannel::PruneConnections() { std::vector<const Connection*> connections_to_prune = ice_controller_->PruneConnections(); for (const Connection* conn : connections_to_prune) { - const_cast<Connection*>(conn)->Prune(); + FromIceController(conn)->Prune(); } } @@ -1907,11 +1915,10 @@ void P2PTransportChannel::CheckAndPing() { UpdateConnectionStates(); auto result = ice_controller_->SelectConnectionToPing(last_ping_sent_ms_); - Connection* conn = - const_cast<Connection*>(result.connection.value_or(nullptr)); int delay = result.recheck_delay_ms; - if (conn) { + if (result.connection.value_or(nullptr)) { + Connection* conn = FromIceController(*result.connection); PingConnection(conn); MarkConnectionPinged(conn); } @@ -1924,7 +1931,12 @@ void P2PTransportChannel::CheckAndPing() { // This method is only for unit testing. Connection* P2PTransportChannel::FindNextPingableConnection() { RTC_DCHECK_RUN_ON(network_thread_); - return const_cast<Connection*>(ice_controller_->FindNextPingableConnection()); + auto* conn = ice_controller_->FindNextPingableConnection(); + if (conn) { + return FromIceController(conn); + } else { + return nullptr; + } } // A connection is considered a backup connection if the channel state diff --git a/chromium/third_party/webrtc/p2p/base/p2p_transport_channel.h b/chromium/third_party/webrtc/p2p/base/p2p_transport_channel.h index 3d6c86f0319..4f891beb1eb 100644 --- a/chromium/third_party/webrtc/p2p/base/p2p_transport_channel.h +++ b/chromium/third_party/webrtc/p2p/base/p2p_transport_channel.h @@ -245,7 +245,7 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal { bool CreateConnection(PortInterface* port, const Candidate& remote_candidate, PortInterface* origin_port); - bool FindConnection(Connection* connection) const; + bool FindConnection(const Connection* connection) const; uint32_t GetRemoteCandidateGeneration(const Candidate& candidate); bool IsDuplicateRemoteCandidate(const Candidate& candidate); @@ -348,6 +348,16 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal { // 2. Peer-reflexive remote candidates. Candidate SanitizeRemoteCandidate(const Candidate& c) const; + // Cast a Connection returned from IceController and verify that it exists. + // (P2P owns all Connections, and only gives const pointers to IceController, + // see IceControllerInterface). + Connection* FromIceController(const Connection* conn) { + // Verify that IceController does not return a connection + // that we have destroyed. + RTC_DCHECK(FindConnection(conn)); + return const_cast<Connection*>(conn); + } + std::string transport_name_ RTC_GUARDED_BY(network_thread_); int component_ RTC_GUARDED_BY(network_thread_); PortAllocator* allocator_ RTC_GUARDED_BY(network_thread_); diff --git a/chromium/third_party/webrtc/p2p/base/p2p_transport_channel_unittest.cc b/chromium/third_party/webrtc/p2p/base/p2p_transport_channel_unittest.cc index ce78335fd94..721ee1589ce 100644 --- a/chromium/third_party/webrtc/p2p/base/p2p_transport_channel_unittest.cc +++ b/chromium/third_party/webrtc/p2p/base/p2p_transport_channel_unittest.cc @@ -177,14 +177,14 @@ cricket::BasicPortAllocator* CreateBasicPortAllocator( class MockIceControllerFactory : public cricket::IceControllerFactoryInterface { public: - ~MockIceControllerFactory() = default; + ~MockIceControllerFactory() override = default; std::unique_ptr<cricket::IceControllerInterface> Create( - const cricket::IceControllerFactoryArgs& args) { + const cricket::IceControllerFactoryArgs& args) override { RecordIceControllerCreated(); return std::make_unique<cricket::BasicIceController>(args); } - MOCK_METHOD0(RecordIceControllerCreated, void()); + MOCK_METHOD(void, RecordIceControllerCreated, ()); }; } // namespace @@ -207,7 +207,7 @@ namespace cricket { // Note that this class is a base class for use by other tests, who will provide // specialized test behavior. class P2PTransportChannelTestBase : public ::testing::Test, - public rtc::MessageHandler, + public rtc::MessageHandlerAutoCleanup, public sigslot::has_slots<> { public: P2PTransportChannelTestBase() @@ -1480,7 +1480,7 @@ TEST_F(P2PTransportChannelTest, PeerReflexiveCandidateBeforeSignaling) { PauseCandidates(1); // Wait until the callee becomes writable to make sure that a ping request is - // received by the caller before his remote ICE credentials are set. + // received by the caller before their remote ICE credentials are set. ASSERT_TRUE_WAIT(ep2_ch1()->selected_connection() != nullptr, kMediumTimeout); // Add two sets of remote ICE credentials, so that the ones used by the // candidate will be generation 1 instead of 0. @@ -1588,7 +1588,7 @@ TEST_F(P2PTransportChannelTest, PeerReflexiveCandidateBeforeSignalingWithNAT) { PauseCandidates(1); // Wait until the callee becomes writable to make sure that a ping request is - // received by the caller before his remote ICE credentials are set. + // received by the caller before their remote ICE credentials are set. ASSERT_TRUE_WAIT(ep2_ch1()->selected_connection() != nullptr, kMediumTimeout); // Add two sets of remote ICE credentials, so that the ones used by the // candidate will be generation 1 instead of 0. @@ -4844,10 +4844,13 @@ TEST_F(P2PTransportChannelTest, // address after the resolution completes. TEST_F(P2PTransportChannelTest, PeerReflexiveCandidateDuringResolvingHostCandidateWithMdnsName) { - NiceMock<rtc::MockAsyncResolver> mock_async_resolver; + auto mock_async_resolver = new NiceMock<rtc::MockAsyncResolver>(); + ON_CALL(*mock_async_resolver, Destroy).WillByDefault([mock_async_resolver] { + delete mock_async_resolver; + }); webrtc::MockAsyncResolverFactory mock_async_resolver_factory; EXPECT_CALL(mock_async_resolver_factory, Create()) - .WillOnce(Return(&mock_async_resolver)); + .WillOnce(Return(mock_async_resolver)); // ep1 and ep2 will only gather host candidates with addresses // kPublicAddrs[0] and kPublicAddrs[1], respectively. @@ -4874,7 +4877,7 @@ TEST_F(P2PTransportChannelTest, bool mock_async_resolver_started = false; // Not signaling done yet, and only make sure we are in the process of // resolution. - EXPECT_CALL(mock_async_resolver, Start(_)) + EXPECT_CALL(*mock_async_resolver, Start(_)) .WillOnce(InvokeWithoutArgs([&mock_async_resolver_started]() { mock_async_resolver_started = true; })); @@ -4887,7 +4890,7 @@ TEST_F(P2PTransportChannelTest, ResumeCandidates(1); ASSERT_TRUE_WAIT(ep1_ch1()->selected_connection() != nullptr, kMediumTimeout); // Let the mock resolver of ep2 receives the correct resolution. - EXPECT_CALL(mock_async_resolver, GetResolvedAddress(_, _)) + EXPECT_CALL(*mock_async_resolver, GetResolvedAddress(_, _)) .WillOnce(DoAll(SetArgPointee<1>(local_address), Return(true))); // Upon receiving a ping from ep1, ep2 adds a prflx candidate from the // unknown address and establishes a connection. @@ -4899,7 +4902,7 @@ TEST_F(P2PTransportChannelTest, ep2_ch1()->selected_connection()->remote_candidate().type()); // ep2 should also be able resolve the hostname candidate. The resolved remote // host candidate should be merged with the prflx remote candidate. - mock_async_resolver.SignalDone(&mock_async_resolver); + mock_async_resolver->SignalDone(mock_async_resolver); EXPECT_EQ_WAIT(LOCAL_PORT_TYPE, ep2_ch1()->selected_connection()->remote_candidate().type(), kMediumTimeout); @@ -5255,10 +5258,14 @@ TEST_F(P2PTransportChannelTest, class MockMdnsResponder : public webrtc::MdnsResponderInterface { public: - MOCK_METHOD2(CreateNameForAddress, - void(const rtc::IPAddress&, NameCreatedCallback)); - MOCK_METHOD2(RemoveNameForAddress, - void(const rtc::IPAddress&, NameRemovedCallback)); + MOCK_METHOD(void, + CreateNameForAddress, + (const rtc::IPAddress&, NameCreatedCallback), + (override)); + MOCK_METHOD(void, + RemoveNameForAddress, + (const rtc::IPAddress&, NameRemovedCallback), + (override)); }; TEST_F(P2PTransportChannelTest, @@ -5539,6 +5546,76 @@ TEST_F(P2PTransportChannelTest, DestroyChannels(); } +// Verify that things break unless +// - both parties use the surface_ice_candidates_on_ice_transport_type_changed +// - both parties loosen candidate filter at the same time (approx.). +// +// i.e surface_ice_candidates_on_ice_transport_type_changed requires +// coordination outside of webrtc to function properly. +TEST_F(P2PTransportChannelTest, SurfaceRequiresCoordination) { + webrtc::test::ScopedFieldTrials field_trials( + "WebRTC-IceFieldTrials/skip_relay_to_non_relay_connections:true/"); + rtc::ScopedFakeClock clock; + + ConfigureEndpoints( + OPEN, OPEN, + kDefaultPortAllocatorFlags | PORTALLOCATOR_ENABLE_SHARED_SOCKET, + kDefaultPortAllocatorFlags | PORTALLOCATOR_ENABLE_SHARED_SOCKET); + auto* ep1 = GetEndpoint(0); + auto* ep2 = GetEndpoint(1); + ep1->allocator_->SetCandidateFilter(CF_RELAY); + ep2->allocator_->SetCandidateFilter(CF_ALL); + // Enable continual gathering and also resurfacing gathered candidates upon + // the candidate filter changed in the ICE configuration. + IceConfig ice_config = CreateIceConfig(1000, GATHER_CONTINUALLY); + ice_config.surface_ice_candidates_on_ice_transport_type_changed = true; + // Pause candidates gathering so we can gather all types of candidates. See + // P2PTransportChannel::OnConnectionStateChange, where we would stop the + // gathering when we have a strongly connected candidate pair. + PauseCandidates(0); + PauseCandidates(1); + CreateChannels(ice_config, ice_config); + + // On the caller we only have relay, + // on the callee we have host, srflx and relay. + EXPECT_TRUE_SIMULATED_WAIT(ep1->saved_candidates_.size() == 1u, + kDefaultTimeout, clock); + EXPECT_TRUE_SIMULATED_WAIT(ep2->saved_candidates_.size() == 3u, + kDefaultTimeout, clock); + + ResumeCandidates(0); + ResumeCandidates(1); + ASSERT_TRUE_SIMULATED_WAIT( + ep1_ch1()->selected_connection() != nullptr && + RELAY_PORT_TYPE == + ep1_ch1()->selected_connection()->local_candidate().type() && + ep2_ch1()->selected_connection() != nullptr && + RELAY_PORT_TYPE == + ep1_ch1()->selected_connection()->remote_candidate().type(), + kDefaultTimeout, clock); + ASSERT_TRUE_SIMULATED_WAIT(ep2_ch1()->selected_connection() != nullptr, + kDefaultTimeout, clock); + + // Wait until the callee discards it's candidates + // since they don't manage to connect. + SIMULATED_WAIT(false, 300000, clock); + + // And then loosen caller candidate filter. + ep1->allocator_->SetCandidateFilter(CF_ALL); + + SIMULATED_WAIT(false, kDefaultTimeout, clock); + + // No p2p connection will be made, it will remain on relay. + EXPECT_TRUE(ep1_ch1()->selected_connection() != nullptr && + RELAY_PORT_TYPE == + ep1_ch1()->selected_connection()->local_candidate().type() && + ep2_ch1()->selected_connection() != nullptr && + RELAY_PORT_TYPE == + ep1_ch1()->selected_connection()->remote_candidate().type()); + + DestroyChannels(); +} + TEST_F(P2PTransportChannelPingTest, TestInitialSelectDampening0) { webrtc::test::ScopedFieldTrials field_trials( "WebRTC-IceFieldTrials/initial_select_dampening:0/"); @@ -5651,4 +5728,159 @@ TEST(P2PTransportChannel, InjectIceController) { /* event_log = */ nullptr, &factory); } +class ForgetLearnedStateController : public cricket::BasicIceController { + public: + explicit ForgetLearnedStateController( + const cricket::IceControllerFactoryArgs& args) + : cricket::BasicIceController(args) {} + + SwitchResult SortAndSwitchConnection(IceControllerEvent reason) override { + auto result = cricket::BasicIceController::SortAndSwitchConnection(reason); + if (forget_connnection_) { + result.connections_to_forget_state_on.push_back(forget_connnection_); + forget_connnection_ = nullptr; + } + result.recheck_event = + IceControllerEvent(IceControllerEvent::ICE_CONTROLLER_RECHECK); + result.recheck_event->recheck_delay_ms = 100; + return result; + } + + void ForgetThisConnectionNextTimeSortAndSwitchConnectionIsCalled( + Connection* con) { + forget_connnection_ = con; + } + + private: + Connection* forget_connnection_ = nullptr; +}; + +class ForgetLearnedStateControllerFactory + : public cricket::IceControllerFactoryInterface { + public: + std::unique_ptr<cricket::IceControllerInterface> Create( + const cricket::IceControllerFactoryArgs& args) override { + auto controller = std::make_unique<ForgetLearnedStateController>(args); + // Keep a pointer to allow modifying calls. + // Must not be used after the p2ptransportchannel has been destructed. + controller_ = controller.get(); + return controller; + } + virtual ~ForgetLearnedStateControllerFactory() = default; + + ForgetLearnedStateController* controller_; +}; + +TEST_F(P2PTransportChannelPingTest, TestForgetLearnedState) { + ForgetLearnedStateControllerFactory factory; + FakePortAllocator pa(rtc::Thread::Current(), nullptr); + P2PTransportChannel ch("ping sufficiently", 1, &pa, nullptr, nullptr, + &factory); + PrepareChannel(&ch); + ch.MaybeStartGathering(); + ch.AddRemoteCandidate(CreateUdpCandidate(LOCAL_PORT_TYPE, "1.1.1.1", 1, 1)); + ch.AddRemoteCandidate(CreateUdpCandidate(LOCAL_PORT_TYPE, "2.2.2.2", 2, 2)); + + Connection* conn1 = WaitForConnectionTo(&ch, "1.1.1.1", 1); + Connection* conn2 = WaitForConnectionTo(&ch, "2.2.2.2", 2); + ASSERT_TRUE(conn1 != nullptr); + ASSERT_TRUE(conn2 != nullptr); + + // Wait for conn1 to be selected. + conn1->ReceivedPingResponse(LOW_RTT, "id"); + EXPECT_EQ_WAIT(conn1, ch.selected_connection(), kMediumTimeout); + + conn2->ReceivedPingResponse(LOW_RTT, "id"); + EXPECT_TRUE(conn2->writable()); + + // Now let the ice controller signal to P2PTransportChannel that it + // should Forget conn2. + factory.controller_ + ->ForgetThisConnectionNextTimeSortAndSwitchConnectionIsCalled(conn2); + + // We don't have a mock Connection, so verify this by checking that it + // is no longer writable. + EXPECT_EQ_WAIT(false, conn2->writable(), kMediumTimeout); +} + +TEST_F(P2PTransportChannelTest, DisableDnsLookupsWithTransportPolicyRelay) { + ConfigureEndpoints(OPEN, OPEN, kDefaultPortAllocatorFlags, + kDefaultPortAllocatorFlags); + auto* ep1 = GetEndpoint(0); + ep1->allocator_->SetCandidateFilter(CF_RELAY); + + rtc::MockAsyncResolver mock_async_resolver; + webrtc::MockAsyncResolverFactory mock_async_resolver_factory; + ON_CALL(mock_async_resolver_factory, Create()) + .WillByDefault(Return(&mock_async_resolver)); + ep1->async_resolver_factory_ = &mock_async_resolver_factory; + + bool lookup_started = false; + ON_CALL(mock_async_resolver, Start(_)) + .WillByDefault(Assign(&lookup_started, true)); + + CreateChannels(); + + ep1_ch1()->AddRemoteCandidate( + CreateUdpCandidate(LOCAL_PORT_TYPE, "hostname.test", 1, 100)); + + EXPECT_FALSE(lookup_started); + + DestroyChannels(); +} + +TEST_F(P2PTransportChannelTest, DisableDnsLookupsWithTransportPolicyNone) { + ConfigureEndpoints(OPEN, OPEN, kDefaultPortAllocatorFlags, + kDefaultPortAllocatorFlags); + auto* ep1 = GetEndpoint(0); + ep1->allocator_->SetCandidateFilter(CF_NONE); + + rtc::MockAsyncResolver mock_async_resolver; + webrtc::MockAsyncResolverFactory mock_async_resolver_factory; + ON_CALL(mock_async_resolver_factory, Create()) + .WillByDefault(Return(&mock_async_resolver)); + ep1->async_resolver_factory_ = &mock_async_resolver_factory; + + bool lookup_started = false; + ON_CALL(mock_async_resolver, Start(_)) + .WillByDefault(Assign(&lookup_started, true)); + + CreateChannels(); + + ep1_ch1()->AddRemoteCandidate( + CreateUdpCandidate(LOCAL_PORT_TYPE, "hostname.test", 1, 100)); + + EXPECT_FALSE(lookup_started); + + DestroyChannels(); +} + +TEST_F(P2PTransportChannelTest, EnableDnsLookupsWithTransportPolicyNoHost) { + ConfigureEndpoints(OPEN, OPEN, kDefaultPortAllocatorFlags, + kDefaultPortAllocatorFlags); + auto* ep1 = GetEndpoint(0); + ep1->allocator_->SetCandidateFilter(CF_ALL & ~CF_HOST); + + rtc::MockAsyncResolver mock_async_resolver; + webrtc::MockAsyncResolverFactory mock_async_resolver_factory; + EXPECT_CALL(mock_async_resolver_factory, Create()) + .WillOnce(Return(&mock_async_resolver)); + EXPECT_CALL(mock_async_resolver, Destroy(_)); + + ep1->async_resolver_factory_ = &mock_async_resolver_factory; + + bool lookup_started = false; + EXPECT_CALL(mock_async_resolver, Start(_)) + .WillOnce(Assign(&lookup_started, true)); + + CreateChannels(); + + ep1_ch1()->AddRemoteCandidate( + CreateUdpCandidate(LOCAL_PORT_TYPE, "hostname.test", 1, 100)); + + EXPECT_TRUE(lookup_started); + + DestroyChannels(); +} + } // namespace cricket diff --git a/chromium/third_party/webrtc/p2p/base/port.h b/chromium/third_party/webrtc/p2p/base/port.h index 893e80b20f4..7418a972659 100644 --- a/chromium/third_party/webrtc/p2p/base/port.h +++ b/chromium/third_party/webrtc/p2p/base/port.h @@ -158,7 +158,7 @@ typedef std::set<rtc::SocketAddress> ServerAddresses; // connections to similar mechanisms of the other client. Subclasses of this // one add support for specific mechanisms like local UDP ports. class Port : public PortInterface, - public rtc::MessageHandler, + public rtc::MessageHandlerAutoCleanup, public sigslot::has_slots<> { public: // INIT: The state when a port is just created. diff --git a/chromium/third_party/webrtc/p2p/base/pseudo_tcp_unittest.cc b/chromium/third_party/webrtc/p2p/base/pseudo_tcp_unittest.cc index a7fc9b3e698..ecafec9fb64 100644 --- a/chromium/third_party/webrtc/p2p/base/pseudo_tcp_unittest.cc +++ b/chromium/third_party/webrtc/p2p/base/pseudo_tcp_unittest.cc @@ -44,7 +44,7 @@ class PseudoTcpForTest : public cricket::PseudoTcp { }; class PseudoTcpTestBase : public ::testing::Test, - public rtc::MessageHandler, + public rtc::MessageHandlerAutoCleanup, public cricket::IPseudoTcpNotify { public: PseudoTcpTestBase() diff --git a/chromium/third_party/webrtc/p2p/base/stun_port_unittest.cc b/chromium/third_party/webrtc/p2p/base/stun_port_unittest.cc index dfc72362ce2..2804ac03aff 100644 --- a/chromium/third_party/webrtc/p2p/base/stun_port_unittest.cc +++ b/chromium/third_party/webrtc/p2p/base/stun_port_unittest.cc @@ -412,24 +412,29 @@ class MockAsyncPacketSocket : public rtc::AsyncPacketSocket { public: ~MockAsyncPacketSocket() = default; - MOCK_CONST_METHOD0(GetLocalAddress, SocketAddress()); - MOCK_CONST_METHOD0(GetRemoteAddress, SocketAddress()); - MOCK_METHOD3(Send, - int(const void* pv, - size_t cb, - const rtc::PacketOptions& options)); - - MOCK_METHOD4(SendTo, - int(const void* pv, - size_t cb, - const SocketAddress& addr, - const rtc::PacketOptions& options)); - MOCK_METHOD0(Close, int()); - MOCK_CONST_METHOD0(GetState, State()); - MOCK_METHOD2(GetOption, int(rtc::Socket::Option opt, int* value)); - MOCK_METHOD2(SetOption, int(rtc::Socket::Option opt, int value)); - MOCK_CONST_METHOD0(GetError, int()); - MOCK_METHOD1(SetError, void(int error)); + MOCK_METHOD(SocketAddress, GetLocalAddress, (), (const, override)); + MOCK_METHOD(SocketAddress, GetRemoteAddress, (), (const, override)); + MOCK_METHOD(int, + Send, + (const void* pv, size_t cb, const rtc::PacketOptions& options), + (override)); + + MOCK_METHOD(int, + SendTo, + (const void* pv, + size_t cb, + const SocketAddress& addr, + const rtc::PacketOptions& options), + (override)); + MOCK_METHOD(int, Close, (), (override)); + MOCK_METHOD(State, GetState, (), (const, override)); + MOCK_METHOD(int, + GetOption, + (rtc::Socket::Option opt, int* value), + (override)); + MOCK_METHOD(int, SetOption, (rtc::Socket::Option opt, int value), (override)); + MOCK_METHOD(int, GetError, (), (const, override)); + MOCK_METHOD(void, SetError, (int error), (override)); }; // Test that outbound packets inherit the dscp value assigned to the socket. diff --git a/chromium/third_party/webrtc/p2p/base/stun_request.h b/chromium/third_party/webrtc/p2p/base/stun_request.h index d45376ea550..17569046151 100644 --- a/chromium/third_party/webrtc/p2p/base/stun_request.h +++ b/chromium/third_party/webrtc/p2p/base/stun_request.h @@ -85,7 +85,7 @@ class StunRequestManager { // Represents an individual request to be sent. The STUN message can either be // constructed beforehand or built on demand. -class StunRequest : public rtc::MessageHandler { +class StunRequest : public rtc::MessageHandlerAutoCleanup { public: StunRequest(); explicit StunRequest(StunMessage* request); diff --git a/chromium/third_party/webrtc/p2p/base/transport_description.cc b/chromium/third_party/webrtc/p2p/base/transport_description.cc index 729b4ae8c3d..96fb9597e04 100644 --- a/chromium/third_party/webrtc/p2p/base/transport_description.cc +++ b/chromium/third_party/webrtc/p2p/base/transport_description.cc @@ -172,8 +172,7 @@ TransportDescription::TransportDescription(const TransportDescription& from) ice_pwd(from.ice_pwd), ice_mode(from.ice_mode), connection_role(from.connection_role), - identity_fingerprint(CopyFingerprint(from.identity_fingerprint.get())), - opaque_parameters(from.opaque_parameters) {} + identity_fingerprint(CopyFingerprint(from.identity_fingerprint.get())) {} TransportDescription::~TransportDescription() = default; @@ -190,7 +189,6 @@ TransportDescription& TransportDescription::operator=( connection_role = from.connection_role; identity_fingerprint.reset(CopyFingerprint(from.identity_fingerprint.get())); - opaque_parameters = from.opaque_parameters; return *this; } diff --git a/chromium/third_party/webrtc/p2p/base/transport_description.h b/chromium/third_party/webrtc/p2p/base/transport_description.h index 1a458c95714..32fdb5c9b32 100644 --- a/chromium/third_party/webrtc/p2p/base/transport_description.h +++ b/chromium/third_party/webrtc/p2p/base/transport_description.h @@ -100,28 +100,6 @@ constexpr auto* ICE_OPTION_RENOMINATION = "renomination"; bool StringToConnectionRole(const std::string& role_str, ConnectionRole* role); bool ConnectionRoleToString(const ConnectionRole& role, std::string* role_str); -// Parameters for an opaque transport protocol which may be plugged into WebRTC. -struct OpaqueTransportParameters { - // Protocol used by this opaque transport. Two endpoints that support the - // same protocol are expected to be able to understand the contents of each - // others' |parameters| fields. If those parameters are compatible, the - // endpoints are expected to use this transport protocol. - std::string protocol; - - // Opaque parameters for this transport. These parameters are serialized in a - // manner determined by the |protocol|. They can be parsed and understood by - // the plugin that supports |protocol|. - std::string parameters; - - bool operator==(const OpaqueTransportParameters& other) const { - return protocol == other.protocol && parameters == other.parameters; - } - - bool operator!=(const OpaqueTransportParameters& other) const { - return !(*this == other); - } -}; - struct TransportDescription { TransportDescription(); TransportDescription(const std::vector<std::string>& transport_options, @@ -168,7 +146,6 @@ struct TransportDescription { ConnectionRole connection_role; std::unique_ptr<rtc::SSLFingerprint> identity_fingerprint; - absl::optional<OpaqueTransportParameters> opaque_parameters; }; } // namespace cricket diff --git a/chromium/third_party/webrtc/p2p/base/transport_description_factory.cc b/chromium/third_party/webrtc/p2p/base/transport_description_factory.cc index 17152d1a047..5cce2ac09d6 100644 --- a/chromium/third_party/webrtc/p2p/base/transport_description_factory.cc +++ b/chromium/third_party/webrtc/p2p/base/transport_description_factory.cc @@ -55,8 +55,6 @@ std::unique_ptr<TransportDescription> TransportDescriptionFactory::CreateOffer( } } - desc->opaque_parameters = options.opaque_parameters; - return desc; } @@ -110,13 +108,6 @@ std::unique_ptr<TransportDescription> TransportDescriptionFactory::CreateAnswer( return NULL; } - // Answers may only attach opaque parameters if the offer contained them as - // well. The answer's parameters may differ, and it's up to the opaque - // transport implementation to decide if the difference is acceptable. - if (offer->opaque_parameters && options.opaque_parameters) { - desc->opaque_parameters = options.opaque_parameters; - } - return desc; } diff --git a/chromium/third_party/webrtc/p2p/base/transport_description_factory.h b/chromium/third_party/webrtc/p2p/base/transport_description_factory.h index d0813dc541e..c1656a0fac2 100644 --- a/chromium/third_party/webrtc/p2p/base/transport_description_factory.h +++ b/chromium/third_party/webrtc/p2p/base/transport_description_factory.h @@ -29,9 +29,6 @@ struct TransportOptions { // If true, ICE renomination is supported and will be used if it is also // supported by the remote side. bool enable_ice_renomination = false; - - // Opaque parameters for plug-in transports. - absl::optional<OpaqueTransportParameters> opaque_parameters; }; // Creates transport descriptions according to the supplied configuration. diff --git a/chromium/third_party/webrtc/p2p/base/transport_description_factory_unittest.cc b/chromium/third_party/webrtc/p2p/base/transport_description_factory_unittest.cc index 8359ffc1c9d..f7675ae643f 100644 --- a/chromium/third_party/webrtc/p2p/base/transport_description_factory_unittest.cc +++ b/chromium/third_party/webrtc/p2p/base/transport_description_factory_unittest.cc @@ -26,7 +26,6 @@ #include "test/gmock.h" #include "test/gtest.h" -using cricket::OpaqueTransportParameters; using cricket::TransportDescription; using cricket::TransportDescriptionFactory; using cricket::TransportOptions; @@ -210,73 +209,6 @@ TEST_F(TransportDescriptionFactoryTest, TestOfferDtlsReofferDtls) { CheckDesc(desc.get(), "", old_desc->ice_ufrag, old_desc->ice_pwd, digest_alg); } -TEST_F(TransportDescriptionFactoryTest, TestOfferOpaqueTransportParameters) { - OpaqueTransportParameters params; - params.protocol = "fake"; - params.parameters = "foobar"; - - TransportOptions options; - options.opaque_parameters = params; - - std::unique_ptr<TransportDescription> desc = - f1_.CreateOffer(options, NULL, &ice_credentials_); - - CheckDesc(desc.get(), "", "", "", ""); - EXPECT_EQ(desc->opaque_parameters, params); -} - -TEST_F(TransportDescriptionFactoryTest, TestAnswerOpaqueTransportParameters) { - OpaqueTransportParameters params; - params.protocol = "fake"; - params.parameters = "foobar"; - - TransportOptions options; - options.opaque_parameters = params; - - std::unique_ptr<TransportDescription> offer = - f1_.CreateOffer(options, NULL, &ice_credentials_); - std::unique_ptr<TransportDescription> answer = - f2_.CreateAnswer(offer.get(), options, true, NULL, &ice_credentials_); - - CheckDesc(answer.get(), "", "", "", ""); - EXPECT_EQ(answer->opaque_parameters, params); -} - -TEST_F(TransportDescriptionFactoryTest, TestAnswerNoOpaqueTransportParameters) { - OpaqueTransportParameters params; - params.protocol = "fake"; - params.parameters = "foobar"; - - TransportOptions options; - options.opaque_parameters = params; - - std::unique_ptr<TransportDescription> offer = - f1_.CreateOffer(options, NULL, &ice_credentials_); - std::unique_ptr<TransportDescription> answer = f2_.CreateAnswer( - offer.get(), TransportOptions(), true, NULL, &ice_credentials_); - - CheckDesc(answer.get(), "", "", "", ""); - EXPECT_EQ(answer->opaque_parameters, absl::nullopt); -} - -TEST_F(TransportDescriptionFactoryTest, - TestAnswerNoOpaqueTransportParametersInOffer) { - std::unique_ptr<TransportDescription> offer = - f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_); - - OpaqueTransportParameters params; - params.protocol = "fake"; - params.parameters = "foobar"; - - TransportOptions options; - options.opaque_parameters = params; - std::unique_ptr<TransportDescription> answer = - f2_.CreateAnswer(offer.get(), options, true, NULL, &ice_credentials_); - - CheckDesc(answer.get(), "", "", "", ""); - EXPECT_EQ(answer->opaque_parameters, absl::nullopt); -} - TEST_F(TransportDescriptionFactoryTest, TestAnswerDefault) { std::unique_ptr<TransportDescription> offer = f1_.CreateOffer(TransportOptions(), NULL, &ice_credentials_); diff --git a/chromium/third_party/webrtc/p2p/base/turn_port.cc b/chromium/third_party/webrtc/p2p/base/turn_port.cc index 2e8024dcb61..4d39f207b46 100644 --- a/chromium/third_party/webrtc/p2p/base/turn_port.cc +++ b/chromium/third_party/webrtc/p2p/base/turn_port.cc @@ -367,7 +367,7 @@ void TurnPort::PrepareAddress() { << server_address_.address.ToSensitiveString(); if (!CreateTurnClientSocket()) { RTC_LOG(LS_ERROR) << "Failed to create TURN client socket"; - OnAllocateError(STUN_ERROR_GLOBAL_FAILURE, + OnAllocateError(SERVER_NOT_REACHABLE_ERROR, "Failed to create TURN client socket."); return; } @@ -883,12 +883,17 @@ void TurnPort::OnAllocateError(int error_code, const std::string& reason) { // port initialization. This way it will not be blocking other port // creation. thread()->Post(RTC_FROM_HERE, this, MSG_ALLOCATE_ERROR); + std::string address = GetLocalAddress().HostAsSensitiveURIString(); + int port = GetLocalAddress().port(); + if (server_address_.proto == PROTO_TCP && + server_address_.address.IsPrivateIP()) { + address.clear(); + port = 0; + } SignalCandidateError( - this, - IceCandidateErrorEvent(GetLocalAddress().HostAsSensitiveURIString(), - GetLocalAddress().port(), - ReconstructedServerUrl(true /* use_hostname */), - error_code, reason)); + this, IceCandidateErrorEvent( + address, port, ReconstructedServerUrl(true /* use_hostname */), + error_code, reason)); } void TurnPort::OnRefreshError() { diff --git a/chromium/third_party/webrtc/p2p/base/turn_port_unittest.cc b/chromium/third_party/webrtc/p2p/base/turn_port_unittest.cc index 1f5a7bf49ed..ce86fe4a3a5 100644 --- a/chromium/third_party/webrtc/p2p/base/turn_port_unittest.cc +++ b/chromium/third_party/webrtc/p2p/base/turn_port_unittest.cc @@ -148,7 +148,7 @@ class TestConnectionWrapper : public sigslot::has_slots<> { // (between local port and TURN server) of kSimulatedRtt. class TurnPortTest : public ::testing::Test, public sigslot::has_slots<>, - public rtc::MessageHandler { + public rtc::MessageHandlerAutoCleanup { public: TurnPortTest() : ss_(new TurnPortTestVirtualSocketServer()), diff --git a/chromium/third_party/webrtc/p2p/base/turn_server.cc b/chromium/third_party/webrtc/p2p/base/turn_server.cc index 3a4784ac528..17a49e403de 100644 --- a/chromium/third_party/webrtc/p2p/base/turn_server.cc +++ b/chromium/third_party/webrtc/p2p/base/turn_server.cc @@ -59,7 +59,7 @@ enum { // Encapsulates a TURN permission. // The object is created when a create permission request is received by an // allocation, and self-deletes when its lifetime timer expires. -class TurnServerAllocation::Permission : public rtc::MessageHandler { +class TurnServerAllocation::Permission : public rtc::MessageHandlerAutoCleanup { public: Permission(rtc::Thread* thread, const rtc::IPAddress& peer); ~Permission() override; @@ -79,7 +79,7 @@ class TurnServerAllocation::Permission : public rtc::MessageHandler { // Encapsulates a TURN channel binding. // The object is created when a channel bind request is received by an // allocation, and self-deletes when its lifetime timer expires. -class TurnServerAllocation::Channel : public rtc::MessageHandler { +class TurnServerAllocation::Channel : public rtc::MessageHandlerAutoCleanup { public: Channel(rtc::Thread* thread, int id, const rtc::SocketAddress& peer); ~Channel() override; diff --git a/chromium/third_party/webrtc/p2p/base/turn_server.h b/chromium/third_party/webrtc/p2p/base/turn_server.h index 0f4fefea840..ca856448b3f 100644 --- a/chromium/third_party/webrtc/p2p/base/turn_server.h +++ b/chromium/third_party/webrtc/p2p/base/turn_server.h @@ -66,7 +66,7 @@ class TurnServerConnection { // handles TURN messages (via HandleTurnMessage) and channel data messages // (via HandleChannelData) for this allocation when received by the server. // The object self-deletes and informs the server if its lifetime timer expires. -class TurnServerAllocation : public rtc::MessageHandler, +class TurnServerAllocation : public rtc::MessageHandlerAutoCleanup, public sigslot::has_slots<> { public: TurnServerAllocation(TurnServer* server_, diff --git a/chromium/third_party/webrtc/p2p/client/basic_port_allocator.cc b/chromium/third_party/webrtc/p2p/client/basic_port_allocator.cc index 8aeef9361dd..bb640d9498d 100644 --- a/chromium/third_party/webrtc/p2p/client/basic_port_allocator.cc +++ b/chromium/third_party/webrtc/p2p/client/basic_port_allocator.cc @@ -979,8 +979,11 @@ void BasicPortAllocatorSession::OnCandidateError( const IceCandidateErrorEvent& event) { RTC_DCHECK_RUN_ON(network_thread_); RTC_DCHECK(FindPort(port)); - - SignalCandidateError(this, event); + if (event.address.empty()) { + candidate_error_events_.push_back(event); + } else { + SignalCandidateError(this, event); + } } Port* BasicPortAllocatorSession::GetBestTurnPortForNetwork( @@ -1140,6 +1143,10 @@ void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() { RTC_LOG(LS_INFO) << "All candidates gathered for " << content_name() << ":" << component() << ":" << generation(); } + for (const auto& event : candidate_error_events_) { + SignalCandidateError(this, event); + } + candidate_error_events_.clear(); SignalCandidatesAllocationDone(this); } } diff --git a/chromium/third_party/webrtc/p2p/client/basic_port_allocator.h b/chromium/third_party/webrtc/p2p/client/basic_port_allocator.h index b9f2b2ebd25..26b181807a7 100644 --- a/chromium/third_party/webrtc/p2p/client/basic_port_allocator.h +++ b/chromium/third_party/webrtc/p2p/client/basic_port_allocator.h @@ -106,8 +106,9 @@ enum class SessionState { // process will be started. }; -class RTC_EXPORT BasicPortAllocatorSession : public PortAllocatorSession, - public rtc::MessageHandler { +class RTC_EXPORT BasicPortAllocatorSession + : public PortAllocatorSession, + public rtc::MessageHandlerAutoCleanup { public: BasicPortAllocatorSession(BasicPortAllocator* allocator, const std::string& content_name, @@ -269,6 +270,7 @@ class RTC_EXPORT BasicPortAllocatorSession : public PortAllocatorSession, std::vector<PortConfiguration*> configs_; std::vector<AllocationSequence*> sequences_; std::vector<PortData> ports_; + std::vector<IceCandidateErrorEvent> candidate_error_events_; uint32_t candidate_filter_ = CF_ALL; // Policy on how to prune turn ports, taken from the port allocator. webrtc::PortPrunePolicy turn_port_prune_policy_; @@ -322,7 +324,7 @@ class TurnPort; // Performs the allocation of ports, in a sequenced (timed) manner, for a given // network and IP address. -class AllocationSequence : public rtc::MessageHandler, +class AllocationSequence : public rtc::MessageHandlerAutoCleanup, public sigslot::has_slots<> { public: enum State { |