| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_BASE_FUCHSIA_NETWORK_INTERFACE_CACHE_H_ |
| #define NET_BASE_FUCHSIA_NETWORK_INTERFACE_CACHE_H_ |
| |
| #include <fuchsia/net/interfaces/cpp/fidl.h> |
| #include <stdint.h> |
| #include <zircon/errors.h> |
| |
| #include "base/containers/flat_map.h" |
| #include "base/sequence_checker.h" |
| #include "base/thread_annotations.h" |
| #include "net/base/net_export.h" |
| #include "net/base/network_change_notifier.h" |
| #include "net/base/network_interfaces.h" |
| #include "net/base/network_interfaces_fuchsia.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| namespace net::internal { |
| |
| // Cache of network interfaces, keyed by unique interface IDs, kept up-to-date |
| // by NetworkChangeNotifierFuchsia. |
| // |
| // If `require_wlan` is `true`, only WLAN interfaces are observed. |
| // |
| // Can be accessed via `NetworkChangeNotifier::GetNetworkInterfaceCache()` to |
| // get the current list of networks. Methods that read the cache are |
| // thread-safe, but methods that modify the cache must be in sequence. |
| // |
| // NetworkInterfaceCache expects valid write operations only, and can go into |
| // unrecoverable error state if `SetError()` is called, or attempted to |
| // - Add an interface twice. |
| // - Add/Change an interface with incomplete properties. |
| // - Change/Remove an interface unknown to the cache. |
| // |
| // After entering error state, all subsequent write operations return |
| // `absl::nullopt`, and subsequent read operations will not return a result |
| // (specifically, `GetOnlineInterfaces` returns `false`, and `GetConnectionType` |
| // returns `CONNECTION_UNKNOWN`). |
| class NET_EXPORT_PRIVATE NetworkInterfaceCache { |
| public: |
| using ChangeBits = uint32_t; |
| enum : ChangeBits { |
| kNoChange = 0, |
| kIpAddressChanged = 1 << 0, |
| kConnectionTypeChanged = 1 << 1, |
| }; |
| |
| explicit NetworkInterfaceCache(bool require_wlan); |
| ~NetworkInterfaceCache(); |
| |
| NetworkInterfaceCache(const NetworkInterfaceCache&) = delete; |
| NetworkInterfaceCache& operator=(const NetworkInterfaceCache&) = delete; |
| |
| // Returns `absl::nullopt` if any of the interfaces fail to be added. See |
| // `AddInterface`. |
| absl::optional<ChangeBits> AddInterfaces( |
| std::vector<fuchsia::net::interfaces::Properties> interfaces); |
| |
| // Returns `absl::nullopt` if `properties` is invalid or incomplete, or if the |
| // interface already exists in the cache. |
| absl::optional<ChangeBits> AddInterface( |
| fuchsia::net::interfaces::Properties properties); |
| |
| // Returns `absl::nullopt` if `properties` is invalid or does not contain an |
| // `id`, or if the interface does not exist in the cache. |
| absl::optional<ChangeBits> ChangeInterface( |
| fuchsia::net::interfaces::Properties properties); |
| |
| // Returns `absl::nullopt` if `interface_id` does not exist in the cache. |
| absl::optional<ChangeBits> RemoveInterface( |
| InterfaceProperties::InterfaceId interface_id); |
| |
| // Set cache to unrecoverable error state and clears the cache. |
| // Should be called when contents of the cache can no longer be updated to |
| // reflect the state of the system. |
| void SetError(); |
| |
| // Thread-safe method that populates a list of online network interfaces. |
| // Ignores loopback interface. Returns `false` if in error state. |
| bool GetOnlineInterfaces(NetworkInterfaceList* networks) const; |
| |
| // Thread-safe method that returns the current connection type. |
| // Returns `CONNECTION_UNKNOWN` if in error state. |
| NetworkChangeNotifier::ConnectionType GetConnectionType() const; |
| |
| private: |
| // Updates `connection_type_` from `interfaces_` and returns `true` if |
| // the connection type changed. |
| bool UpdateConnectionTypeWhileLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_) |
| VALID_CONTEXT_REQUIRED(sequence_checker_); |
| |
| absl::optional<ChangeBits> AddInterfaceWhileLocked( |
| fuchsia::net::interfaces::Properties properties) |
| EXCLUSIVE_LOCKS_REQUIRED(lock_) VALID_CONTEXT_REQUIRED(sequence_checker_); |
| |
| void SetErrorWhileLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_) |
| VALID_CONTEXT_REQUIRED(sequence_checker_); |
| |
| // Whether only WLAN interfaces should be taken into account. |
| const bool require_wlan_; |
| |
| mutable base::Lock lock_; |
| |
| base::flat_map<InterfaceProperties::InterfaceId, InterfaceProperties> |
| interfaces_ GUARDED_BY(lock_); |
| |
| // The ConnectionType of the default network interface. |
| NetworkChangeNotifier::ConnectionType connection_type_ GUARDED_BY(lock_) = |
| NetworkChangeNotifier::CONNECTION_NONE; |
| |
| // Set to true if any update is inconsistent with the network interfaces state |
| // that is currently cached. |
| bool error_state_ GUARDED_BY(lock_) = false; |
| |
| SEQUENCE_CHECKER(sequence_checker_); |
| }; |
| |
| } // namespace net::internal |
| |
| #endif // NET_BASE_FUCHSIA_NETWORK_INTERFACE_CACHE_H_ |