[fuchsia-component] ServiceFs - send OnOpen event
Sending OnOpen event since appmgr expects it before mounting the out
directory.
This commit also specifies a list of supported flags, but only the
OPEN_FLAG_DESCRIBE flag is currently handled.
CF-628 #comment
Test: verify that out directory shows up for a Rust component
Change-Id: I77ac6bec937d096dd8f0c2bd55ea573258a118b2
diff --git a/garnet/public/rust/fuchsia-component/src/lib.rs b/garnet/public/rust/fuchsia-component/src/lib.rs
index 5de8f04..43e5c88 100644
--- a/garnet/public/rust/fuchsia-component/src/lib.rs
+++ b/garnet/public/rust/fuchsia-component/src/lib.rs
@@ -9,7 +9,7 @@
#[allow(unused)] // Remove pending fix to rust-lang/rust#53682
use {
- failure::{Error, ResultExt, Fail, format_err},
+ failure::{Error, ResultExt, Fail, bail, format_err},
fdio::fdio_sys,
fuchsia_async as fasync,
futures::{
@@ -19,7 +19,7 @@
task::Waker,
},
fidl::{
- encoding::Decodable,
+ encoding::{Decodable, OutOfLine},
endpoints::{RequestStream, ServiceMarker, Proxy},
},
fidl_fuchsia_io::{
@@ -28,6 +28,11 @@
DirectoryObject,
NodeAttributes,
NodeInfo,
+ OPEN_RIGHT_READABLE,
+ OPEN_RIGHT_WRITABLE,
+ OPEN_FLAG_DESCRIBE,
+ OPEN_FLAG_DIRECTORY,
+ OPEN_FLAG_POSIX,
},
fidl_fuchsia_sys::{
ComponentControllerProxy,
@@ -369,6 +374,12 @@
}
const ROOT_NODE: usize = 0;
+ const NO_FLAGS: u32 = 0;
+ const CLONE_REQ_SUPPORTED_FLAGS: u32 =
+ OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE | OPEN_FLAG_DESCRIBE;
+ const OPEN_REQ_SUPPORTED_FLAGS: u32 =
+ OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE | OPEN_FLAG_DESCRIBE | OPEN_FLAG_POSIX |
+ OPEN_FLAG_DIRECTORY;
impl<Output: 'static> ServiceFs<ServiceObjLocal<Output>> {
/// Create a new `ServiceFs` that is singlethreaded-only and does not
@@ -743,11 +754,11 @@
/// Add an additional connection to the `FdioServer` to provide services to.
pub fn serve_connection(&mut self, chan: zx::Channel) -> Result<&mut Self, Error> {
- self.serve_connection_at(chan, ROOT_NODE)?;
+ self.serve_connection_at(chan, ROOT_NODE, NO_FLAGS)?;
Ok(self)
}
- fn serve_connection_at(&mut self, chan: zx::Channel, position: usize)
+ fn serve_connection_at(&mut self, chan: zx::Channel, position: usize, flags: u32)
-> Result<(), Error>
{
chan
@@ -757,9 +768,15 @@
let chan = fasync::Channel::from_channel(chan)
.context("failure to convert to async channel")?;
- let stream = Some(DirectoryRequestStream::from_channel(chan));
+ let stream = DirectoryRequestStream::from_channel(chan);
+ if (flags & OPEN_FLAG_DESCRIBE) != 0 {
+ let mut info = NodeInfo::Directory(DirectoryObject);
+ stream.control_handle().send_on_open_(zx::sys::ZX_OK, Some(OutOfLine(&mut info)))
+ .context("fail sending OnOpen event")?;
+ }
+
self.client_connections.push(ClientConnection {
- stream,
+ stream: Some(stream),
position,
});
Ok(())
@@ -778,14 +795,33 @@
}
}
+ macro_rules! handle_potentially_unsupported_flags {
+ ($object:ident, $flags:expr, $supported_flags_bitmask:expr) => {
+ if has_unsupported_flags($flags, $supported_flags_bitmask) {
+ if ($flags & OPEN_FLAG_DESCRIBE) != 0 {
+ let (_stream, control_handle) = $object.into_stream_and_control_handle()
+ .context("fail to convert to stream and control handle")?;
+ control_handle.send_on_open_(zx::sys::ZX_ERR_NOT_SUPPORTED, None)
+ .context("fail sending OnOpenEvent")?;
+ }
+ bail!("flags contains unsupported flags: {}", $flags);
+ }
+ }
+ }
+
match request {
- DirectoryRequest::Clone { flags: _, object, control_handle: _ } => {
- if let Err(e) = self.serve_connection_at(object.into_channel(), position) {
+ DirectoryRequest::Clone { flags, object, control_handle: _ } => {
+ handle_potentially_unsupported_flags!(object, flags, CLONE_REQ_SUPPORTED_FLAGS);
+
+ if let Err(e) = self.serve_connection_at(object.into_channel(), position, flags)
+ {
eprintln!("ServiceFs failed to clone: {:?}", e);
}
}
DirectoryRequest::Close { responder, } => responder.send(zx::sys::ZX_OK)?,
- DirectoryRequest::Open { flags: _, mode: _, path, object, control_handle: _, } => {
+ DirectoryRequest::Open { flags, mode: _, path, object, control_handle: _, } => {
+ handle_potentially_unsupported_flags!(object, flags, OPEN_REQ_SUPPORTED_FLAGS);
+
let channel = object.into_channel();
let node = self.nodes.get(position)
.expect("ServiceFs client connected at missing node");
@@ -801,7 +837,9 @@
.expect("Missing child node")
{
ServiceFsNode::Directory { .. } => {
- if let Err(e) = self.serve_connection_at(channel, target_node_position) {
+ if let Err(e) =
+ self.serve_connection_at(channel, target_node_position, flags)
+ {
eprintln!("ServiceFs failed to open directory: {:?}", e);
}
}
@@ -840,6 +878,10 @@
}
}
+ fn has_unsupported_flags(flags: u32, supported_flags_bitmask: u32) -> bool {
+ (flags & !supported_flags_bitmask) != 0
+ }
+
impl<ServiceObjTy: ServiceObjTrait> Unpin for ServiceFs<ServiceObjTy> {}
impl<ServiceObjTy: ServiceObjTrait> Stream for ServiceFs<ServiceObjTy> {