Fuchsia: Implement NetworkChangeNotifierFuchsia with FIDL APIs.
This code adds Fuchsia platform implementation code for broadcasting
events on major network interface change events (IP
address changes, connectivity change, interface up/down changes, etc.)
Modified network_interfaces_fuchsia.cc to support adapters w/multiple
IPv6 addresses.
Added unit tests.
Bug: 843443
Change-Id: Id7edc944ceef439d9c360e5d31966807f306489c
Reviewed-on: https://chromium-review.googlesource.com/1066074
Commit-Queue: Kevin Marshall <[email protected]>
Reviewed-by: Paul Jensen <[email protected]>
Reviewed-by: Wez <[email protected]>
Reviewed-by: Sergey Ulanov <[email protected]>
Cr-Commit-Position: refs/heads/master@{#564669}
diff --git a/net/base/network_interfaces_fuchsia.cc b/net/base/network_interfaces_fuchsia.cc
index 1c03e968..9d7a83d 100644
--- a/net/base/network_interfaces_fuchsia.cc
+++ b/net/base/network_interfaces_fuchsia.cc
@@ -2,14 +2,64 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/base/network_interfaces.h"
+#include "net/base/network_interfaces_fuchsia.h"
#include <fuchsia/netstack/cpp/fidl.h>
+#include <string>
+#include <utility>
+
+#include "base/format_macros.h"
#include "base/fuchsia/component_context.h"
+#include "base/strings/stringprintf.h"
#include "net/base/ip_endpoint.h"
+#include "net/base/network_change_notifier.h"
+#include "net/base/network_interfaces.h"
namespace net {
+namespace internal {
+namespace {
+
+using ConnectionType = NetworkChangeNotifier::ConnectionType;
+
+ConnectionType ConvertConnectionType(
+ const fuchsia::netstack::NetInterface& iface) {
+ return iface.features & fuchsia::netstack::interfaceFeatureWlan
+ ? NetworkChangeNotifier::CONNECTION_WIFI
+ : NetworkChangeNotifier::CONNECTION_UNKNOWN;
+}
+
+// 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(sergeyu): 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 = NetAddressToIPAddress(interface.addr);
+ prefix_length = MaskPrefixLength(NetAddressToIPAddress(interface.netmask));
+ } else {
+ CHECK_LE(address_index, interface.ipv6addrs->size());
+ address =
+ NetAddressToIPAddress(interface.ipv6addrs->at(address_index - 1).addr);
+ prefix_length = interface.ipv6addrs->at(address_index - 1).prefix_len;
+ }
+
+ return NetworkInterface(*interface.name, interface.name, interface.id,
+ ConvertConnectionType(interface), address,
+ prefix_length, attributes);
+}
+
+} // namespace
IPAddress NetAddressToIPAddress(const fuchsia::netstack::NetAddress& addr) {
if (addr.ipv4) {
@@ -21,38 +71,46 @@
return IPAddress();
}
+std::vector<NetworkInterface> NetInterfaceToNetworkInterfaces(
+ const fuchsia::netstack::NetInterface& iface_in) {
+ std::vector<NetworkInterface> output;
+
+ // Check if the interface is up.
+ if (!(iface_in.flags & fuchsia::netstack::NetInterfaceFlagUp))
+ return output;
+
+ // Skip loopback.
+ if (iface_in.features & fuchsia::netstack::interfaceFeatureLoopback)
+ return output;
+
+ output.push_back(NetworkInterfaceFromAddress(iface_in, 0));
+
+ // 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));
+ }
+
+ return output;
+}
+
+} // namespace internal
+
bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
+ DCHECK(networks);
+
fuchsia::netstack::NetstackSyncPtr netstack =
base::fuchsia::ComponentContext::GetDefault()
->ConnectToServiceSync<fuchsia::netstack::Netstack>();
+ // TODO(kmarshall): Use NetworkChangeNotifier's cached interface list.
fidl::VectorPtr<fuchsia::netstack::NetInterface> interfaces;
if (!netstack->GetInterfaces(&interfaces))
return false;
for (auto& interface : interfaces.get()) {
- // Check if the interface is up.
- if (!(interface.flags & fuchsia::netstack::NetInterfaceFlagUp))
- continue;
-
- // Skip loopback.
- if (interface.features & fuchsia::netstack::interfaceFeatureLoopback)
- continue;
-
- NetworkChangeNotifier::ConnectionType connection_type =
- (interface.features & fuchsia::netstack::interfaceFeatureWlan)
- ? NetworkChangeNotifier::CONNECTION_WIFI
- : NetworkChangeNotifier::CONNECTION_UNKNOWN;
-
- // TODO(sergeyu): attributes field is used to return address state for IPv6
- // addresses. Currently Netstack doesn't provide this information.
- int attributes = 0;
-
- networks->push_back(NetworkInterface(
- *interface.name, *interface.name, interface.id, connection_type,
- NetAddressToIPAddress(interface.addr),
- MaskPrefixLength(NetAddressToIPAddress(interface.netmask)),
- attributes));
+ auto converted = internal::NetInterfaceToNetworkInterfaces(interface);
+ std::move(converted.begin(), converted.end(),
+ std::back_inserter(*networks));
}
return true;