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