Enable CallbackList constructor subscription and adopt in NetworkManager Update the CallbackList utility to allow subscribers to be added directly during instantiation. This adds new constructors that accept a callback, optionally with a removal tag, reducing the boilerplate required to set up subscriptions immediately after object creation and allows for removing multi-step initialization (that in some cases requires thread hops). As an initial accompanying change, the NetworkManager hierarchy—including NetworkManagerBase and BasicNetworkManager—has been updated to provide constructors that accept an initial network-change callback. This allows clients to subscribe to network updates at the moment of manager creation, simplifying initialization patterns and ensuring no events are missed during setup. Existing tests have been refactored to utilize these new constructor-based subscriptions. Bug: webrtc:42222117 Change-Id: If1b001bf36e6a246c3ea241b1685d79e3c3acaec Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/467740 Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org> Cr-Commit-Position: refs/heads/main@{#47570}
diff --git a/rtc_base/callback_list.h b/rtc_base/callback_list.h index 043ed00..96e83a3 100644 --- a/rtc_base/callback_list.h +++ b/rtc_base/callback_list.h
@@ -175,6 +175,12 @@ CallbackList(CallbackList&&) = delete; CallbackList& operator=(CallbackList&&) = delete; + // Adds a new receiver with removal tag in constructor. + template <typename F> + CallbackList(const void* removal_tag, F&& f) { + AddReceiver(removal_tag, std::forward<F>(f)); + } + // Adds a new receiver. The receiver (a callable object or a function pointer) // must be movable, but need not be copyable. Its call signature should be // `void(ArgT...)`. The removal tag is a pointer to an arbitrary object that
diff --git a/rtc_base/callback_list_unittest.cc b/rtc_base/callback_list_unittest.cc index 7c576ea..a5b0c41 100644 --- a/rtc_base/callback_list_unittest.cc +++ b/rtc_base/callback_list_unittest.cc
@@ -317,5 +317,16 @@ #pragma clang diagnostic pop +TEST(CallbackList, ConstructorSingleSubscriberWithTagTest) { + int removal_tag; + int accumulator = 0; + CallbackList<> c(&removal_tag, [&accumulator] { accumulator += 10; }); + c.Send(); + EXPECT_EQ(accumulator, 10); + c.RemoveReceivers(&removal_tag); + c.Send(); + EXPECT_EQ(accumulator, 10); // No change after removal. +} + } // namespace } // namespace webrtc
diff --git a/rtc_base/network.cc b/rtc_base/network.cc index f8ad220..e023bc8 100644 --- a/rtc_base/network.cc +++ b/rtc_base/network.cc
@@ -327,6 +327,12 @@ return nullptr; } +NetworkManager::NetworkManager(NetworksChangedCallback callback) { + RTC_CHECK(callback.callback != nullptr); + networks_changed_callbacks_.AddReceiver(callback.removal_tag, + std::move(callback.callback)); +} + void NetworkManager::SubscribeNetworksChanged( absl::AnyInvocable<void()> callback) { networks_changed_callbacks_.AddReceiver(std::move(callback)); @@ -354,6 +360,10 @@ NetworkManagerBase::NetworkManagerBase() : enumeration_permission_(NetworkManager::ENUMERATION_ALLOWED) {} +NetworkManagerBase::NetworkManagerBase(NetworksChangedCallback callback) + : NetworkManager(std::move(callback)), + enumeration_permission_(NetworkManager::ENUMERATION_ALLOWED) {} + NetworkManager::EnumerationPermission NetworkManagerBase::enumeration_permission() const { return enumeration_permission_; @@ -594,6 +604,22 @@ RTC_DCHECK(socket_factory_); } +BasicNetworkManager::BasicNetworkManager( + const Environment& env, + SocketFactory* absl_nonnull socket_factory, + NetworksChangedCallback callback, + NetworkMonitorFactory* absl_nullable network_monitor_factory) + : NetworkManagerBase(std::move(callback)), + env_(env), + network_monitor_factory_(network_monitor_factory), + socket_factory_(socket_factory), + allow_mac_based_ipv6_( + env_.field_trials().IsEnabled("WebRTC-AllowMACBasedIPv6")), + bind_using_ifname_( + !env_.field_trials().IsDisabled("WebRTC-BindUsingInterfaceName")) { + RTC_DCHECK(socket_factory_); +} + BasicNetworkManager::~BasicNetworkManager() { if (task_safety_flag_) { task_safety_flag_->SetNotAlive();
diff --git a/rtc_base/network.h b/rtc_base/network.h index 0190f49..3772371 100644 --- a/rtc_base/network.h +++ b/rtc_base/network.h
@@ -126,6 +126,13 @@ public MdnsResponderProvider { public: NetworkManager() = default; + // NetworksChangedCallback joins the removal tag and the callable. + struct NetworksChangedCallback { + const void* removal_tag; + absl::AnyInvocable<void()> callback; + }; + + explicit NetworkManager(NetworksChangedCallback callback); // This enum indicates whether adapter enumeration is allowed. enum EnumerationPermission { ENUMERATION_ALLOWED, // Adapter enumeration is allowed. Getting 0 network @@ -480,6 +487,7 @@ class RTC_EXPORT NetworkManagerBase : public NetworkManager { public: NetworkManagerBase(); + explicit NetworkManagerBase(NetworksChangedCallback callback); std::vector<const Network*> GetNetworks() const override; std::vector<const Network*> GetAnyAddressNetworks() override; @@ -555,6 +563,12 @@ SocketFactory* absl_nonnull socket_factory, NetworkMonitorFactory* absl_nullable network_monitor_factory = nullptr); + BasicNetworkManager( + const Environment& env, + SocketFactory* absl_nonnull socket_factory, + NetworksChangedCallback callback, + NetworkMonitorFactory* absl_nullable network_monitor_factory = nullptr); + ~BasicNetworkManager() override; void StartUpdating() override;
diff --git a/rtc_base/network_unittest.cc b/rtc_base/network_unittest.cc index e5697a5..5694358 100644 --- a/rtc_base/network_unittest.cc +++ b/rtc_base/network_unittest.cc
@@ -426,8 +426,8 @@ // ALLOWED. TEST_F(NetworkTest, TestUpdateNetworks) { PhysicalSocketServer socket_server; - BasicNetworkManager manager(env_, &socket_server); - manager.SubscribeNetworksChanged(this, [this] { OnNetworksChanged(); }); + BasicNetworkManager manager(env_, &socket_server, + {this, [this] { OnNetworksChanged(); }}); EXPECT_EQ(NetworkManager::ENUMERATION_ALLOWED, manager.enumeration_permission()); manager.StartUpdating(); @@ -572,8 +572,8 @@ // Test that the basic network merging case works. TEST_F(NetworkTest, TestIPv6MergeNetworkList) { PhysicalSocketServer socket_server; - BasicNetworkManager manager(env_, &socket_server); - manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); }); + BasicNetworkManager manager(env_, &socket_server, + {this, [this]() { OnNetworksChanged(); }}); std::vector<std::unique_ptr<Network>> networks; SetupNetworks(&networks); std::vector<const Network*> original_list = CopyNetworkPointers(networks); @@ -593,8 +593,8 @@ // objects remain in the result list. TEST_F(NetworkTest, TestNoChangeMerge) { PhysicalSocketServer socket_server; - BasicNetworkManager manager(env_, &socket_server); - manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); }); + BasicNetworkManager manager(env_, &socket_server, + {this, [this]() { OnNetworksChanged(); }}); std::vector<std::unique_ptr<Network>> networks; SetupNetworks(&networks); std::vector<const Network*> original_list = CopyNetworkPointers(networks); @@ -623,8 +623,8 @@ // IP changed. TEST_F(NetworkTest, MergeWithChangedIP) { PhysicalSocketServer socket_server; - BasicNetworkManager manager(env_, &socket_server); - manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); }); + BasicNetworkManager manager(env_, &socket_server, + {this, [this]() { OnNetworksChanged(); }}); std::vector<std::unique_ptr<Network>> original_list; SetupNetworks(&original_list); // Make a network that we're going to change. @@ -658,8 +658,8 @@ TEST_F(NetworkTest, TestMultipleIPMergeNetworkList) { PhysicalSocketServer socket_server; - BasicNetworkManager manager(env_, &socket_server); - manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); }); + BasicNetworkManager manager(env_, &socket_server, + {this, [this]() { OnNetworksChanged(); }}); std::vector<std::unique_ptr<Network>> original_list; SetupNetworks(&original_list); const Network* const network_ptr = original_list[2].get(); @@ -710,8 +710,8 @@ // Test that merge correctly distinguishes multiple networks on an interface. TEST_F(NetworkTest, TestMultiplePublicNetworksOnOneInterfaceMerge) { PhysicalSocketServer socket_server; - BasicNetworkManager manager(env_, &socket_server); - manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); }); + BasicNetworkManager manager(env_, &socket_server, + {this, [this]() { OnNetworksChanged(); }}); std::vector<std::unique_ptr<Network>> original_list; SetupNetworks(&original_list); bool changed = false; @@ -1244,8 +1244,9 @@ TEST_F(NetworkTest, TestNetworkMonitoring) { FakeNetworkMonitorFactory factory; PhysicalSocketServer socket_server; - BasicNetworkManager manager(env_, &socket_server, &factory); - manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); }); + BasicNetworkManager manager(env_, &socket_server, + {this, [this]() { OnNetworksChanged(); }}, + &factory); manager.StartUpdating(); FakeNetworkMonitor* network_monitor = GetNetworkMonitor(manager); EXPECT_TRUE(network_monitor && network_monitor->started()); @@ -1275,8 +1276,9 @@ IPAddress ip; FakeNetworkMonitorFactory factory; PhysicalSocketServer socket_server; - TestBasicNetworkManager manager(env_, &socket_server, &factory); - manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); }); + TestBasicNetworkManager manager(env_, &socket_server, + {this, [this]() { OnNetworksChanged(); }}, + &factory); manager.StartUpdating(); EXPECT_THAT(WaitUntil([&] { return callback_called_; }, IsTrue()), IsRtcOk());