1use crate::fidl::RemotableCapability;
6use crate::{Capability, CapabilityBound, Dict, Request, Router, RouterResponse};
7use fidl::AsHandleRef;
8use router_error::{Explain, RouterError};
9use std::sync::Arc;
10use vfs::directory::entry::{self, DirectoryEntry, DirectoryEntryAsync, EntryInfo, GetEntryInfo};
11use vfs::execution_scope::ExecutionScope;
12use {fidl_fuchsia_component_sandbox as fsandbox, fidl_fuchsia_io as fio, zx};
13
14impl From<Request> for fsandbox::RouteRequest {
15 fn from(request: Request) -> Self {
16 let (token, server) = zx::EventPair::create();
17 request.target.register(token.get_koid().unwrap(), server);
18 fsandbox::RouteRequest {
19 requesting: Some(fsandbox::InstanceToken { token }),
20 metadata: Some(request.metadata.into()),
21 ..Default::default()
22 }
23 }
24}
25
26impl TryFrom<fsandbox::DictionaryRouterRouteResponse> for RouterResponse<Dict> {
27 type Error = crate::RemoteError;
28
29 fn try_from(resp: fsandbox::DictionaryRouterRouteResponse) -> Result<Self, Self::Error> {
30 Ok(match resp {
31 fsandbox::DictionaryRouterRouteResponse::Dictionary(dict) => {
32 RouterResponse::<Dict>::Capability(dict.try_into()?)
33 }
34 fsandbox::DictionaryRouterRouteResponse::Unavailable(_) => RouterResponse::Unavailable,
35 })
36 }
37}
38
39pub(crate) async fn route_from_fidl<T, R>(
42 router: &Router<T>,
43 payload: fsandbox::RouteRequest,
44) -> Result<R, fsandbox::RouterError>
45where
46 T: CapabilityBound,
47 R: TryFrom<RouterResponse<T>, Error = fsandbox::RouterError>,
48{
49 let resp = match (payload.requesting, payload.metadata) {
50 (Some(token), Some(metadata)) => {
51 let capability =
52 crate::fidl::registry::get(token.token.as_handle_ref().get_koid().unwrap());
53 let component = match capability {
54 Some(crate::Capability::Instance(c)) => c,
55 Some(_) => return Err(fsandbox::RouterError::InvalidArgs),
56 None => return Err(fsandbox::RouterError::InvalidArgs),
57 };
58 let Capability::Dictionary(metadata) =
59 Capability::try_from(fsandbox::Capability::Dictionary(metadata)).unwrap()
60 else {
61 return Err(fsandbox::RouterError::InvalidArgs);
62 };
63 let request = Request { target: component, metadata };
64 router.route(Some(request), false).await?
65 }
66 (None, None) => router.route(None, false).await?,
67 _ => {
68 return Err(fsandbox::RouterError::InvalidArgs);
69 }
70 };
71 resp.try_into()
72}
73
74impl<T: CapabilityBound + Clone> Router<T>
75where
76 Capability: From<T>,
77{
78 pub(crate) fn into_directory_entry(
79 self,
80 entry_type: fio::DirentType,
81 scope: ExecutionScope,
82 ) -> Arc<dyn DirectoryEntry> {
83 struct RouterEntry<T: CapabilityBound> {
84 router: Router<T>,
85 entry_type: fio::DirentType,
86 scope: ExecutionScope,
87 }
88
89 impl<T: CapabilityBound + Clone> DirectoryEntry for RouterEntry<T>
90 where
91 Capability: From<T>,
92 {
93 fn open_entry(
94 self: Arc<Self>,
95 mut request: entry::OpenRequest<'_>,
96 ) -> Result<(), zx::Status> {
97 request.set_scope(self.scope.clone());
98 request.spawn(self);
99 Ok(())
100 }
101 }
102
103 impl<T: CapabilityBound> GetEntryInfo for RouterEntry<T> {
104 fn entry_info(&self) -> EntryInfo {
105 EntryInfo::new(fio::INO_UNKNOWN, self.entry_type)
106 }
107 }
108
109 impl<T: CapabilityBound + Clone> DirectoryEntryAsync for RouterEntry<T>
110 where
111 Capability: From<T>,
112 {
113 async fn open_entry_async(
114 self: Arc<Self>,
115 open_request: entry::OpenRequest<'_>,
116 ) -> Result<(), zx::Status> {
117 let Some(_guard) = open_request.scope().try_active_guard() else {
120 return Err(zx::Status::PEER_CLOSED);
121 };
122
123 let result = match self.router.route(None, false).await {
125 Ok(RouterResponse::<T>::Capability(c)) => Ok(Capability::from(c)),
126 Ok(RouterResponse::<T>::Unavailable) => {
127 return Err(zx::Status::NOT_FOUND);
128 }
129 Ok(RouterResponse::<T>::Debug(_)) => {
130 return Err(zx::Status::INTERNAL);
132 }
133 Err(e) => Err(e),
134 };
135 let error = match result {
136 Ok(capability) => {
137 match capability.try_into_directory_entry(self.scope.clone()) {
138 Ok(open) => return open.open_entry(open_request),
139 Err(_) => RouterError::NotSupported,
140 }
141 }
142 Err(error) => error, };
144 Err(error.as_zx_status())
145 }
146 }
147
148 Arc::new(RouterEntry { router: self, entry_type, scope })
149 }
150}