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