Commit 022c5b0e authored by Marina Ciocea's avatar Marina Ciocea Committed by Commit Bot

[fuchsia] Migrate to fuchsia.net.interfaces/State

Fixed: fuchsia:21155
Change-Id: I85b388be33d4c9697ba866cf11a143493b2b3239
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2380329Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarAdam Langley <agl@chromium.org>
Reviewed-by: default avatarSergey Volk <servolk@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Commit-Queue: Marina Ciocea <marinaciocea@chromium.org>
Cr-Commit-Position: refs/heads/master@{#828229}
parent 62ce5fc8
{
"sandbox": {
"dev": [
"null",
"zero"
],
"features": [
"deprecated-ambient-replace-as-executable",
"isolated-cache-storage",
......@@ -8,10 +12,6 @@
"root-ssl-certificates",
"vulkan"
],
"dev": [
"null",
"zero"
],
"services": [
"fuchsia.accessibility.semantics.SemanticsManager",
"fuchsia.camera3.DeviceWatcher",
......@@ -26,7 +26,7 @@
"fuchsia.mediacodec.CodecFactory",
"fuchsia.memorypressure.Provider",
"fuchsia.net.NameLookup",
"fuchsia.netstack.Netstack",
"fuchsia.net.interfaces.State",
"fuchsia.posix.socket.Provider",
"fuchsia.process.Launcher",
"fuchsia.sys.Environment",
......
{
"sandbox": {
"dev": [
"null",
"zero"
],
"features": [
"config-data",
"isolated-cache-storage",
......@@ -8,10 +12,6 @@
"root-ssl-certificates",
"vulkan"
],
"dev": [
"null",
"zero"
],
"services": [
"fuchsia.accessibility.semantics.SemanticsManager",
"fuchsia.camera3.DeviceWatcher",
......@@ -26,7 +26,7 @@
"fuchsia.mediacodec.CodecFactory",
"fuchsia.memorypressure.Provider",
"fuchsia.net.NameLookup",
"fuchsia.netstack.Netstack",
"fuchsia.net.interfaces.State",
"fuchsia.posix.socket.Provider",
"fuchsia.process.Launcher",
"fuchsia.sys.Environment",
......
......@@ -32,10 +32,7 @@ cast_source_set("net") {
"network_change_notifier_factory_fuchsia.h",
]
deps += [
"//chromecast/base:chromecast_switches",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.hardware.ethernet",
]
deps += [ "//chromecast/base:chromecast_switches" ]
}
}
......@@ -51,9 +48,7 @@ cast_source_set("time_sync_tracker") {
"time_sync_tracker.cc",
"time_sync_tracker.h",
]
deps = [
"//base",
]
deps = [ "//base" ]
if (is_fuchsia) {
sources += [
......
......@@ -4,8 +4,6 @@
#include "chromecast/net/network_change_notifier_factory_fuchsia.h"
#include <fuchsia/hardware/ethernet/cpp/fidl.h>
#include "base/command_line.h"
#include "chromecast/base/chromecast_switches.h"
#include "net/base/network_change_notifier_fuchsia.h"
......@@ -14,12 +12,10 @@ namespace chromecast {
std::unique_ptr<net::NetworkChangeNotifier>
NetworkChangeNotifierFactoryFuchsia::CreateInstance() {
auto required_features = GetSwitchValueBoolean(switches::kRequireWlan, false)
? fuchsia::hardware::ethernet::Features::WLAN
: fuchsia::hardware::ethernet::Features();
auto require_wlan = GetSwitchValueBoolean(switches::kRequireWlan, false);
// Caller assumes ownership.
return std::make_unique<net::NetworkChangeNotifierFuchsia>(required_features);
return std::make_unique<net::NetworkChangeNotifierFuchsia>(require_wlan);
}
NetworkChangeNotifierFactoryFuchsia::NetworkChangeNotifierFactoryFuchsia() =
......
......@@ -19,7 +19,7 @@
"fuchsia.mediacodec.CodecFactory",
"fuchsia.memorypressure.Provider",
"fuchsia.net.NameLookup",
"fuchsia.netstack.Netstack",
"fuchsia.net.interfaces.State",
"fuchsia.posix.socket.Provider",
"fuchsia.process.Launcher",
"fuchsia.sys.Launcher",
......@@ -31,4 +31,4 @@
"fuchsia.vulkan.loader.Loader"
]
}
}
\ No newline at end of file
}
{
"sandbox": {
"features": [
"isolated-persistent-storage",
"deprecated-ambient-replace-as-executable"
"deprecated-ambient-replace-as-executable",
"isolated-persistent-storage"
],
"services": [
"fuchsia.accessibility.semantics.SemanticsManager",
......@@ -17,7 +17,7 @@
"fuchsia.mediacodec.CodecFactory",
"fuchsia.memorypressure.Provider",
"fuchsia.net.NameLookup",
"fuchsia.netstack.Netstack",
"fuchsia.net.interfaces.State",
"fuchsia.posix.socket.Provider",
"fuchsia.process.Launcher",
"fuchsia.sys.Launcher",
......
......@@ -16,7 +16,7 @@
"fuchsia.media.SessionAudioConsumerFactory",
"fuchsia.memorypressure.Provider",
"fuchsia.net.NameLookup",
"fuchsia.netstack.Netstack",
"fuchsia.net.interfaces.State",
"fuchsia.posix.socket.Provider",
"fuchsia.process.Launcher",
"fuchsia.sys.Launcher",
......
per-file *.cmx=set noparent
per-file *.cmx=file://fuchsia/SECURITY_OWNERS
{
"sandbox": {
"features": [
"root-ssl-certificates",
"deprecated-ambient-replace-as-executable"
"deprecated-ambient-replace-as-executable",
"root-ssl-certificates"
],
"services": [
"fuchsia.device.NameProvider",
"fuchsia.intl.PropertyProvider",
"fuchsia.logger.LogSink",
"fuchsia.net.NameLookup",
"fuchsia.netstack.Netstack",
"fuchsia.net.interfaces.State",
"fuchsia.posix.socket.Provider"
]
}
......
......@@ -40,7 +40,7 @@ static constexpr const char* kServices[] = {
"fuchsia.mediacodec.CodecFactory",
"fuchsia.memorypressure.Provider",
"fuchsia.net.NameLookup",
"fuchsia.netstack.Netstack",
"fuchsia.net.interfaces.State",
"fuchsia.posix.socket.Provider",
"fuchsia.process.Launcher",
"fuchsia.settings.Display",
......
......@@ -20,7 +20,7 @@
"fuchsia.mediacodec.CodecFactory",
"fuchsia.memorypressure.Provider",
"fuchsia.net.NameLookup",
"fuchsia.netstack.Netstack",
"fuchsia.net.interfaces.State",
"fuchsia.posix.socket.Provider",
"fuchsia.process.Launcher",
"fuchsia.settings.Display",
......
......@@ -5,8 +5,8 @@
],
"services": [
"fuchsia.accessibility.semantics.SemanticsManager",
"fuchsia.device.NameProvider",
"fuchsia.camera3.DeviceWatcher",
"fuchsia.device.NameProvider",
"fuchsia.fonts.Provider",
"fuchsia.intl.PropertyProvider",
"fuchsia.logger.LogSink",
......@@ -16,7 +16,7 @@
"fuchsia.mediacodec.CodecFactory",
"fuchsia.memorypressure.Provider",
"fuchsia.net.NameLookup",
"fuchsia.netstack.Netstack",
"fuchsia.net.interfaces.State",
"fuchsia.posix.socket.Provider",
"fuchsia.process.Launcher",
"fuchsia.sysmem.Allocator",
......
......@@ -1456,7 +1456,8 @@ component("net") {
if (is_fuchsia) {
deps += [ "//third_party/fuchsia-sdk/sdk/pkg/async-loop-cpp" ]
public_deps += [ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.netstack" ]
public_deps +=
[ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.net.interfaces" ]
sources += [
"base/network_change_notifier_fuchsia.cc",
"base/network_change_notifier_fuchsia.h",
......@@ -1708,8 +1709,8 @@ source_set("net_deps") {
if (is_fuchsia) {
public_deps += [
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.hardware.ethernet",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.netstack",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.hardware.network",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.net.interfaces",
"//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
]
}
......@@ -4625,7 +4626,7 @@ test("net_unittests") {
if (is_fuchsia) {
use_test_server = true
deps += [
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.netstack",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.net.interfaces",
"//third_party/fuchsia-sdk/sdk/pkg/fidl_cpp",
]
sources += [ "base/network_change_notifier_fuchsia_unittest.cc" ]
......
......@@ -248,7 +248,7 @@ std::unique_ptr<NetworkChangeNotifier> NetworkChangeNotifier::CreateIfNeeded(
return std::make_unique<NetworkChangeNotifierMac>();
#elif defined(OS_FUCHSIA)
return std::make_unique<NetworkChangeNotifierFuchsia>(
fuchsia::hardware::ethernet::Features());
/*require_wlan=*/false);
#else
NOTIMPLEMENTED();
return NULL;
......
......@@ -4,63 +4,63 @@
#include "net/base/network_change_notifier_fuchsia.h"
#include <lib/async-loop/cpp/loop.h>
#include <lib/sys/cpp/component_context.h>
#include <algorithm>
#include <iterator>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/fuchsia/process_context.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "net/base/network_interfaces.h"
#include "net/base/network_interfaces_fuchsia.h"
#include "base/strings/stringprintf.h"
namespace net {
NetworkChangeNotifierFuchsia::NetworkChangeNotifierFuchsia(
fuchsia::hardware::ethernet::Features required_features)
: NetworkChangeNotifierFuchsia(base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::netstack::Netstack>(),
required_features) {}
NetworkChangeNotifierFuchsia::NetworkChangeNotifierFuchsia(bool require_wlan)
: NetworkChangeNotifierFuchsia(internal::ConnectInterfacesWatcher(),
require_wlan) {}
NetworkChangeNotifierFuchsia::NetworkChangeNotifierFuchsia(
fidl::InterfaceHandle<fuchsia::netstack::Netstack> netstack,
fuchsia::hardware::ethernet::Features required_features,
fidl::InterfaceHandle<fuchsia::net::interfaces::Watcher> handle,
bool require_wlan,
SystemDnsConfigChangeNotifier* system_dns_config_notifier)
: NetworkChangeNotifier(NetworkChangeCalculatorParams(),
system_dns_config_notifier),
required_features_(required_features) {
DCHECK(netstack);
require_wlan_(require_wlan) {
DCHECK(handle);
netstack_.set_error_handler([](zx_status_t status) {
ZX_LOG(FATAL, status) << "Lost connection to netstack.";
});
watcher_.set_error_handler(
[](zx_status_t status) {
ZX_LOG(FATAL, status)
<< "Lost connection to fuchsia.net.interfaces/Watcher.";
});
netstack_.events().OnInterfacesChanged = fit::bind_member(
this, &NetworkChangeNotifierFuchsia::ProcessInterfaceList);
fuchsia::net::interfaces::WatcherSyncPtr watcher = handle.BindSync();
base::Optional<internal::ExistingInterfaceProperties> interfaces =
internal::GetExistingInterfaces(watcher);
if (!interfaces) {
ZX_LOG(ERROR, ZX_ERR_INVALID_ARGS) << "Failed to load existing interfaces";
return;
}
handle = watcher.Unbind();
bool notify_ip_address_changed = false;
for (const auto& interface_entry : *interfaces) {
notify_ip_address_changed |=
CanReachExternalNetwork(interface_entry.second);
}
interface_cache_ = InterfacePropertiesMap(std::move(*interfaces));
// Temporarily bind to a local dispatcher so we can synchronously wait for the
// synthetic event to populate the initial state.
async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
zx_status_t status = netstack_.Bind(std::move(netstack), loop.dispatcher());
ZX_CHECK(status == ZX_OK, status) << "Bind()";
on_initial_interfaces_received_ =
base::BindOnce(&async::Loop::Quit, base::Unretained(&loop));
status = loop.Run();
ZX_CHECK(status == ZX_ERR_CANCELED, status) << "loop.Run()";
UpdateConnectionType();
if (notify_ip_address_changed) {
NotifyObserversOfIPAddressChange();
}
// Bind to the dispatcher for the thread's MessagePump.
//
// Note this must be done before |loop| is destroyed, since that would close
// the interface handle underlying |netstack_|.
status = netstack_.Bind(netstack_.Unbind());
zx_status_t status = watcher_.Bind(std::move(handle));
ZX_CHECK(status == ZX_OK, status) << "Bind()";
watcher_->Watch(
fit::bind_member(this, &NetworkChangeNotifierFuchsia::OnInterfacesEvent));
}
NetworkChangeNotifierFuchsia::~NetworkChangeNotifierFuchsia() {
......@@ -75,80 +75,146 @@ NetworkChangeNotifierFuchsia::GetCurrentConnectionType() const {
return type;
}
void NetworkChangeNotifierFuchsia::ProcessInterfaceList(
std::vector<fuchsia::netstack::NetInterface> interfaces) {
netstack_->GetRouteTable(
[this, interfaces = std::move(interfaces)](
std::vector<fuchsia::netstack::RouteTableEntry> route_table) mutable {
OnRouteTableReceived(std::move(interfaces), std::move(route_table));
});
void NetworkChangeNotifierFuchsia::OnInterfacesEvent(
fuchsia::net::interfaces::Event event) {
// Immediately trigger the next watch, which will happen asynchronously. If
// event processing encounters an error it'll close the watcher channel which
// will cancel any pending callbacks.
watcher_->Watch(
fit::bind_member(this, &NetworkChangeNotifierFuchsia::OnInterfacesEvent));
switch (event.Which()) {
case fuchsia::net::interfaces::Event::kAdded:
OnInterfaceAdded(std::move(event.added()));
break;
case fuchsia::net::interfaces::Event::kRemoved:
OnInterfaceRemoved(event.removed());
break;
case fuchsia::net::interfaces::Event::kChanged:
OnInterfaceChanged(std::move(event.changed()));
break;
case fuchsia::net::interfaces::Event::kExisting:
case fuchsia::net::interfaces::Event::kIdle:
OnWatcherError(base::StringPrintf(
"OnInterfaceEvent: unexpected event %lu.", event.Which()));
break;
case fuchsia::net::interfaces::Event::Invalid:
LOG(WARNING)
<< "Invalid event received from fuchsia.net.interfaces/Watcher";
break;
}
}
void NetworkChangeNotifierFuchsia::OnRouteTableReceived(
std::vector<fuchsia::netstack::NetInterface> interfaces,
std::vector<fuchsia::netstack::RouteTableEntry> route_table) {
// Create a set of NICs that have default routes (ie 0.0.0.0).
base::flat_set<uint32_t> default_route_ids;
for (const auto& route : route_table) {
if (MaskPrefixLength(
internal::FuchsiaIpAddressToIPAddress(route.netmask)) == 0) {
default_route_ids.insert(route.nicid);
}
void NetworkChangeNotifierFuchsia::OnInterfaceAdded(
fuchsia::net::interfaces::Properties properties) {
base::Optional<internal::InterfaceProperties> cache_entry =
internal::InterfaceProperties::VerifyAndCreate(std::move(properties));
if (!cache_entry) {
OnWatcherError("OnInterfaceAdded: incomplete interface properties.");
return;
}
uint64_t id = properties.id();
if (interface_cache_.find(id) != interface_cache_.end()) {
OnWatcherError(base::StringPrintf(
"OnInterfaceAdded: duplicate interface ID %lu.", id));
return;
}
const bool can_reach = CanReachExternalNetwork(*cache_entry);
interface_cache_.emplace(id, std::move(*cache_entry));
UpdateConnectionType();
if (can_reach) {
NotifyObserversOfIPAddressChange();
}
}
ConnectionType connection_type = CONNECTION_NONE;
base::flat_set<IPAddress> addresses;
for (auto& interface : interfaces) {
// Filter out loopback and invalid connection types.
if ((internal::ConvertConnectionType(interface) ==
NetworkChangeNotifier::CONNECTION_NONE) ||
(interface.features &
fuchsia::hardware::ethernet::Features::LOOPBACK) ==
fuchsia::hardware::ethernet::Features::LOOPBACK) {
continue;
}
// Filter out interfaces that do not meet the |required_features_|.
if ((interface.features & required_features_) != required_features_) {
continue;
}
// Filter out interfaces with non-default routes.
if (!default_route_ids.contains(interface.id)) {
continue;
}
std::vector<NetworkInterface> flattened_interfaces =
internal::NetInterfaceToNetworkInterfaces(interface);
if (flattened_interfaces.empty()) {
continue;
}
// Add the addresses from this interface to the list of all addresses.
std::transform(
flattened_interfaces.begin(), flattened_interfaces.end(),
std::inserter(addresses, addresses.begin()),
[](const NetworkInterface& interface) { return interface.address; });
void NetworkChangeNotifierFuchsia::OnInterfaceRemoved(uint64_t interface_id) {
InterfacePropertiesMap::iterator cache_entry =
interface_cache_.find(interface_id);
if (cache_entry == interface_cache_.end()) {
OnWatcherError(base::StringPrintf(
"OnInterfaceRemoved: unknown interface ID %lu.", interface_id));
return;
}
const bool can_reach = CanReachExternalNetwork(cache_entry->second);
interface_cache_.erase(cache_entry);
UpdateConnectionType();
if (can_reach) {
NotifyObserversOfIPAddressChange();
}
}
// Set the default connection to the first interface connection found.
if (connection_type == CONNECTION_NONE) {
connection_type = flattened_interfaces.front().type;
}
void NetworkChangeNotifierFuchsia::OnInterfaceChanged(
fuchsia::net::interfaces::Properties properties) {
if (!properties.has_id()) {
OnWatcherError("OnInterfaceChanged: no interface ID.");
return;
}
const uint64_t id = properties.id();
InterfacePropertiesMap::iterator cache_entry = interface_cache_.find(id);
if (cache_entry == interface_cache_.end()) {
OnWatcherError(base::StringPrintf(
"OnInterfaceChanged: unknown interface ID %lu.", id));
return;
}
const bool old_can_reach = CanReachExternalNetwork(cache_entry->second);
const bool has_addresses = properties.has_addresses();
if (!cache_entry->second.Update(std::move(properties))) {
OnWatcherError("OnInterfaceChanged: update failed.");
return;
}
if (addresses != cached_addresses_) {
std::swap(cached_addresses_, addresses);
UpdateConnectionType();
const bool can_reach = CanReachExternalNetwork(cache_entry->second);
if (has_addresses || old_can_reach != can_reach) {
NotifyObserversOfIPAddressChange();
}
}
if (connection_type != cached_connection_type_) {
void NetworkChangeNotifierFuchsia::OnWatcherError(
base::StringPiece error_message) {
LOG(ERROR) << error_message;
watcher_.Unbind();
ResetConnectionType();
}
void NetworkChangeNotifierFuchsia::UpdateConnectionType() {
ConnectionType connection_type = ConnectionType::CONNECTION_NONE;
for (const auto& interface : interface_cache_) {
if (CanReachExternalNetwork(interface.second)) {
connection_type = GetEffectiveConnectionType(interface.second);
break;
}
}
if (connection_type != GetCurrentConnectionType()) {
base::subtle::Release_Store(&cached_connection_type_, connection_type);
NotifyObserversOfConnectionTypeChange();
}
}
if (on_initial_interfaces_received_) {
std::move(on_initial_interfaces_received_).Run();
void NetworkChangeNotifierFuchsia::ResetConnectionType() {
base::subtle::Release_Store(&cached_connection_type_,
ConnectionType::CONNECTION_UNKNOWN);
}
NetworkChangeNotifier::ConnectionType
NetworkChangeNotifierFuchsia::GetEffectiveConnectionType(
const internal::InterfaceProperties& properties) {
if (!properties.IsPubliclyRoutable())
return NetworkChangeNotifier::CONNECTION_NONE;
NetworkChangeNotifier::ConnectionType connection_type =
internal::ConvertConnectionType(properties.device_class());
if (require_wlan_ &&
connection_type != NetworkChangeNotifier::CONNECTION_WIFI) {
return NetworkChangeNotifier::CONNECTION_NONE;
}
return connection_type;
}
bool NetworkChangeNotifierFuchsia::CanReachExternalNetwork(
const internal::InterfaceProperties& properties) {
return GetEffectiveConnectionType(properties) !=
NetworkChangeNotifier::CONNECTION_NONE;
}
} // namespace net
......@@ -5,19 +5,21 @@
#ifndef NET_BASE_NETWORK_CHANGE_NOTIFIER_FUCHSIA_H_
#define NET_BASE_NETWORK_CHANGE_NOTIFIER_FUCHSIA_H_
#include <fuchsia/netstack/cpp/fidl.h>
#include <fuchsia/net/interfaces/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <vector>
#include "base/atomicops.h"
#include "base/callback.h"
#include "base/containers/flat_set.h"
#include "base/containers/flat_map.h"
#include "base/gtest_prod_util.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread_checker.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"
namespace net {
......@@ -25,9 +27,8 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierFuchsia
: public NetworkChangeNotifier {
public:
// Registers for asynchronous notifications of changes to network interfaces.
// Interfaces are filtered by |required_features|.
explicit NetworkChangeNotifierFuchsia(
fuchsia::hardware::ethernet::Features required_features);
// Only WLAN interfaces are observed if |require_wlan| is requested.
explicit NetworkChangeNotifierFuchsia(bool require_wlan);
NetworkChangeNotifierFuchsia(const NetworkChangeNotifierFuchsia&) = delete;
NetworkChangeNotifierFuchsia& operator=(const NetworkChangeNotifierFuchsia&) =
delete;
......@@ -37,42 +38,55 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierFuchsia
ConnectionType GetCurrentConnectionType() const override;
private:
using InterfacePropertiesMap =
base::flat_map<uint64_t, internal::InterfaceProperties>;
friend class NetworkChangeNotifierFuchsiaTest;
// For testing purposes. Receives a |netstack| pointer for easy mocking.
// Interfaces are filtered by |required_features|.
NetworkChangeNotifierFuchsia(
fidl::InterfaceHandle<fuchsia::netstack::Netstack> netstack,
fuchsia::hardware::ethernet::Features required_features,
fidl::InterfaceHandle<fuchsia::net::interfaces::Watcher> watcher,
bool require_wlan,
SystemDnsConfigChangeNotifier* system_dns_config_notifier = nullptr);
// Forwards the network interface list along with the result of
// GetRouteTable() to OnRouteTableReceived().
void ProcessInterfaceList(
std::vector<fuchsia::netstack::NetInterface> interfaces);
// Processes events from the watcher for interface addition, change, or
// removal.
void OnInterfacesEvent(fuchsia::net::interfaces::Event event);
// Computes network change notification state change from the list of
// interfaces and routing table data, sending observer events if IP or
// connection type changes are detected.
void OnRouteTableReceived(
std::vector<fuchsia::netstack::NetInterface> interfaces,
std::vector<fuchsia::netstack::RouteTableEntry> table);
// Handlers for the interface change events. Listeners are notified of changes
// that affect them. |watcher_| is closed if an event is malformed in some
// way.
void OnInterfaceAdded(fuchsia::net::interfaces::Properties properties);
void OnInterfaceRemoved(uint64_t interface_id);
void OnInterfaceChanged(fuchsia::net::interfaces::Properties properties);
// Required features for an interface to be taken into account.
const fuchsia::hardware::ethernet::Features required_features_;
// Unbinds the watcher, reset the connection type and logs |error_message|.
void OnWatcherError(base::StringPiece error_message);
fuchsia::netstack::NetstackPtr netstack_;
// Updates the connection type from |interface_cache_| and notifies observers
// of changes.
void UpdateConnectionType();
// Used to allow the constructor to block until the initial state is received
// from |netstack_|.
base::OnceClosure on_initial_interfaces_received_;
// Resets the connection type to CONNECTION_UNKNOWN.
void ResetConnectionType();
// Returns the ConnectionType converted from |properties|' device_class.
// Returns CONNECTION_NONE if the interface is not publicly routable, taking
// into account the |requires_wlan_| setting.
ConnectionType GetEffectiveConnectionType(
const internal::InterfaceProperties& properties);
// Returns true if the effective connection type is not CONNECTION_NONE.
bool CanReachExternalNetwork(const internal::InterfaceProperties& properties);
// Whether only WLAN interfaces should be taken into account.
const bool require_wlan_;
fuchsia::net::interfaces::WatcherPtr watcher_;
// The ConnectionType of the default network interface, stored as an atomic
// 32-bit int for safe concurrent access.
base::subtle::Atomic32 cached_connection_type_ = CONNECTION_UNKNOWN;
// Set of addresses from the previous query/update for the default interface.
base::flat_set<IPAddress> cached_addresses_;
InterfacePropertiesMap interface_cache_;
THREAD_CHECKER(thread_checker_);
};
......
......@@ -4,8 +4,7 @@
#include "net/base/network_change_notifier_fuchsia.h"
#include <fuchsia/hardware/ethernet/cpp/fidl.h>
#include <fuchsia/netstack/cpp/fidl_test_base.h>
#include <fuchsia/net/interfaces/cpp/fidl_test_base.h>
#include <memory>
#include <string>
#include <utility>
......@@ -32,18 +31,15 @@ enum : uint32_t { kDefaultInterfaceId = 1, kSecondaryInterfaceId = 2 };
using IPv4Octets = std::array<uint8_t, 4>;
using IPv6Octets = std::array<uint8_t, 16>;
constexpr IPv4Octets kIPv4DefaultGatewayNetmask = {0, 0, 0, 0};
constexpr IPv4Octets kIPv4DefaultGatewayAddress = {192, 168, 0, 1};
constexpr IPv4Octets kDefaultIPv4Address = {192, 168, 0, 2};
constexpr IPv4Octets kDefaultIPv4Netmask = {255, 255, 0, 0};
constexpr uint8_t kDefaultIPv4Prefix = 16;
constexpr IPv4Octets kSecondaryIPv4Address = {10, 0, 0, 1};
constexpr IPv4Octets kSecondaryIPv4Netmask = {255, 0, 0, 0};
constexpr uint8_t kSecondaryIPv4Prefix = 8;
constexpr IPv6Octets kDefaultIPv6Address = {0xfe, 0x80, 0x01};
constexpr IPv6Octets kDefaultIPv6Netmask = {0xfe, 0x80};
constexpr IPv6Octets kSecondaryIPv6Address = {0xfe, 0x80, 0x02};
constexpr IPv6Octets kSecondaryIPv6Netmask = {0xfe, 0x80};
constexpr IPv6Octets kDefaultIPv6Address = {0x20, 0x01, 0x01};
constexpr uint8_t kDefaultIPv6Prefix = 16;
constexpr IPv6Octets kSecondaryIPv6Address = {0x20, 0x01, 0x02};
constexpr uint8_t kSecondaryIPv6Prefix = 16;
fuchsia::net::IpAddress IpAddressFrom(IPv4Octets octets) {
fuchsia::net::IpAddress output;
......@@ -57,130 +53,165 @@ fuchsia::net::IpAddress IpAddressFrom(IPv6Octets octets) {
return output;
}
fuchsia::net::Subnet SubnetFrom(IPv6Octets octets, uint8_t prefix) {
template <typename T>
fuchsia::net::Subnet SubnetFrom(T octets, uint8_t prefix) {
fuchsia::net::Subnet output;
output.addr = IpAddressFrom(octets);
output.prefix_len = prefix;
return output;
}
fuchsia::netstack::NetInterface DefaultNetInterface() {
// For most tests a live interface with an IPv4 address and no |features| set
template <typename T>
fuchsia::net::interfaces::Address InterfaceAddressFrom(T octets,
uint8_t prefix) {
fuchsia::net::interfaces::Address addr;
addr.set_addr(SubnetFrom(octets, prefix));
return addr;
}
template <typename T>
std::vector<T> MakeSingleItemVec(T item) {
std::vector<T> vec;
vec.push_back(std::move(item));
return vec;
}
fuchsia::net::interfaces::Properties DefaultInterfaceProperties(
fuchsia::hardware::network::DeviceClass device_class =
fuchsia::hardware::network::DeviceClass::UNKNOWN) {
// For most tests a live interface with an IPv4 address and an unknown class
// is sufficient.
fuchsia::netstack::NetInterface interface;
interface.id = kDefaultInterfaceId;
interface.flags = fuchsia::netstack::Flags::UP;
interface.features = {};
interface.addr = IpAddressFrom(kDefaultIPv4Address);
interface.netmask = IpAddressFrom(kDefaultIPv4Netmask);
interface.broadaddr = IpAddressFrom(kDefaultIPv4Address);
fuchsia::net::interfaces::Properties interface;
interface.set_id(kDefaultInterfaceId);
interface.set_online(true);
interface.set_has_default_ipv4_route(true);
interface.set_has_default_ipv6_route(true);
interface.set_device_class(fuchsia::net::interfaces::DeviceClass::WithDevice(
std::move(device_class)));
interface.set_addresses(MakeSingleItemVec(
InterfaceAddressFrom(kDefaultIPv4Address, kDefaultIPv4Prefix)));
return interface;
}
fuchsia::netstack::NetInterface SecondaryNetInterface() {
// For most tests a live interface with an IPv4 address and no |features| set
fuchsia::net::interfaces::Properties SecondaryInterfaceProperties() {
// For most tests a live interface with an IPv4 address and an unknown class
// is sufficient.
fuchsia::netstack::NetInterface interface;
interface.id = kSecondaryInterfaceId;
interface.flags = fuchsia::netstack::Flags::UP;
interface.features = {};
interface.addr = IpAddressFrom(kSecondaryIPv4Address);
interface.netmask = IpAddressFrom(kSecondaryIPv4Netmask);
interface.broadaddr = IpAddressFrom(kSecondaryIPv4Address);
fuchsia::net::interfaces::Properties interface;
interface.set_id(kSecondaryInterfaceId);
interface.set_online(true);
interface.set_has_default_ipv4_route(false);
interface.set_has_default_ipv6_route(false);
interface.set_device_class(fuchsia::net::interfaces::DeviceClass::WithDevice(
fuchsia::hardware::network::DeviceClass::UNKNOWN));
interface.set_addresses(MakeSingleItemVec(
InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
return interface;
}
std::vector<fuchsia::netstack::NetInterface> CloneNetInterfaces(
const std::vector<fuchsia::netstack::NetInterface>& interfaces) {
std::vector<fuchsia::netstack::NetInterface> interfaces_copy(
interfaces.size());
for (size_t i = 0; i < interfaces.size(); ++i) {
CHECK_EQ(ZX_OK, interfaces[i].Clone(&interfaces_copy[i]));
}
return interfaces_copy;
template <typename F>
fuchsia::net::interfaces::Event MakeChangeEvent(uint64_t interface_id, F fn) {
fuchsia::net::interfaces::Properties props;
props.set_id(interface_id);
fn(&props);
return fuchsia::net::interfaces::Event::WithChanged(std::move(props));
}
// Partial fake implementation of a Netstack.
class FakeNetstack : public fuchsia::netstack::testing::Netstack_TestBase {
// Partial fake implementation of a fuchsia.net.interfaces/Watcher.
class FakeWatcher : public fuchsia::net::interfaces::testing::Watcher_TestBase {
public:
FakeNetstack() = default;
FakeNetstack(const FakeNetstack&) = delete;
FakeNetstack& operator=(const FakeNetstack&) = delete;
~FakeNetstack() override = default;
void Bind(
fidl::InterfaceRequest<fuchsia::netstack::Netstack> netstack_request) {
CHECK_EQ(ZX_OK, binding_.Bind(std::move(netstack_request)));
binding_.events().OnInterfacesChanged(CloneNetInterfaces(interfaces_));
explicit FakeWatcher() : binding_(this) {
// Always create the watcher with an empty set of interfaces.
// Callers can override the initial set of events with SetInitial.
pending_.push(fuchsia::net::interfaces::Event::WithIdle(
fuchsia::net::interfaces::Empty{}));
}
FakeWatcher(const FakeWatcher&) = delete;
FakeWatcher& operator=(const FakeWatcher&) = delete;
~FakeWatcher() override = default;
// Sets the interfaces reported by the fake Netstack and sends an
// OnInterfacesChanged() event to the client.
void SetInterfaces(std::vector<fuchsia::netstack::NetInterface> interfaces) {
interfaces_ = std::move(interfaces);
if (binding_.is_bound()) {
binding_.events().OnInterfacesChanged(CloneNetInterfaces(interfaces_));
}
void Bind(fidl::InterfaceRequest<fuchsia::net::interfaces::Watcher> request) {
CHECK_EQ(ZX_OK, binding_.Bind(std::move(request)));
}
private:
void GetRouteTable(GetRouteTableCallback callback) override {
CHECK(binding_.is_bound());
std::vector<fuchsia::netstack::RouteTableEntry> table(2);
table[0].nicid = kDefaultInterfaceId;
table[0].netmask = IpAddressFrom(kIPv4DefaultGatewayNetmask);
table[0].destination = IpAddressFrom(kDefaultIPv4Address);
table[0].gateway = IpAddressFrom(kIPv4DefaultGatewayAddress);
void PushEvent(fuchsia::net::interfaces::Event event) {
if (pending_callback_) {
pending_callback_(std::move(event));
pending_callback_ = nullptr;
} else {
pending_.push(std::move(event));
}
}
table[1].nicid = kSecondaryInterfaceId;
table[1].netmask = IpAddressFrom(kSecondaryIPv4Netmask);
table[1].destination = IpAddressFrom(kSecondaryIPv4Address);
table[1].gateway = IpAddressFrom(kSecondaryIPv4Address);
void SetInitial(std::vector<fuchsia::net::interfaces::Properties> props) {
// Discard any pending events.
pending_ = std::queue<fuchsia::net::interfaces::Event>();
for (auto& prop : props) {
pending_.push(
fuchsia::net::interfaces::Event::WithExisting(std::move(prop)));
}
pending_.push(fuchsia::net::interfaces::Event::WithIdle(
fuchsia::net::interfaces::Empty{}));
// We should not have a pending callback already when setting initial state.
CHECK(!pending_callback_);
}
callback(std::move(table));
private:
void Watch(WatchCallback callback) override {
ASSERT_FALSE(pending_callback_);
if (pending_.empty()) {
pending_callback_ = std::move(callback);
} else {
callback(std::move(pending_.front()));
pending_.pop();
}
}
void NotImplemented_(const std::string& name) override {
LOG(FATAL) << "Unimplemented function called: " << name;
}
std::vector<fuchsia::netstack::NetInterface> interfaces_;
fidl::Binding<fuchsia::netstack::Netstack> binding_{this};
std::queue<fuchsia::net::interfaces::Event> pending_;
fidl::Binding<fuchsia::net::interfaces::Watcher> binding_;
WatchCallback pending_callback_ = nullptr;
};
class FakeNetstackAsync {
class FakeWatcherAsync {
public:
FakeNetstackAsync() : thread_("Netstack Thread") {
explicit FakeWatcherAsync() {
base::Thread::Options options(base::MessagePumpType::IO, 0);
CHECK(thread_.StartWithOptions(options));
netstack_ = base::SequenceBound<FakeNetstack>(thread_.task_runner());
watcher_ = base::SequenceBound<FakeWatcher>(thread_.task_runner());
}
FakeNetstackAsync(const FakeNetstackAsync&) = delete;
FakeNetstackAsync& operator=(const FakeNetstackAsync&) = delete;
~FakeNetstackAsync() = default;
FakeWatcherAsync(const FakeWatcherAsync&) = delete;
FakeWatcherAsync& operator=(const FakeWatcherAsync&) = delete;
~FakeWatcherAsync() = default;
void Bind(
fidl::InterfaceRequest<fuchsia::netstack::Netstack> netstack_request) {
netstack_.Post(FROM_HERE, &FakeNetstack::Bind, std::move(netstack_request));
void Bind(fidl::InterfaceRequest<fuchsia::net::interfaces::Watcher> request) {
watcher_.Post(FROM_HERE, &FakeWatcher::Bind, std::move(request));
}
// Asynchronously update the state of the netstack.
void SetInterfaces(
const std::vector<fuchsia::netstack::NetInterface>& interfaces) {
netstack_.Post(FROM_HERE, &FakeNetstack::SetInterfaces,
CloneNetInterfaces(interfaces));
// Asynchronously push an event to the watcher.
void PushEvent(fuchsia::net::interfaces::Event event) {
watcher_.Post(FROM_HERE, &FakeWatcher::PushEvent, std::move(event));
}
// Ensures that any SetInterfaces() or SendOnInterfacesChanged() calls have
// been processed.
void FlushNetstackThread() {
thread_.FlushForTesting();
// Asynchronously push an initial set of interfaces to the watcher.
void SetInitial(std::vector<fuchsia::net::interfaces::Properties> props) {
watcher_.Post(FROM_HERE, &FakeWatcher::SetInitial, std::move(props));
}
// Asynchronously push an initial single intface to the watcher.
void SetInitial(fuchsia::net::interfaces::Properties prop) {
SetInitial(MakeSingleItemVec(std::move(prop)));
}
// Ensures that any PushEvent() or SetInitial() calls have
// been processed.
void FlushThread() { thread_.FlushForTesting(); }
private:
base::Thread thread_;
base::SequenceBound<FakeNetstack> netstack_;
base::Thread thread_{"Watcher Thread"};
base::SequenceBound<FakeWatcher> watcher_;
};
template <class T>
......@@ -302,25 +333,22 @@ class NetworkChangeNotifierFuchsiaTest : public testing::Test {
const NetworkChangeNotifierFuchsiaTest&) = delete;
~NetworkChangeNotifierFuchsiaTest() override = default;
// Creates a NetworkChangeNotifier and spins the MessageLoop to allow it to
// populate from the list of interfaces which have already been added to
// |netstack_|. |observer_| is registered last, so that tests need only
// express expectations on changes they make themselves.
void CreateNotifier(
fuchsia::hardware::ethernet::Features required_features = {}) {
// Ensure that the Netstack internal state is up-to-date before the
// Creates a NetworkChangeNotifier that binds to |watcher_|.
// |observer_| is registered last, so that tests need only express
// expectations on changes they make themselves.
void CreateNotifier(bool requires_wlan = false) {
// Ensure that internal state is up-to-date before the
// notifier queries it.
netstack_.FlushNetstackThread();
watcher_.FlushThread();
CHECK(!netstack_handle_);
netstack_.Bind(netstack_handle_.NewRequest());
CHECK(!watcher_handle_);
watcher_.Bind(watcher_handle_.NewRequest());
// Use a noop DNS notifier.
dns_config_notifier_ = std::make_unique<SystemDnsConfigChangeNotifier>(
nullptr /* task_runner */, nullptr /* dns_config_service */);
notifier_.reset(new NetworkChangeNotifierFuchsia(
std::move(netstack_handle_), required_features,
dns_config_notifier_.get()));
std::move(watcher_handle_), requires_wlan, dns_config_notifier_.get()));
type_observer_ = std::make_unique<FakeConnectionTypeObserver>();
ip_observer_ = std::make_unique<FakeIPAddressObserver>();
......@@ -328,7 +356,7 @@ class NetworkChangeNotifierFuchsiaTest : public testing::Test {
void TearDown() override {
// Spin the loops to catch any unintended notifications.
netstack_.FlushNetstackThread();
watcher_.FlushThread();
base::RunLoop().RunUntilIdle();
}
......@@ -336,8 +364,8 @@ class NetworkChangeNotifierFuchsiaTest : public testing::Test {
base::test::SingleThreadTaskEnvironment task_environment_{
base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
fidl::InterfaceHandle<fuchsia::netstack::Netstack> netstack_handle_;
FakeNetstackAsync netstack_;
fidl::InterfaceHandle<fuchsia::net::interfaces::Watcher> watcher_handle_;
FakeWatcherAsync watcher_;
// Allows us to allocate our own NetworkChangeNotifier for unit testing.
NetworkChangeNotifier::DisableForTest disable_for_test_;
......@@ -356,19 +384,19 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, InitialState) {
TEST_F(NetworkChangeNotifierFuchsiaTest, NotifyNetworkChangeOnInitialIPChange) {
// Set a live interface with an IP address and create the notifier.
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].features = fuchsia::hardware::ethernet::Features::WLAN;
netstack_.SetInterfaces(interfaces);
watcher_.SetInitial(DefaultInterfaceProperties(
fuchsia::hardware::network::DeviceClass::WLAN));
CreateNotifier();
// Add the NetworkChangeNotifier, and change the IP address. This should
// trigger a network change notification, since the IP address is out-of-sync.
// trigger a network change notification.
FakeNetworkChangeObserver network_change_observer;
interfaces[0].addr = IpAddressFrom(kSecondaryIPv4Address);
netstack_.SetInterfaces(interfaces);
watcher_.PushEvent(MakeChangeEvent(
kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
props->set_addresses(MakeSingleItemVec(
InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
}));
EXPECT_TRUE(network_change_observer.RunAndExpectNetworkChanges(
{NetworkChangeNotifier::CONNECTION_NONE,
......@@ -378,139 +406,137 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, NotifyNetworkChangeOnInitialIPChange) {
TEST_F(NetworkChangeNotifierFuchsiaTest, NoChange) {
// Set a live interface with an IP address and create the notifier.
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
// Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
netstack_.SetInterfaces(interfaces);
// Push an event with no side-effects.
watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, NoChangeV6) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].addr = IpAddressFrom(kDefaultIPv6Address);
interfaces[0].netmask = IpAddressFrom(kDefaultIPv6Netmask);
netstack_.SetInterfaces(interfaces);
auto initial = DefaultInterfaceProperties();
initial.set_addresses(MakeSingleItemVec(
InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix)));
watcher_.SetInitial(std::move(initial));
CreateNotifier();
// Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
netstack_.SetInterfaces(interfaces);
// Push an event with no side-effects.
watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, MultiInterfaceNoChange) {
std::vector<fuchsia::netstack::NetInterface> interfaces(2);
interfaces[0] = DefaultNetInterface();
interfaces[1] = SecondaryNetInterface();
netstack_.SetInterfaces(interfaces);
std::vector<fuchsia::net::interfaces::Properties> props;
props.push_back(DefaultInterfaceProperties());
props.push_back(SecondaryInterfaceProperties());
watcher_.SetInitial(std::move(props));
CreateNotifier();
// Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
netstack_.SetInterfaces(interfaces);
// Push an event with no side-effects.
watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPNoChange) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].ipv6addrs.push_back(SubnetFrom(kDefaultIPv6Address, 2));
auto props = DefaultInterfaceProperties();
props.mutable_addresses()->push_back(
InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix));
props.mutable_addresses()->push_back(
InterfaceAddressFrom(kSecondaryIPv6Address, kSecondaryIPv6Prefix));
netstack_.SetInterfaces(interfaces);
watcher_.SetInitial(std::move(props));
CreateNotifier();
// Leave the set of interfaces unchanged, but re-send OnInterfacesChanged.
netstack_.SetInterfaces(interfaces);
// Push an event with no side-effects.
watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, IpChange) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
interfaces[0].addr = IpAddressFrom(kSecondaryIPv4Address);
netstack_.SetInterfaces(interfaces);
watcher_.PushEvent(MakeChangeEvent(
kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
props->set_addresses(MakeSingleItemVec(
InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
}));
// Expect a single OnIPAddressChanged() notification.
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, IpChangeV6) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].addr = IpAddressFrom(kDefaultIPv6Address);
interfaces[0].netmask = IpAddressFrom(kDefaultIPv6Netmask);
interfaces[0].broadaddr = IpAddressFrom(kDefaultIPv6Address);
netstack_.SetInterfaces(interfaces);
auto props = DefaultInterfaceProperties();
props.set_addresses(MakeSingleItemVec(
InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix)));
watcher_.SetInitial(std::move(props));
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
interfaces[0].addr = IpAddressFrom(kSecondaryIPv6Address);
interfaces[0].netmask = IpAddressFrom(kSecondaryIPv6Netmask);
interfaces[0].broadaddr = IpAddressFrom(kSecondaryIPv6Address);
netstack_.SetInterfaces(interfaces);
watcher_.PushEvent(MakeChangeEvent(
kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
props->set_addresses(MakeSingleItemVec(
InterfaceAddressFrom(kSecondaryIPv6Address, kSecondaryIPv6Prefix)));
}));
// Expect a single OnIPAddressChanged() notification.
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPChanged) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].ipv6addrs.push_back(SubnetFrom(kDefaultIPv6Address, 2));
auto props = DefaultInterfaceProperties();
props.mutable_addresses()->push_back(
InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix));
netstack_.SetInterfaces(interfaces);
watcher_.SetInitial(std::move(props));
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
interfaces[0].addr = IpAddressFrom(kSecondaryIPv4Address);
interfaces[0].netmask = IpAddressFrom(kSecondaryIPv4Netmask);
interfaces[0].broadaddr = IpAddressFrom(kSecondaryIPv4Address);
interfaces[0].ipv6addrs[0] = SubnetFrom(kSecondaryIPv6Address, 2);
netstack_.SetInterfaces(interfaces);
watcher_.PushEvent(MakeChangeEvent(
kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
std::vector<fuchsia::net::interfaces::Address> addrs;
addrs.push_back(
InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix));
addrs.push_back(
InterfaceAddressFrom(kSecondaryIPv6Address, kSecondaryIPv6Prefix));
props->set_addresses(std::move(addrs));
}));
// Expect a single OnIPAddressChanged() notification.
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, Ipv6AdditionalIpChange) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
interfaces[0].ipv6addrs.push_back(SubnetFrom(kDefaultIPv6Address, 2));
netstack_.SetInterfaces(interfaces);
watcher_.PushEvent(MakeChangeEvent(
kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
// Add the initial default address + a new IPv6 one. Address changes are
// always sent as the entire new list of addresses.
props->mutable_addresses()->push_back(
InterfaceAddressFrom(kDefaultIPv4Address, kDefaultIPv4Prefix));
props->mutable_addresses()->push_back(
InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix));
}));
// Expect a single OnIPAddressChanged() notification.
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDown) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
interfaces[0].flags = {};
netstack_.SetInterfaces(interfaces);
watcher_.PushEvent(MakeChangeEvent(
kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
props->set_online(false);
}));
EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
{NetworkChangeNotifier::ConnectionType::CONNECTION_NONE}));
......@@ -518,17 +544,17 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDown) {
}
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceUp) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].flags = {};
netstack_.SetInterfaces(interfaces);
auto props = DefaultInterfaceProperties();
props.set_online(false);
watcher_.SetInitial(std::move(props));
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
notifier_->GetCurrentConnectionType());
interfaces[0].flags = fuchsia::netstack::Flags::UP;
netstack_.SetInterfaces(interfaces);
watcher_.PushEvent(MakeChangeEvent(
kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
props->set_online(true);
}));
EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
{NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN}));
......@@ -536,15 +562,13 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceUp) {
}
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDeleted) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
notifier_->GetCurrentConnectionType());
netstack_.SetInterfaces({});
watcher_.PushEvent(
fuchsia::net::interfaces::Event::WithRemoved(kDefaultInterfaceId));
EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
{NetworkChangeNotifier::ConnectionType::CONNECTION_NONE}));
......@@ -557,11 +581,9 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceAdded) {
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
notifier_->GetCurrentConnectionType());
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].features = fuchsia::hardware::ethernet::Features::WLAN;
netstack_.SetInterfaces(interfaces);
watcher_.PushEvent(
fuchsia::net::interfaces::Event::WithAdded(DefaultInterfaceProperties(
fuchsia::hardware::network::DeviceClass::WLAN)));
EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
{NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI}));
......@@ -569,56 +591,44 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceAdded) {
}
TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceAddedNoop) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier();
interfaces.push_back(SecondaryNetInterface());
netstack_.SetInterfaces(interfaces);
watcher_.PushEvent(fuchsia::net::interfaces::Event::WithAdded(
SecondaryInterfaceProperties()));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceDeletedNoop) {
std::vector<fuchsia::netstack::NetInterface> interfaces(2);
interfaces[0] = DefaultNetInterface();
interfaces[1] = SecondaryNetInterface();
std::vector<fuchsia::net::interfaces::Properties> interfaces;
interfaces.push_back(DefaultInterfaceProperties());
interfaces.push_back(SecondaryInterfaceProperties());
netstack_.SetInterfaces(interfaces);
watcher_.SetInitial(std::move(interfaces));
CreateNotifier();
interfaces.pop_back();
netstack_.SetInterfaces(interfaces);
watcher_.PushEvent(
fuchsia::net::interfaces::Event::WithRemoved(kSecondaryInterfaceId));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, FoundWiFi) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].features = fuchsia::hardware::ethernet::Features::WLAN;
netstack_.SetInterfaces(interfaces);
watcher_.SetInitial(DefaultInterfaceProperties(
fuchsia::hardware::network::DeviceClass::WLAN));
CreateNotifier();
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
notifier_->GetCurrentConnectionType());
}
TEST_F(NetworkChangeNotifierFuchsiaTest, FindsInterfaceWithRequiredFeature) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
interfaces[0].features = fuchsia::hardware::ethernet::Features::WLAN;
netstack_.SetInterfaces(interfaces);
CreateNotifier(fuchsia::hardware::ethernet::Features::WLAN);
TEST_F(NetworkChangeNotifierFuchsiaTest, FindsInterfaceWithRequiredWlan) {
watcher_.SetInitial(DefaultInterfaceProperties(
fuchsia::hardware::network::DeviceClass::WLAN));
CreateNotifier(/*require_wlan=*/true);
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
notifier_->GetCurrentConnectionType());
}
TEST_F(NetworkChangeNotifierFuchsiaTest, IgnoresInterfaceWithMissingFeature) {
std::vector<fuchsia::netstack::NetInterface> interfaces(1);
interfaces[0] = DefaultNetInterface();
netstack_.SetInterfaces(interfaces);
CreateNotifier(fuchsia::hardware::ethernet::Features::WLAN);
TEST_F(NetworkChangeNotifierFuchsiaTest, IgnoresNonWlanInterface) {
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier(/*require_wlan=*/true);
EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
notifier_->GetCurrentConnectionType());
}
......
......@@ -4,9 +4,6 @@
#include "net/base/network_interfaces_fuchsia.h"
#include <fuchsia/hardware/ethernet/cpp/fidl.h>
#include <fuchsia/net/cpp/fidl.h>
#include <fuchsia/netstack/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h>
#include <string>
......@@ -16,124 +13,222 @@
#include "base/fuchsia/fuchsia_logging.h"
#include "base/fuchsia/process_context.h"
#include "base/strings/stringprintf.h"
#include "net/base/ip_endpoint.h"
#include "net/base/network_interfaces.h"
namespace net {
namespace internal {
namespace {
using ConnectionType = NetworkChangeNotifier::ConnectionType;
// Converts a Netstack NetInterface |interface| to a Chrome NetworkInterface.
// NetInterfaces may be bound to multiple IPv6 addresses. |address_index| is
// used to specify which address to use for the conversion.
// address_index = 0: Uses NetInterface::addr, NetInterface::netmask.
// address_index >= 1: Uses NetInterface::ipv6addrs[], with the array index
// offset by one.
NetworkInterface NetworkInterfaceFromAddress(
const fuchsia::netstack::NetInterface& interface,
size_t address_index) {
// TODO(crbug.com/1131220): attributes field is used to return address state
// for IPv6 addresses. Currently Netstack doesn't provide this information.
const int attributes = 0;
IPAddress address;
uint8_t prefix_length;
if (address_index == 0) {
address = FuchsiaIpAddressToIPAddress(interface.addr);
prefix_length =
MaskPrefixLength(FuchsiaIpAddressToIPAddress(interface.netmask));
} else {
CHECK_LE(address_index, interface.ipv6addrs.size());
address = FuchsiaIpAddressToIPAddress(
interface.ipv6addrs.at(address_index - 1).addr);
prefix_length = interface.ipv6addrs.at(address_index - 1).prefix_len;
IPAddress FuchsiaIpAddressToIPAddress(const fuchsia::net::IpAddress& address) {
switch (address.Which()) {
case fuchsia::net::IpAddress::kIpv4:
return IPAddress(address.ipv4().addr.data(), address.ipv4().addr.size());
case fuchsia::net::IpAddress::kIpv6:
return IPAddress(address.ipv6().addr.data(), address.ipv6().addr.size());
default:
return IPAddress();
}
return NetworkInterface(interface.name, interface.name, interface.id,
ConvertConnectionType(interface), address,
prefix_length, attributes);
}
} // namespace
NetworkChangeNotifier::ConnectionType ConvertConnectionType(
const fuchsia::netstack::NetInterface& iface) {
if ((iface.flags & fuchsia::netstack::Flags::UP) !=
fuchsia::netstack::Flags::UP) {
return NetworkChangeNotifier::CONNECTION_NONE;
} else if ((iface.features & fuchsia::hardware::ethernet::Features::WLAN) ==
fuchsia::hardware::ethernet::Features::WLAN) {
return NetworkChangeNotifier::CONNECTION_WIFI;
}
return NetworkChangeNotifier::CONNECTION_UNKNOWN;
// static
base::Optional<InterfaceProperties> InterfaceProperties::VerifyAndCreate(
fuchsia::net::interfaces::Properties properties) {
if (!internal::VerifyCompleteInterfaceProperties(properties))
return base::nullopt;
return base::make_optional(InterfaceProperties(std::move(properties)));
}
IPAddress FuchsiaIpAddressToIPAddress(const fuchsia::net::IpAddress& addr) {
if (addr.is_ipv4()) {
return IPAddress(addr.ipv4().addr.data(), addr.ipv4().addr.size());
InterfaceProperties::InterfaceProperties(
fuchsia::net::interfaces::Properties properties)
: properties_(std::move(properties)) {}
InterfaceProperties::InterfaceProperties(InterfaceProperties&& interface) =
default;
InterfaceProperties& InterfaceProperties::operator=(
InterfaceProperties&& interface) = default;
InterfaceProperties::~InterfaceProperties() = default;
bool InterfaceProperties::Update(
fuchsia::net::interfaces::Properties properties) {
if (!properties.has_id() || properties_.id() != properties.id()) {
LOG(WARNING) << "Update failed: invalid properties.";
return false;
}
if (addr.is_ipv6()) {
return IPAddress(addr.ipv6().addr.data(), addr.ipv6().addr.size());
if (properties.has_addresses()) {
for (const auto& fidl_address : properties.addresses()) {
if (!fidl_address.has_addr()) {
LOG(WARNING) << "Update failed: invalid properties.";
return false;
}
}
properties_.set_addresses(std::move(*properties.mutable_addresses()));
}
return IPAddress();
if (properties.has_online())
properties_.set_online(properties.online());
if (properties.has_has_default_ipv4_route())
properties_.set_has_default_ipv4_route(properties.has_default_ipv4_route());
if (properties.has_has_default_ipv6_route())
properties_.set_has_default_ipv6_route(properties.has_default_ipv6_route());
return true;
}
std::vector<NetworkInterface> NetInterfaceToNetworkInterfaces(
const fuchsia::netstack::NetInterface& iface_in) {
std::vector<NetworkInterface> output;
void InterfaceProperties::AppendNetworkInterfaces(
NetworkInterfaceList* interfaces) const {
uint32_t address_counter = 1;
for (const auto& fidl_address : properties_.addresses()) {
IPAddress address = FuchsiaIpAddressToIPAddress(fidl_address.addr().addr);
if (address.empty()) {
LOG(WARNING) << "Unknown fuchsia.net/IpAddress variant "
<< fidl_address.addr().addr.Which();
continue;
}
// If the interface is not currently up then there are no addresses to return.
if (internal::ConvertConnectionType(iface_in) ==
NetworkChangeNotifier::CONNECTION_NONE) {
return output;
// TODO(crbug.com/1131220): Set correct attributes once available in
// fuchsia::net::interfaces::Properties.
const int kAttributes = 0;
std::string interface_name = base::StringPrintf(
"%s-%d", properties_.name().c_str(), address_counter);
address_counter++;
interfaces->emplace_back(
interface_name, interface_name, properties_.id(),
internal::ConvertConnectionType(properties_.device_class()),
std::move(address), fidl_address.addr().prefix_len, kAttributes);
}
}
// It is possible for the interface not to have an IPv4 address.
NetworkInterface ipv4_interface = NetworkInterfaceFromAddress(iface_in, 0);
if (!ipv4_interface.address.IsZero())
output.push_back(std::move(ipv4_interface));
bool InterfaceProperties::IsPubliclyRoutable() const {
if (!properties_.online())
return false;
// Append interface entries for all additional IPv6 addresses.
for (size_t i = 0; i < iface_in.ipv6addrs.size(); ++i) {
output.push_back(NetworkInterfaceFromAddress(iface_in, i + 1));
for (const auto& fidl_address : properties_.addresses()) {
const IPAddress address =
FuchsiaIpAddressToIPAddress(fidl_address.addr().addr);
if ((address.IsIPv4() && properties_.has_default_ipv4_route() &&
!address.IsLinkLocal()) ||
(address.IsIPv6() && properties_.has_default_ipv6_route() &&
address.IsPubliclyRoutable())) {
return true;
}
}
return false;
}
return output;
NetworkChangeNotifier::ConnectionType ConvertConnectionType(
const fuchsia::net::interfaces::DeviceClass& device_class) {
switch (device_class.Which()) {
case fuchsia::net::interfaces::DeviceClass::kLoopback:
return NetworkChangeNotifier::CONNECTION_NONE;
case fuchsia::net::interfaces::DeviceClass::kDevice:
switch (device_class.device()) {
case fuchsia::hardware::network::DeviceClass::WLAN:
return NetworkChangeNotifier::CONNECTION_WIFI;
case fuchsia::hardware::network::DeviceClass::ETHERNET:
return NetworkChangeNotifier::CONNECTION_ETHERNET;
default:
return NetworkChangeNotifier::CONNECTION_UNKNOWN;
}
default:
LOG(WARNING) << "Received unknown fuchsia.net.interfaces/DeviceClass "
<< device_class.Which();
return NetworkChangeNotifier::CONNECTION_UNKNOWN;
}
}
fuchsia::net::interfaces::WatcherHandle ConnectInterfacesWatcher() {
fuchsia::net::interfaces::StateSyncPtr state;
zx_status_t status =
base::ComponentContextForProcess()->svc()->Connect(state.NewRequest());
ZX_CHECK(status == ZX_OK, status) << "Connect()";
fuchsia::net::interfaces::WatcherHandle watcher;
state->GetWatcher({} /*options*/, watcher.NewRequest());
return watcher;
}
bool VerifyCompleteInterfaceProperties(
const fuchsia::net::interfaces::Properties& properties) {
if (!properties.has_id())
return false;
if (!properties.has_addresses())
return false;
for (const auto& fidl_address : properties.addresses()) {
if (!fidl_address.has_addr())
return false;
}
if (!properties.has_online())
return false;
if (!properties.has_device_class())
return false;
if (!properties.has_has_default_ipv4_route())
return false;
if (!properties.has_has_default_ipv6_route())
return false;
return true;
}
base::Optional<ExistingInterfaceProperties> GetExistingInterfaces(
const fuchsia::net::interfaces::WatcherSyncPtr& watcher) {
ExistingInterfaceProperties existing_interfaces;
for (;;) {
fuchsia::net::interfaces::Event event;
zx_status_t status = watcher->Watch(&event);
if (status != ZX_OK)
return base::nullopt;
switch (event.Which()) {
case fuchsia::net::interfaces::Event::Tag::kExisting: {
base::Optional<InterfaceProperties> interface =
InterfaceProperties::VerifyAndCreate(std::move(event.existing()));
if (!interface) {
return base::nullopt;
}
uint64_t id = interface->id();
existing_interfaces.emplace_back(id, std::move(*interface));
break;
}
case fuchsia::net::interfaces::Event::Tag::kIdle:
// Idle means we've listed all the existing interfaces. We can stop
// fetching events.
return existing_interfaces;
default:
return base::nullopt;
}
}
}
} // namespace internal
bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
DCHECK(networks);
fuchsia::netstack::NetstackSyncPtr netstack;
base::ComponentContextForProcess()->svc()->Connect(netstack.NewRequest());
fuchsia::net::interfaces::WatcherHandle handle =
internal::ConnectInterfacesWatcher();
fuchsia::net::interfaces::WatcherSyncPtr watcher = handle.BindSync();
// TODO(crbug.com/1131238): Use NetworkChangeNotifier's cached interface
// list.
std::vector<fuchsia::netstack::NetInterface> interfaces;
zx_status_t status = netstack->GetInterfaces(&interfaces);
if (status != ZX_OK) {
ZX_LOG(ERROR, status) << "fuchsia::netstack::GetInterfaces()";
base::Optional<internal::ExistingInterfaceProperties> existing_interfaces =
internal::GetExistingInterfaces(watcher);
if (!existing_interfaces)
return false;
}
for (auto& interface : interfaces) {
if ((internal::ConvertConnectionType(interface) ==
NetworkChangeNotifier::CONNECTION_NONE) ||
(interface.features &
fuchsia::hardware::ethernet::Features::LOOPBACK) ==
fuchsia::hardware::ethernet::Features::LOOPBACK) {
handle = watcher.Unbind();
for (const auto& interface_entry : *existing_interfaces) {
if (!interface_entry.second.online()) {
// GetNetworkList() only returns online interfaces.
continue;
}
auto converted = internal::NetInterfaceToNetworkInterfaces(interface);
std::move(converted.begin(), converted.end(),
std::back_inserter(*networks));
if (interface_entry.second.device_class().is_loopback()) {
// GetNetworkList() returns all interfaces except loopback.
continue;
}
interface_entry.second.AppendNetworkInterfaces(networks);
}
return true;
}
......
......@@ -5,41 +5,81 @@
#ifndef NET_BASE_NETWORK_INTERFACES_FUCHSIA_H_
#define NET_BASE_NETWORK_INTERFACES_FUCHSIA_H_
#include <fuchsia/net/interfaces/cpp/fidl.h>
#include <vector>
#include "net/base/network_change_notifier.h"
#include "net/base/network_interfaces.h"
namespace fuchsia {
namespace net {
class IpAddress;
}
namespace netstack {
class NetInterface;
} // namespace netstack
} // namespace fuchsia
namespace internal {
namespace net {
// Move-only wrapper for fuchsia::net::interface::Properties that guarantees
// that its inner |properties_| are valid and complete properties as reported by
// |VerifyCompleteInterfaceProperties|.
class InterfaceProperties final {
public:
// Creates an |InterfaceProperties| if |properties| are valid complete
// properties as reported by |VerifyCompleteInterfaceProperties|.
static base::Optional<InterfaceProperties> VerifyAndCreate(
fuchsia::net::interfaces::Properties properties);
InterfaceProperties(InterfaceProperties&& interface);
InterfaceProperties& operator=(InterfaceProperties&& interface);
~InterfaceProperties();
class IPAddress;
struct NetworkInterface;
// Updates this instance with the values set in |properties|.
// Fields not set in |properties| retain their previous values.
// Returns false if the |properties| has a missing or mismatched |id| field,
// or if any field set in |properties| has an invalid value (e.g. addresses of
// unknown types).
bool Update(fuchsia::net::interfaces::Properties properties);
namespace internal {
// Appends the NetworkInterfaces for this interface to |interfaces|.
void AppendNetworkInterfaces(NetworkInterfaceList* interfaces) const;
// Returns true if the interface is online and it has either an IPv4 default
// route and a non-link-local address, or an IPv6 default route and a global
// address.
bool IsPubliclyRoutable() const;
bool HasAddresses() const { return !properties_.addresses().empty(); }
uint64_t id() const { return properties_.id(); }
bool online() const { return properties_.online(); }
const fuchsia::net::interfaces::DeviceClass& device_class() const {
return properties_.device_class();
}
private:
explicit InterfaceProperties(fuchsia::net::interfaces::Properties properties);
fuchsia::net::interfaces::Properties properties_;
};
using ExistingInterfaceProperties =
std::vector<std::pair<uint64_t, InterfaceProperties>>;
// Returns the //net ConnectionType for the supplied netstack interface
// description. Returns ConnectionType::CONNECTION_NONE if the interface is not
// "up".
// description. Returns CONNECTION_NONE for loopback interfaces.
NetworkChangeNotifier::ConnectionType ConvertConnectionType(
const fuchsia::netstack::NetInterface& iface);
const fuchsia::net::interfaces::DeviceClass& device_class);
// Connects to the service via the process' ComponentContext, and connects the
// Watcher to the service.
fuchsia::net::interfaces::WatcherHandle ConnectInterfacesWatcher();
// Converts a Fuchsia Netstack NetInterface object to NetworkInterface objects.
// Interfaces with more than one IPv6 address will yield multiple
// NetworkInterface objects, with friendly names to distinguish the different
// IPs (e.g. "wlan" with three IPv6 IPs yields wlan-0, wlan-1, wlan-2).
std::vector<NetworkInterface> NetInterfaceToNetworkInterfaces(
const fuchsia::netstack::NetInterface& iface_in);
// Validates that |properties| contains all the required fields, returning
// |true| if so.
bool VerifyCompleteInterfaceProperties(
const fuchsia::net::interfaces::Properties& properties);
// Converts a Fuchsia IPv4/IPv6 address to a Chromium IPAddress.
IPAddress FuchsiaIpAddressToIPAddress(const fuchsia::net::IpAddress& addr);
// Consumes events describing existing interfaces from |watcher| and
// returns a vector of interface Id & properties pairs. |watcher| must
// be a newly-connected Watcher channel.
// Returns base::nullopt if any protocol error is encountered, e.g.
// |watcher| supplies an invalid event, or disconnects.
base::Optional<internal::ExistingInterfaceProperties> GetExistingInterfaces(
const fuchsia::net::interfaces::WatcherSyncPtr& watcher);
} // namespace internal
} // namespace net
......
......@@ -129,7 +129,7 @@ component("policy") {
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.logger",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mediacodec",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.net",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.netstack",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.net.interfaces",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.sysmem",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.scenic",
]
......
......@@ -15,7 +15,7 @@
#include <fuchsia/logger/cpp/fidl.h>
#include <fuchsia/mediacodec/cpp/fidl.h>
#include <fuchsia/net/cpp/fidl.h>
#include <fuchsia/netstack/cpp/fidl.h>
#include <fuchsia/net/interfaces/cpp/fidl.h>
#include <fuchsia/sysmem/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h>
......@@ -90,7 +90,7 @@ constexpr SandboxConfig kGpuConfig = {
constexpr SandboxConfig kNetworkConfig = {
base::make_span((const char* const[]){
fuchsia::net::NameLookup::Name_,
fuchsia::netstack::Netstack::Name_,
fuchsia::net::interfaces::State::Name_,
"fuchsia.posix.socket.Provider",
}),
kProvideSslConfig,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment