blob: 2072abac3f7d1496ac4e51e4274e6fa3693c739a [file] [log] [blame]
// Copyright 2020 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 {
crate::{builtin::capability::BuiltinCapability, capability::*},
anyhow::Error,
async_trait::async_trait,
cm_rust::CapabilityName,
fidl_fuchsia_boot as fboot,
fuchsia_zircon::{self as zx, HandleBased, Resource},
futures::prelude::*,
lazy_static::lazy_static,
std::sync::Arc,
};
lazy_static! {
static ref ROOT_RESOURCE_CAPABILITY_NAME: CapabilityName = "fuchsia.boot.RootResource".into();
}
/// An implementation of the `fuchsia.boot.RootResource` protocol.
pub struct RootResource {
resource: Resource,
}
impl RootResource {
pub fn new(resource: Resource) -> Arc<Self> {
Arc::new(Self { resource })
}
}
#[async_trait]
impl BuiltinCapability for RootResource {
const NAME: &'static str = "RootResource";
type Marker = fboot::RootResourceMarker;
async fn serve(
self: Arc<Self>,
mut stream: fboot::RootResourceRequestStream,
) -> Result<(), Error> {
while let Some(fboot::RootResourceRequest::Get { responder }) = stream.try_next().await? {
responder.send(self.resource.duplicate_handle(zx::Rights::SAME_RIGHTS)?)?;
}
Ok(())
}
fn matches_routed_capability(&self, capability: &InternalCapability) -> bool {
capability.matches_protocol(&ROOT_RESOURCE_CAPABILITY_NAME)
}
}
#[cfg(test)]
mod tests {
use {
super::*,
crate::model::hooks::{Event, EventPayload, Hooks},
fidl::endpoints::ClientEnd,
fidl_fuchsia_kernel as fkernel, fuchsia_async as fasync,
futures::lock::Mutex,
moniker::AbsoluteMoniker,
std::path::PathBuf,
};
#[fasync::run_singlethreaded(test)]
async fn can_connect() -> Result<(), Error> {
let root_resource = RootResource::new(Resource::from(zx::Handle::invalid()));
let hooks = Hooks::new(None);
hooks.install(root_resource.hooks()).await;
let provider = Arc::new(Mutex::new(None));
let source = CapabilitySource::Builtin {
capability: InternalCapability::Protocol(ROOT_RESOURCE_CAPABILITY_NAME.clone()),
};
let event = Event::new_for_test(
AbsoluteMoniker::root(),
"fuchsia-pkg://root",
Ok(EventPayload::CapabilityRouted { source, capability_provider: provider.clone() }),
);
hooks.dispatch(&event).await?;
let (client, mut server) = zx::Channel::create()?;
if let Some(provider) = provider.lock().await.take() {
provider.open(0, 0, PathBuf::new(), &mut server).await?;
}
// We do not call get, as we passed an invalid handle to RootResource,
// which would cause a PEER_CLOSED failure. We passed an invalid handle
// to RootResource because you need a Resource to create another one,
// which we do not have.
ClientEnd::<fkernel::RootJobMarker>::new(client)
.into_proxy()
.expect("Failed to create proxy");
Ok(())
}
}