• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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