xref: /aosp_15_r20/external/cronet/net/base/fuchsia/network_interface_cache.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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