driver_manager_node/
binding.rs1use crate::node::Node;
6use crate::types::NodeState;
7use driver_manager_shutdown::{RemovalSet, ShutdownIntent};
8use driver_manager_types::{BindResultTracker, ShutdownState};
9use futures::channel::oneshot;
10use log::{error, warn};
11use std::cell::RefCell;
12use std::rc::Rc;
13use {fidl_fuchsia_driver_development as fdd, fidl_fuchsia_driver_framework as fdf};
14
15impl Node {
16 pub async fn complete_bind(self: &Rc<Self>, result: Result<(), zx::Status>) {
17 if result.is_err() {
18 warn!("Bind failed for node '{}'", self.make_component_moniker());
19 if self.shutdown_state() == ShutdownState::Running && !self.is_unbound() {
20 warn!("Quarantining node '{}'", self.make_component_moniker());
21 self.quarantine_node().await;
22 } else {
23 self.set_state(NodeState::Unbound);
24 }
25 }
26
27 if self.is_running() {
28 self.on_bind();
29 }
30
31 let completer = self.take_pending_bind_completer();
32 if let Some(completer) = completer {
33 let _ = completer.send(result);
34 }
35
36 if let Err(status) = &result {
37 self.on_start_error(*status);
38 } else {
39 let completer = self.take_wait_for_driver_completer();
40 if let Some(completer) = completer {
41 if let Some(token) = self.token_handle() {
42 let _ = completer.send(Ok(fdf::DriverResult::DriverStartedNodeToken(token)));
43 } else {
44 let _ = completer.send(Err(zx::Status::INTERNAL));
45 }
46 }
47 }
48
49 self.node_shutdown_coordinator.borrow_mut().check_node_state();
50 }
51
52 pub(crate) fn wait_for_driver(
53 self: &Rc<Self>,
54 completer: oneshot::Sender<Result<fdf::DriverResult, zx::Status>>,
55 ) {
56 if let Some(token) = self.token_handle() {
57 let _ = completer.send(Ok(fdf::DriverResult::DriverStartedNodeToken(token)));
58 return;
59 }
60
61 if self.has_wait_for_driver_completer() {
62 let _ = completer.send(Err(zx::Status::ALREADY_EXISTS));
63 return;
64 }
65
66 self.set_wait_for_driver_completer(completer);
67
68 let node_clone = self.clone();
69 self.scope.spawn_local(async move {
70 node_clone.node_manager.wait_for_bootup().await;
71 let completer = node_clone.take_wait_for_driver_completer();
72 if let Some(completer) = completer {
73 if let Some(result) = node_clone.bind_error() {
74 let response = match result {
75 fdf::DriverResult::MatchError(s) => Ok(fdf::DriverResult::MatchError(s)),
76 fdf::DriverResult::StartError(s) => Ok(fdf::DriverResult::StartError(s)),
77 _ => Err(zx::Status::INTERNAL),
78 };
79 let _ = completer.send(response);
80 return;
81 }
82
83 if let Some(token) = node_clone.token_handle() {
85 let _ = completer.send(Ok(fdf::DriverResult::DriverStartedNodeToken(token)));
86 return;
87 }
88
89 let _ = completer.send(Err(zx::Status::INTERNAL));
90 }
91 });
92 }
93
94 pub(crate) async fn bind(self: &Rc<Self>, driver: String) -> Result<(), zx::Status> {
95 self.bind_helper(false, Some(driver)).await
96 }
97
98 pub(crate) async fn bind_helper(
99 self: &Rc<Self>,
100 force_rebind: bool,
101 driver_url_suffix: Option<String>,
102 ) -> Result<(), zx::Status> {
103 if !force_rebind && self.is_bound() {
104 return Err(zx::Status::ALREADY_BOUND);
105 }
106
107 if self.has_pending_bind_completer() {
108 return Err(zx::Status::ALREADY_EXISTS);
109 }
110
111 let (tx, rx) = oneshot::channel();
112 if self.is_bound() {
113 self.restart_node_with_rematch(driver_url_suffix, tx);
114 } else {
115 self.set_pending_bind_completer(tx);
116 let tracker = self.create_bind_result_tracker(false);
117 if let Some(driver_url_suffix) = driver_url_suffix {
118 self.node_manager.bind_to_url(self, &driver_url_suffix, tracker);
119 } else {
120 self.node_manager.bind(self, tracker);
121 }
122 }
123 rx.await.map_err(|_| zx::Status::INTERNAL)?
124 }
125
126 pub(crate) fn create_bind_result_tracker(
127 self: &Rc<Self>,
128 silent: bool,
129 ) -> Rc<RefCell<BindResultTracker>> {
130 let weak_self = Rc::downgrade(self);
131 let (tx, rx) = oneshot::channel::<Vec<fdd::NodeBindingInfo>>();
132 self.scope.spawn_local(async move {
133 let Ok(info) = rx.await else {
134 return;
135 };
136 let Some(self_ptr) = weak_self.upgrade() else {
137 return;
138 };
139 if info.is_empty() {
140 self_ptr.set_state(NodeState::Unbound);
141 self_ptr.on_match_error(zx::Status::NOT_FOUND);
142 if !silent {
143 self_ptr.complete_bind(Err(zx::Status::NOT_FOUND)).await;
144 }
145 } else if info.len() > 1 {
146 error!("Unexpectedly bound multiple drivers to a single node");
147 self_ptr.on_match_error(zx::Status::BAD_STATE);
148 if !silent {
149 self_ptr.complete_bind(Err(zx::Status::BAD_STATE)).await;
150 }
151 }
152 });
153
154 Rc::new(RefCell::new(BindResultTracker::new(1, tx)))
155 }
156
157 pub(crate) async fn rebind(self: &Rc<Self>, driver: Option<String>) -> Result<(), zx::Status> {
158 let (tx, rx) = oneshot::channel();
159 self.restart_node_with_rematch(driver, tx);
160 rx.await.map_err(|_| zx::Status::INTERNAL)?
161 }
162
163 pub(crate) async fn unbind_children(self: &Rc<Self>) -> Result<(), zx::Status> {
164 let children = self.children();
165 if children.is_empty() {
166 return Ok(());
167 }
168
169 let rx = {
170 let (tx, rx) = oneshot::channel();
171 self.push_unbinding_children_completer(tx);
172 if self.unbinding_children_completers_len() == 1 {
173 for child in children {
174 child.remove(RemovalSet::All, None);
175 }
176 }
177 rx
178 };
179 rx.await.map_err(|_| zx::Status::INTERNAL)?
180 }
181
182 pub(crate) fn schedule_unbind(self: &Rc<Self>) {
183 self.remove(RemovalSet::All, None);
184 }
185
186 pub fn restart_node_with_rematch(
187 self: &Rc<Self>,
188 restart_driver_url_suffix: Option<String>,
189 completer: oneshot::Sender<Result<(), zx::Status>>,
190 ) {
191 if self.has_pending_bind_completer() {
192 let _ = completer.send(Err(zx::Status::ALREADY_EXISTS));
193 return;
194 }
195
196 self.set_pending_bind_completer(completer);
197 if let Some(suffix) = restart_driver_url_suffix {
198 self.set_restart_driver_url_suffix(suffix);
199 }
200 self.restart_node();
201 }
202
203 pub fn restart_node(self: &Rc<Self>) {
204 self.node_shutdown_coordinator.borrow_mut().set_shutdown_intent(ShutdownIntent::Restart);
205 self.remove(RemovalSet::All, None);
206 }
207
208 pub(crate) async fn quarantine_node(self: &Rc<Self>) {
209 if !self.quarantine_start() {
210 panic!("QuarantineNode called from unexpected state");
211 }
212
213 self.node_shutdown_coordinator.borrow_mut().set_shutdown_intent(ShutdownIntent::Quarantine);
214 self.remove(RemovalSet::All, None);
215 }
216
217 fn on_bind(&self) {
218 if let Some(node_token) = self.token_handle() {
219 if let Some(controller_ref) = self.node_controller_ref() {
220 let event = fdf::NodeControllerOnBindRequest {
221 node_token: Some(node_token.duplicate(zx::Rights::SAME_RIGHTS).unwrap()),
222 ..Default::default()
223 };
224 if let Err(e) = controller_ref.send_on_bind(event) {
225 error!("Failed to send OnBind event: {}", e);
226 }
227 }
228
229 let koid = self.token_koid().unwrap().raw_koid();
230 if let Some(driver_host) = self.driver_host() {
231 let node_manager = self.node_manager.clone_box();
232 self.scope.spawn_local(async move {
233 if let Ok(process_koid) = driver_host.get_process_koid().await
234 && let Some(attributor) = node_manager.memory_attributor()
235 {
236 attributor.add_driver(node_token, koid, process_koid);
237 }
238 });
239 }
240 }
241 }
242}