sandbox/fidl/
dir_entry_router.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::fidl::router;
6use crate::{ConversionError, DirEntry, Router, RouterResponse, WeakInstanceToken};
7use fidl::handle::AsHandleRef;
8use futures::TryStreamExt;
9use std::sync::Arc;
10use vfs::directory::entry::DirectoryEntry;
11use vfs::execution_scope::ExecutionScope;
12use {fidl_fuchsia_component_sandbox as fsandbox, fidl_fuchsia_io as fio};
13
14impl crate::RemotableCapability for Router<DirEntry> {
15    fn try_into_directory_entry(
16        self,
17        scope: ExecutionScope,
18        token: WeakInstanceToken,
19    ) -> Result<Arc<dyn DirectoryEntry>, ConversionError> {
20        Ok(self.into_directory_entry(
21            // TODO(https://fxbug.dev/340891837): This assumes the DirEntry type is Service.
22            // Unfortunately, with the current API there is no good way to get the DirEntry type in
23            // advance. This problem should go away once we revamp or remove DirEntry.
24            fio::DirentType::Service,
25            scope,
26            token,
27        ))
28    }
29}
30
31impl TryFrom<RouterResponse<DirEntry>> for fsandbox::DirEntryRouterRouteResponse {
32    type Error = fsandbox::RouterError;
33
34    fn try_from(resp: RouterResponse<DirEntry>) -> Result<Self, Self::Error> {
35        match resp {
36            RouterResponse::<DirEntry>::Capability(c) => {
37                Ok(fsandbox::DirEntryRouterRouteResponse::DirEntry(c.into()))
38            }
39            RouterResponse::<DirEntry>::Unavailable => {
40                Ok(fsandbox::DirEntryRouterRouteResponse::Unavailable(fsandbox::Unit {}))
41            }
42            RouterResponse::<DirEntry>::Debug(_) => Err(fsandbox::RouterError::NotSupported),
43        }
44    }
45}
46
47impl crate::fidl::IntoFsandboxCapability for Router<DirEntry> {
48    fn into_fsandbox_capability(self, token: WeakInstanceToken) -> fsandbox::Capability {
49        let (client_end, sender_stream) =
50            fidl::endpoints::create_request_stream::<fsandbox::DirEntryRouterMarker>();
51        self.serve_and_register(sender_stream, client_end.get_koid().unwrap(), token);
52        fsandbox::Capability::DirEntryRouter(client_end)
53    }
54}
55
56impl Router<DirEntry> {
57    async fn serve_router(
58        self,
59        mut stream: fsandbox::DirEntryRouterRequestStream,
60        token: WeakInstanceToken,
61    ) -> Result<(), fidl::Error> {
62        while let Ok(Some(request)) = stream.try_next().await {
63            match request {
64                fsandbox::DirEntryRouterRequest::Route { payload, responder } => {
65                    responder.send(router::route_from_fidl(&self, payload, token.clone()).await)?;
66                }
67                fsandbox::DirEntryRouterRequest::_UnknownMethod { ordinal, .. } => {
68                    log::warn!(
69                        ordinal:%; "Received unknown DirEntryRouter request"
70                    );
71                }
72            }
73        }
74        Ok(())
75    }
76
77    /// Serves the `fuchsia.sandbox.Router` protocol and moves ourself into the registry.
78    pub fn serve_and_register(
79        self,
80        stream: fsandbox::DirEntryRouterRequestStream,
81        koid: zx::Koid,
82        token: WeakInstanceToken,
83    ) {
84        let router = self.clone();
85
86        // Move this capability into the registry.
87        crate::fidl::registry::insert(self.into(), koid, async move {
88            router.serve_router(stream, token).await.expect("failed to serve Router");
89        });
90    }
91}