input_pipeline/
incoming.rs1use crate::Transport;
6use anyhow::Context;
7use fidl_fuchsia_io as fio;
8use fuchsia_component::client::Connect;
9use fuchsia_component::directory::{AsRefDirectory, Directory};
10
11#[cfg(feature = "dso")]
12pub use dso::*;
13
14#[cfg(not(feature = "dso"))]
15pub use elf::*;
16
17mod dso {
18 #![cfg(feature = "dso")]
19
20 use super::*;
21 use crate::DriverTransport;
22
23 #[derive(Clone)]
24 pub struct Incoming(std::sync::Arc<fdf_component::Incoming>);
25
26 impl Incoming {
27 pub fn new(incoming: std::sync::Arc<fdf_component::Incoming>) -> Self {
28 Self(incoming)
29 }
30
31 pub fn open_service<S: fidl::endpoints::ServiceMarker>(
32 &self,
33 marker: S,
34 ) -> Result<fuchsia_component::client::Service<S>, anyhow::Error> {
35 fuchsia_component::client::Service::open_from_dir_prefix(&*self.0, "svc", marker)
36 .context("Service::open_from_dir_prefix")
37 }
38
39 pub fn connect_protocol<T: Connect>(&self) -> Result<T, anyhow::Error> {
40 self.0.connect_protocol().context("connect_protocol")
41 }
42
43 pub fn connect_protocol_next<P: fidl_next::Discoverable>(
44 &self,
45 ) -> Result<fidl_next::ClientEnd<P, Transport>, anyhow::Error> {
46 self.0.connect_protocol_libasync_next().context("connect_protocol_next")
47 }
48
49 pub fn connect_protocol_next_at<P: fidl_next::Discoverable>(
50 dir: &impl AsRefDirectory,
51 path: &str,
52 ) -> Result<fidl_next::ClientEnd<P, Transport>, anyhow::Error> {
53 fdf_component::Incoming::connect_protocol_libasync_next_at(dir, path)
54 .context("connect_protocol_next_at")
55 }
56
57 pub fn connect_protocol_driver_transport<P: fidl_next::Discoverable>(
58 &self,
59 ) -> Result<fidl_next::ClientEnd<P, DriverTransport>, zx::Status> {
60 self.0.connect_protocol_driver_transport::<P, _>(fdf::CurrentDispatcher)
61 }
62
63 pub fn connect_protocol_driver_transport_at<P: fidl_next::Discoverable>(
64 dir: &impl AsRefDirectory,
65 path: &str,
66 ) -> Result<fidl_next::ClientEnd<P, DriverTransport>, zx::Status> {
67 fdf_component::Incoming::connect_protocol_driver_transport_at::<P, _>(
68 dir,
69 path,
70 fdf::CurrentDispatcher,
71 )
72 }
73 }
74
75 impl Directory for Incoming {
76 fn open(
77 &self,
78 path: &str,
79 flags: fio::Flags,
80 server_end: zx::Channel,
81 ) -> Result<(), anyhow::Error> {
82 self.0.open(path, flags, server_end)
83 }
84 }
85}
86
87mod elf {
88 #![cfg(not(feature = "dso"))]
89
90 use super::*;
91 use fuchsia_component::client::connect;
92
93 #[derive(Clone)]
94 pub struct Incoming;
95
96 impl Incoming {
97 pub fn new() -> Self {
98 Self {}
99 }
100
101 pub fn open_service<S: fidl::endpoints::ServiceMarker>(
102 &self,
103 marker: S,
104 ) -> Result<fuchsia_component::client::Service<S>, anyhow::Error> {
105 fuchsia_component::client::Service::open(marker).context("Service::open")
106 }
107
108 pub fn connect_protocol<T: Connect>(&self) -> Result<T, anyhow::Error> {
109 connect::connect_to_protocol::<T>()
110 }
111
112 pub fn connect_protocol_next<P: fidl_next::Discoverable>(
113 &self,
114 ) -> Result<fidl_next::ClientEnd<P, Transport>, anyhow::Error> {
115 let (client_end, server_end) = zx::Channel::create();
116 fdio::service_connect(&format!("/svc/{}", P::PROTOCOL_NAME), server_end)
117 .context("connect_protocol_next")?;
118 Ok(fidl_next::ClientEnd::<P, zx::Channel>::from_untyped(client_end))
119 }
120
121 pub fn connect_protocol_next_at<P: fidl_next::Discoverable>(
122 dir: &impl AsRefDirectory,
123 path: &str,
124 ) -> Result<fidl_next::ClientEnd<P, Transport>, anyhow::Error> {
125 let (client_end, server_end) = zx::Channel::create();
126 dir.as_ref_directory().open(path, fio::Flags::PROTOCOL_SERVICE, server_end)?;
127 Ok(fidl_next::ClientEnd::<P, zx::Channel>::from_untyped(client_end))
128 }
129 }
130
131 impl Directory for Incoming {
132 fn open(
133 &self,
134 path: &str,
135 flags: fio::Flags,
136 server_end: zx::Channel,
137 ) -> Result<(), anyhow::Error> {
138 let path = path.trim_start_matches('/');
139 let absolute_path = if path.starts_with("svc/")
140 || path == "svc"
141 || path.starts_with("pkg/")
142 || path == "pkg"
143 || path.starts_with("dev/")
144 || path == "dev"
145 || path.starts_with("tmp/")
146 || path == "tmp"
147 || path.starts_with("hub/")
148 || path == "hub"
149 || path.starts_with("data/")
150 || path == "data"
151 || path.starts_with("cache/")
152 || path == "cache"
153 || path.starts_with("config/")
154 || path == "config"
155 || path.starts_with("incoming/")
156 || path == "incoming"
157 {
158 format!("/{}", path)
159 } else if path.is_empty() {
160 "/".to_string()
161 } else {
162 format!("/svc/{}", path)
165 };
166
167 let namespace =
168 fdio::Namespace::installed().context("failed to get installed namespace")?;
169 namespace.open(&absolute_path, flags, server_end).context("Namespace::open")
170 }
171 }
172}
173
174impl AsRefDirectory for Incoming {
175 fn as_ref_directory(&self) -> &dyn fuchsia_component::directory::Directory {
176 self
177 }
178}