1 // Copyright 2023 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_BASE_FUCHSIA_NETWORK_INTERFACE_CACHE_H_ 6 #define NET_BASE_FUCHSIA_NETWORK_INTERFACE_CACHE_H_ 7 8 #include <fuchsia/net/interfaces/cpp/fidl.h> 9 #include <stdint.h> 10 #include <zircon/errors.h> 11 12 #include "base/containers/flat_map.h" 13 #include "base/sequence_checker.h" 14 #include "base/thread_annotations.h" 15 #include "net/base/net_export.h" 16 #include "net/base/network_change_notifier.h" 17 #include "net/base/network_interfaces.h" 18 #include "net/base/network_interfaces_fuchsia.h" 19 #include "third_party/abseil-cpp/absl/types/optional.h" 20 21 namespace net::internal { 22 23 // Cache of network interfaces, keyed by unique interface IDs, kept up-to-date 24 // by NetworkChangeNotifierFuchsia. 25 // 26 // If `require_wlan` is `true`, only WLAN interfaces are observed. 27 // 28 // Can be accessed via `NetworkChangeNotifier::GetNetworkInterfaceCache()` to 29 // get the current list of networks. Methods that read the cache are 30 // thread-safe, but methods that modify the cache must be in sequence. 31 // 32 // NetworkInterfaceCache expects valid write operations only, and can go into 33 // unrecoverable error state if `SetError()` is called, or attempted to 34 // - Add an interface twice. 35 // - Add/Change an interface with incomplete properties. 36 // - Change/Remove an interface unknown to the cache. 37 // 38 // After entering error state, all subsequent write operations return 39 // `absl::nullopt`, and subsequent read operations will not return a result 40 // (specifically, `GetOnlineInterfaces` returns `false`, and `GetConnectionType` 41 // returns `CONNECTION_UNKNOWN`). 42 class NET_EXPORT_PRIVATE NetworkInterfaceCache { 43 public: 44 using ChangeBits = uint32_t; 45 enum : ChangeBits { 46 kNoChange = 0, 47 kIpAddressChanged = 1 << 0, 48 kConnectionTypeChanged = 1 << 1, 49 }; 50 51 explicit NetworkInterfaceCache(bool require_wlan); 52 ~NetworkInterfaceCache(); 53 54 NetworkInterfaceCache(const NetworkInterfaceCache&) = delete; 55 NetworkInterfaceCache& operator=(const NetworkInterfaceCache&) = delete; 56 57 // Returns `absl::nullopt` if any of the interfaces fail to be added. See 58 // `AddInterface`. 59 absl::optional<ChangeBits> AddInterfaces( 60 std::vector<fuchsia::net::interfaces::Properties> interfaces); 61 62 // Returns `absl::nullopt` if `properties` is invalid or incomplete, or if the 63 // interface already exists in the cache. 64 absl::optional<ChangeBits> AddInterface( 65 fuchsia::net::interfaces::Properties properties); 66 67 // Returns `absl::nullopt` if `properties` is invalid or does not contain an 68 // `id`, or if the interface does not exist in the cache. 69 absl::optional<ChangeBits> ChangeInterface( 70 fuchsia::net::interfaces::Properties properties); 71 72 // Returns `absl::nullopt` if `interface_id` does not exist in the cache. 73 absl::optional<ChangeBits> RemoveInterface( 74 InterfaceProperties::InterfaceId interface_id); 75 76 // Set cache to unrecoverable error state and clears the cache. 77 // Should be called when contents of the cache can no longer be updated to 78 // reflect the state of the system. 79 void SetError(); 80 81 // Thread-safe method that populates a list of online network interfaces. 82 // Ignores loopback interface. Returns `false` if in error state. 83 bool GetOnlineInterfaces(NetworkInterfaceList* networks) const; 84 85 // Thread-safe method that returns the current connection type. 86 // Returns `CONNECTION_UNKNOWN` if in error state. 87 NetworkChangeNotifier::ConnectionType GetConnectionType() const; 88 89 private: 90 // Updates `connection_type_` from `interfaces_` and returns `true` if 91 // the connection type changed. 92 bool UpdateConnectionTypeWhileLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_) 93 VALID_CONTEXT_REQUIRED(sequence_checker_); 94 95 absl::optional<ChangeBits> AddInterfaceWhileLocked( 96 fuchsia::net::interfaces::Properties properties) 97 EXCLUSIVE_LOCKS_REQUIRED(lock_) VALID_CONTEXT_REQUIRED(sequence_checker_); 98 99 void SetErrorWhileLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_) 100 VALID_CONTEXT_REQUIRED(sequence_checker_); 101 102 // Whether only WLAN interfaces should be taken into account. 103 const bool require_wlan_; 104 105 mutable base::Lock lock_; 106 107 base::flat_map<InterfaceProperties::InterfaceId, InterfaceProperties> 108 interfaces_ GUARDED_BY(lock_); 109 110 // The ConnectionType of the default network interface. 111 NetworkChangeNotifier::ConnectionType connection_type_ GUARDED_BY(lock_) = 112 NetworkChangeNotifier::CONNECTION_NONE; 113 114 // Set to true if any update is inconsistent with the network interfaces state 115 // that is currently cached. 116 bool error_state_ GUARDED_BY(lock_) = false; 117 118 SEQUENCE_CHECKER(sequence_checker_); 119 }; 120 121 } // namespace net::internal 122 123 #endif // NET_BASE_FUCHSIA_NETWORK_INTERFACE_CACHE_H_ 124