Skip to main content

driver_manager_node/
serve.rs

1// Copyright 2026 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::node::{Node, NodeComponent};
6use driver_manager_shutdown::RemovalSet;
7use driver_manager_types::{ShutdownState, StartRequestReceiver};
8use fidl::endpoints::{ControlHandle, ServerEnd};
9use fuchsia_async::{self as fasync};
10use futures::channel::oneshot;
11use futures::{StreamExt, TryStreamExt};
12use log::{debug, warn};
13use std::rc::Rc;
14use {
15    fidl_fuchsia_component as fcomponent, fidl_fuchsia_component_runner as frunner,
16    fidl_fuchsia_driver_framework as fdf, fidl_fuchsia_driver_host as fdh,
17};
18
19#[derive(Debug)]
20pub struct NodeServerBinding {
21    pub node_ref: fdf::NodeControlHandle,
22    server_task: Option<fasync::Task<()>>,
23    close_listener_task: Option<fasync::Task<()>>,
24}
25
26impl NodeServerBinding {
27    pub fn new(
28        node_ref: fdf::NodeControlHandle,
29        server_task: Option<fasync::Task<()>>,
30        close_listener_task: Option<fasync::Task<()>>,
31    ) -> Self {
32        NodeServerBinding { node_ref, server_task, close_listener_task }
33    }
34
35    pub fn close(self) {
36        self.node_ref.shutdown_with_epitaph(zx::Status::OK);
37    }
38}
39
40impl Drop for NodeServerBinding {
41    fn drop(&mut self) {
42        if let Some(t) = self.close_listener_task.take() {
43            drop(t.abort());
44        }
45
46        if let Some(t) = self.server_task.take() {
47            drop(t.abort());
48        }
49    }
50}
51
52#[derive(Debug)]
53pub struct NodeControllerServerBinding {
54    pub node_controller_ref: fdf::NodeControllerControlHandle,
55    server_task: Option<fasync::Task<()>>,
56    close_listener_task: Option<fasync::Task<()>>,
57}
58
59impl NodeControllerServerBinding {
60    pub fn new(
61        node_controller_ref: fdf::NodeControllerControlHandle,
62        server_task: Option<fasync::Task<()>>,
63        close_listener_task: Option<fasync::Task<()>>,
64    ) -> Self {
65        NodeControllerServerBinding { node_controller_ref, server_task, close_listener_task }
66    }
67
68    pub fn close(self) {
69        self.node_controller_ref.shutdown_with_epitaph(zx::Status::OK);
70    }
71}
72
73impl Drop for NodeControllerServerBinding {
74    fn drop(&mut self) {
75        if let Some(t) = self.close_listener_task.take() {
76            drop(t.abort());
77        }
78
79        if let Some(t) = self.server_task.take() {
80            drop(t.abort());
81        }
82    }
83}
84
85#[derive(Debug)]
86pub struct ComponentRunnerComponentControllerServerBinding {
87    pub control_handle: frunner::ComponentControllerControlHandle,
88    server_task: Option<fasync::Task<()>>,
89    close_listener_task: Option<fasync::Task<()>>,
90}
91
92impl ComponentRunnerComponentControllerServerBinding {
93    pub fn new(
94        control_handle: frunner::ComponentControllerControlHandle,
95        server_task: Option<fasync::Task<()>>,
96        close_listener_task: Option<fasync::Task<()>>,
97    ) -> Self {
98        ComponentRunnerComponentControllerServerBinding {
99            control_handle,
100            server_task,
101            close_listener_task,
102        }
103    }
104}
105
106impl Drop for ComponentRunnerComponentControllerServerBinding {
107    fn drop(&mut self) {
108        if let Some(t) = self.close_listener_task.take() {
109            drop(t.abort());
110        }
111
112        if let Some(t) = self.server_task.take() {
113            drop(t.abort());
114        }
115    }
116}
117
118pub struct ComponentControllerClientBinding {
119    pub component_controller_proxy: fcomponent::ControllerProxy,
120    close_listener_task: Option<fasync::Task<()>>,
121}
122
123impl ComponentControllerClientBinding {
124    pub fn new(
125        component_controller_proxy: fcomponent::ControllerProxy,
126        close_listener_task: Option<fasync::Task<()>>,
127    ) -> Self {
128        ComponentControllerClientBinding { component_controller_proxy, close_listener_task }
129    }
130}
131
132impl Drop for ComponentControllerClientBinding {
133    fn drop(&mut self) {
134        if let Some(t) = self.close_listener_task.take() {
135            drop(t.abort());
136        }
137    }
138}
139
140#[derive(Debug)]
141pub struct DriverHostClientBinding {
142    pub driver_host_proxy: fdh::DriverProxy,
143    close_listener_task: Option<fasync::Task<()>>,
144}
145
146impl DriverHostClientBinding {
147    pub fn new(
148        driver_host_proxy: fdh::DriverProxy,
149        close_listener_task: Option<fasync::Task<()>>,
150    ) -> Self {
151        DriverHostClientBinding { driver_host_proxy, close_listener_task }
152    }
153}
154
155impl Drop for DriverHostClientBinding {
156    fn drop(&mut self) {
157        if let Some(t) = self.close_listener_task.take() {
158            drop(t.abort());
159        }
160    }
161}
162
163impl Node {
164    pub async fn set_created_info(
165        self: &Rc<Self>,
166        proxy: fcomponent::ControllerProxy,
167        handle_info: fidl_fuchsia_process::HandleInfo,
168        receiver: StartRequestReceiver,
169    ) {
170        let self_clone = self.clone();
171
172        let (sender, local_receiver) = oneshot::channel();
173        self.scope.spawn_local(async move {
174            let stream = proxy.take_event_stream();
175            let weak_node = self_clone.weak_from_this();
176            let close_listener_task = Some(fasync::Task::local(async move {
177                // There is no specific event in this stream, we just want to know when it is closed.
178                stream.for_each(|_| async {}).await;
179                if let Some(node) = weak_node.upgrade() {
180                    node.take_component();
181                    node.on_component_controller_closed();
182                }
183            }));
184            self_clone.set_component(NodeComponent {
185                controller: ComponentControllerClientBinding::new(proxy, close_listener_task),
186                start_handles: Some(vec![handle_info]),
187                start_request_receiver: Some(receiver),
188            });
189            sender.send(()).unwrap();
190        });
191        local_receiver.await.unwrap();
192    }
193
194    pub(crate) fn serve_node(
195        self: &Rc<Self>,
196        node: ServerEnd<fdf::NodeMarker>,
197    ) -> NodeServerBinding {
198        let (mut stream, control_handle) = node.into_stream_and_control_handle();
199        let control_handle_clone = control_handle.clone();
200        let weak_self = Rc::downgrade(self);
201
202        let close_listener_task = Some(fasync::Task::local(async move {
203            let result = control_handle_clone.on_closed().await;
204            if let Some(this) = weak_self.upgrade() {
205                this.on_node_closed(result);
206            }
207        }));
208
209        let weak_self = Rc::downgrade(self);
210        let server_task = Some(fasync::Task::local(async move {
211            while let Some(Ok(msg)) = stream.next().await {
212                let Some(this) = weak_self.upgrade() else {
213                    break;
214                };
215                match msg {
216                    fdf::NodeRequest::AddChild { args, controller, node, responder } => {
217                        let _ = responder
218                            .send(this.add_child(args, Some(controller), node).await.map(|_| ()));
219                    }
220                    _ => {
221                        log::warn!("received unknown method.");
222                    }
223                };
224            }
225        }));
226
227        NodeServerBinding::new(control_handle, server_task, close_listener_task)
228    }
229
230    pub(crate) fn serve_node_controller(
231        self: &Rc<Self>,
232        node_controller: ServerEnd<fdf::NodeControllerMarker>,
233    ) -> NodeControllerServerBinding {
234        let (mut stream, control_handle) = node_controller.into_stream_and_control_handle();
235
236        let weak_self = Rc::downgrade(self);
237        let control_handle_clone = control_handle.clone();
238        let close_listener_task = Some(fasync::Task::local(async move {
239            let _ = control_handle_clone.on_closed().await;
240            if let Some(this) = weak_self.upgrade() {
241                this.take_node_controller();
242            }
243        }));
244
245        let weak_self = Rc::downgrade(self);
246        let server_task = Some(fasync::Task::local(async move {
247            while let Some(Ok(msg)) = stream.next().await {
248                let Some(this) = weak_self.upgrade() else {
249                    break;
250                };
251                match msg {
252                    fdf::NodeControllerRequest::RequestBind { payload, responder } => {
253                        let result = this
254                            .bind_helper(
255                                payload.force_rebind.unwrap_or(false),
256                                payload.driver_url_suffix,
257                            )
258                            .await;
259                        let _ = responder.send(result.map_err(zx::Status::into_raw));
260                    }
261                    fdf::NodeControllerRequest::Remove { .. } => {
262                        this.set_should_destroy_driver_component(true);
263                        this.remove(RemovalSet::All, None);
264                    }
265                    fdf::NodeControllerRequest::WaitForDriver { responder } => {
266                        let (tx, rx) = oneshot::channel();
267                        this.wait_for_driver(tx);
268                        this.scope.spawn_local(async move {
269                            match rx.await {
270                                Ok(result) => {
271                                    let _ = responder.send(result.map_err(zx::Status::into_raw));
272                                }
273                                Err(_) => {
274                                    let _ = responder.send(Err(zx::Status::CANCELED.into_raw()));
275                                }
276                            }
277                        });
278                    }
279                    _ => {
280                        log::warn!("received unknown method.");
281                    }
282                };
283            }
284        }));
285
286        NodeControllerServerBinding::new(control_handle, server_task, close_listener_task)
287    }
288
289    pub(crate) fn serve_runner_component_controller(
290        self: &Rc<Self>,
291        runner_component_controller: ServerEnd<frunner::ComponentControllerMarker>,
292    ) -> ComponentRunnerComponentControllerServerBinding {
293        let (controller_stream, control_handle) =
294            runner_component_controller.into_stream_and_control_handle();
295
296        let weak_self = Rc::downgrade(self);
297        let control_handle_clone = control_handle.clone();
298        let close_listener_task = Some(fasync::Task::local(async move {
299            let _ = control_handle_clone.on_closed().await;
300            if let Some(this) = weak_self.upgrade() {
301                this.take_node_controller();
302                this.on_runner_component_controller_closed();
303            }
304        }));
305
306        let weak_self = self.weak_from_this();
307        let server_task = Some(fasync::Task::local(async move {
308            let mut stream: frunner::ComponentControllerRequestStream = controller_stream;
309            while let Ok(Some(s)) = stream.try_next().await {
310                match s {
311                    frunner::ComponentControllerRequest::Stop { .. } => {
312                        if let Some(node) = weak_self.upgrade() {
313                            debug!(
314                                "Node: '{}' received stop from component framework",
315                                node.make_component_moniker()
316                            );
317                            node.remove(RemovalSet::All, None);
318                        }
319                    }
320                    frunner::ComponentControllerRequest::Kill { .. } => {
321                        if let Some(node) = weak_self.upgrade() {
322                            debug!(
323                                "Node: '{}' received kill from component framework",
324                                node.make_component_moniker()
325                            );
326                            node.remove(RemovalSet::All, None);
327                        }
328                    }
329                    _ => {}
330                }
331            }
332        }));
333
334        ComponentRunnerComponentControllerServerBinding::new(
335            control_handle,
336            server_task,
337            close_listener_task,
338        )
339    }
340
341    pub(crate) fn serve_driver_host_client(
342        &self,
343        driver_host_proxy: fdh::DriverProxy,
344    ) -> DriverHostClientBinding {
345        let weak_self = self.weak_from_this();
346        let mut driver_event_stream = driver_host_proxy.take_event_stream();
347        let close_listener_task = Some(fasync::Task::local(async move {
348            if let Some(event) = driver_event_stream.next().await {
349                // The only valid way a driver host should shut down the Driver channel
350                // is with the ZX_OK epitaph.
351                // TODO(b/322235974): Increase the log severity to ERROR once we resolve the
352                // component shutdown order in DriverTestRealm.
353                let Err(e) = event;
354                if let fidl::Error::ClientChannelClosed { status, .. } = e
355                    && status == zx::Status::OK
356                {
357                } else {
358                    warn!("Node: driver channel shutdown with: {e}");
359                }
360            }
361
362            let Some(this) = weak_self.upgrade() else {
363                return;
364            };
365            this.clear_driver_host();
366
367            let moniker = this.make_component_moniker();
368
369            let shutdown_state = this.shutdown_state();
370            if shutdown_state == ShutdownState::WaitingOnDriver {
371                debug!("Node: {moniker}: driver channel had expected shutdown.");
372                this.node_shutdown_coordinator.borrow_mut().check_node_state();
373                return;
374            }
375
376            if this.host_restart_on_crash() {
377                warn!("Restarting node {moniker} because of unexpected driver channel shutdown.");
378                this.restart_node();
379                return;
380            }
381
382            // If the driver fails to bind to the node, don't remove the node.
383            if this.is_pending_bind() {
384                debug!("Node: {moniker}: driver channel closed during binding.");
385                return;
386            }
387
388            warn!("Removing node {moniker} because of unexpected driver channel shutdown.");
389            this.remove(RemovalSet::All, None);
390        }));
391
392        DriverHostClientBinding::new(driver_host_proxy, close_listener_task)
393    }
394
395    fn on_node_closed(self: &Rc<Self>, result: Result<zx::Signals, fidl::Status>) {
396        // If the unbind is initiated from us, we don't need to do anything to handle
397        // the closure.
398        if self.node_shutdown_coordinator.borrow().is_shutting_down() {
399            return;
400        }
401
402        // If the driver fails to bind to the node, don't remove the node.
403        if self.is_pending_bind() {
404            warn!("The driver for node {} failed to bind.", self.name());
405            return;
406        }
407
408        if self.shutdown_state() == ShutdownState::Running {
409            // If the node is running but this node closure has happened, then we want to restart
410            // the node if it has the host_restart_on_crash_ enabled on it.
411            if self.host_restart_on_crash() {
412                warn!("Restarting node {} due to node closure while running.", self.name());
413                self.restart_node();
414                return;
415            }
416
417            warn!(
418                "fdf::Node binding for node {} closed while the node was running: {:?}",
419                self.name(),
420                result
421            );
422        }
423
424        self.remove(RemovalSet::All, None);
425    }
426
427    fn on_component_controller_closed(self: &Rc<Self>) {
428        if self.node_shutdown_coordinator.borrow().node_state() == &ShutdownState::WaitingOnDestroy
429        {
430            debug!(
431                "Node '{}': component controller channel had expected shutdown.",
432                self.make_component_moniker()
433            );
434            self.node_shutdown_coordinator.borrow_mut().check_node_state();
435            return;
436        }
437
438        warn!(
439            "Node '{}': unexpected component controller channel shutdown. in state {:?}",
440            self.make_component_moniker(),
441            self.node_shutdown_coordinator.borrow().node_state()
442        );
443    }
444
445    fn on_runner_component_controller_closed(self: &Rc<Self>) {
446        let node_state = self.shutdown_state();
447        if self.has_driver_component() {
448            if node_state == ShutdownState::WaitingOnDriverComponent {
449                debug!(
450                    "Node '{}': runner component controller channel had expected close",
451                    self.make_component_moniker()
452                );
453                self.set_driver_stopped();
454                self.node_shutdown_coordinator.borrow_mut().check_node_state();
455            } else {
456                warn!(
457                    "Node '{}': runner component controller channel had unexpected close",
458                    self.make_component_moniker()
459                );
460                self.set_driver_stopped();
461                self.remove(RemovalSet::All, None);
462            }
463        }
464    }
465}