blob: 163d91d03fe2fba9a00af28cad94d01d1b6a8475 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
anyhow::{format_err, Result},
fidl_fuchsia_buildinfo as buildinfo, fidl_fuchsia_developer_remotecontrol as rcs,
fidl_fuchsia_device as fdevice, fidl_fuchsia_hwinfo as hwinfo, fidl_fuchsia_net as fnet,
fidl_fuchsia_net_stack as fnetstack, fuchsia_zircon as zx,
tracing::*,
};
pub struct HostIdentifier {
pub(crate) netstack_proxy: fnetstack::StackProxy,
pub(crate) name_provider_proxy: fdevice::NameProviderProxy,
pub(crate) device_info_proxy: hwinfo::DeviceProxy,
pub(crate) build_info_proxy: buildinfo::ProviderProxy,
pub(crate) boot_timestamp_nanos: u64,
}
impl HostIdentifier {
pub fn new() -> Result<Self> {
let netstack_proxy =
fuchsia_component::client::connect_to_service::<fnetstack::StackMarker>()
.map_err(|s| format_err!("Failed to connect to NetStack service: {}", s))?;
let name_provider_proxy =
fuchsia_component::client::connect_to_service::<fdevice::NameProviderMarker>()
.map_err(|s| format_err!("Failed to connect to NameProviderService: {}", s))?;
let device_info_proxy =
fuchsia_component::client::connect_to_service::<hwinfo::DeviceMarker>()
.map_err(|s| format_err!("Failed to connect to DeviceProxy: {}", s))?;
let build_info_proxy =
fuchsia_component::client::connect_to_service::<buildinfo::ProviderMarker>()
.map_err(|s| format_err!("Failed to connect to BoardProxy: {}", s))?;
let boot_timestamp_nanos = (fuchsia_runtime::utc_time().into_nanos()
- zx::Time::get_monotonic().into_nanos()) as u64;
return Ok(Self {
netstack_proxy,
name_provider_proxy,
device_info_proxy,
build_info_proxy,
boot_timestamp_nanos,
});
}
pub async fn identify(&self) -> Result<rcs::IdentifyHostResponse, rcs::IdentifyHostError> {
let mut ilist = self.netstack_proxy.list_interfaces().await.map_err(|e| {
error!(%e, "Getting interface list failed");
rcs::IdentifyHostError::ListInterfacesFailed
})?;
let serial_number = self
.device_info_proxy
.get_info()
.await
.map_err(|e| error!(%e, "DeviceProxy internal err"))
.ok()
.and_then(|i| i.serial_number);
let (product_config, board_config) = self
.build_info_proxy
.get_build_info()
.await
.map_err(|e| error!(%e, "buildinfo::ProviderProxy internal err"))
.ok()
.and_then(|i| Some((i.product_config, i.board_config)))
.unwrap_or((None, None));
let addresses = Some(
ilist
.iter_mut()
.flat_map(|int| int.properties.addresses.drain(..))
.collect::<Vec<fnet::Subnet>>(),
);
let nodename = match self.name_provider_proxy.get_device_name().await {
Ok(result) => match result {
Ok(name) => Some(name),
Err(err) => {
error!(%err, "NameProvider internal error");
return Err(rcs::IdentifyHostError::GetDeviceNameFailed);
}
},
Err(err) => {
error!(%err, "Getting nodename failed");
return Err(rcs::IdentifyHostError::GetDeviceNameFailed);
}
};
let boot_timestamp_nanos = Some(self.boot_timestamp_nanos);
Ok(rcs::IdentifyHostResponse {
nodename,
addresses,
serial_number,
boot_timestamp_nanos,
product_config,
board_config,
..rcs::IdentifyHostResponse::EMPTY
})
}
}