124 lines
4.7 KiB
C
124 lines
4.7 KiB
C
|
|
// 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_
|