blob: 685307976fc4dd17083d7f57528e2c9b5330cc5a [file] [log] [blame]
// 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_