settings/setup/
setup_fidl_handler.rs1use super::setup_controller::{Request, SetupController, SetupError};
6use crate::setup::types::{ConfigurationInterfaceFlags, SetupInfo};
7use async_utils::hanging_get::server;
8use fidl_fuchsia_settings::{
9 Error as SettingsError, SetupRequest, SetupRequestStream, SetupSettings, SetupWatchResponder,
10};
11use fuchsia_async as fasync;
12use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
13use futures::channel::oneshot;
14use futures::StreamExt;
15use settings_common::inspect::event::{
16 RequestType, ResponseType, UsagePublisher, UsageResponsePublisher,
17};
18
19impl From<fidl_fuchsia_settings::ConfigurationInterfaces> for ConfigurationInterfaceFlags {
20 fn from(interfaces: fidl_fuchsia_settings::ConfigurationInterfaces) -> Self {
21 let mut flags = ConfigurationInterfaceFlags::empty();
22
23 if interfaces.intersects(fidl_fuchsia_settings::ConfigurationInterfaces::ETHERNET) {
24 flags |= ConfigurationInterfaceFlags::ETHERNET;
25 }
26
27 if interfaces.intersects(fidl_fuchsia_settings::ConfigurationInterfaces::WIFI) {
28 flags |= ConfigurationInterfaceFlags::WIFI;
29 }
30
31 flags
32 }
33}
34
35impl From<ConfigurationInterfaceFlags> for fidl_fuchsia_settings::ConfigurationInterfaces {
36 fn from(flags: ConfigurationInterfaceFlags) -> Self {
37 let mut interfaces = fidl_fuchsia_settings::ConfigurationInterfaces::empty();
38
39 if flags.intersects(ConfigurationInterfaceFlags::ETHERNET) {
40 interfaces |= fidl_fuchsia_settings::ConfigurationInterfaces::ETHERNET;
41 }
42
43 if flags.intersects(ConfigurationInterfaceFlags::WIFI) {
44 interfaces |= fidl_fuchsia_settings::ConfigurationInterfaces::WIFI;
45 }
46
47 interfaces
48 }
49}
50
51impl From<SetupInfo> for SetupSettings {
52 fn from(info: SetupInfo) -> Self {
53 let mut settings = SetupSettings::default();
54 let interfaces =
55 fidl_fuchsia_settings::ConfigurationInterfaces::from(info.configuration_interfaces);
56
57 if !interfaces.is_empty() {
58 settings.enabled_configuration_interfaces = Some(interfaces);
59 }
60
61 settings
62 }
63}
64
65pub(super) type SubscriberObject = (UsageResponsePublisher<SetupInfo>, SetupWatchResponder);
66type InfoHangingFn = fn(&SetupInfo, SubscriberObject) -> bool;
67pub(super) type InfoHangingGet = server::HangingGet<SetupInfo, SubscriberObject, InfoHangingFn>;
68pub(super) type InfoPublisher = server::Publisher<SetupInfo, SubscriberObject, InfoHangingFn>;
69pub(super) type InfoSubscriber = server::Subscriber<SetupInfo, SubscriberObject, InfoHangingFn>;
70
71pub struct SetupFidlHandler {
72 info_hanging_get: InfoHangingGet,
73 controller_tx: UnboundedSender<Request>,
74 usage_publisher: UsagePublisher<SetupInfo>,
75}
76
77impl SetupFidlHandler {
78 pub(super) fn new(
79 setup_controller: &mut SetupController,
80 usage_publisher: UsagePublisher<SetupInfo>,
81 initial_value: SetupInfo,
82 ) -> (Self, UnboundedReceiver<Request>) {
83 let info_hanging_get = InfoHangingGet::new(initial_value, Self::hanging_get);
84 setup_controller.register_publisher(info_hanging_get.new_publisher());
85 let (controller_tx, controller_rx) = mpsc::unbounded();
86 (Self { info_hanging_get, controller_tx, usage_publisher }, controller_rx)
87 }
88
89 fn hanging_get(info: &SetupInfo, (usage_responder, responder): SubscriberObject) -> bool {
90 usage_responder.respond(format!("{info:?}"), ResponseType::OkSome);
91 if let Err(e) = responder.send(&SetupSettings::from(*info)) {
92 log::warn!("Failed to respond to watch request: {e:?}");
93 return false;
94 }
95 true
96 }
97
98 pub fn handle_stream(&mut self, mut stream: SetupRequestStream) {
99 let request_handler = RequestHandler {
100 subscriber: self.info_hanging_get.new_subscriber(),
101 controller_tx: self.controller_tx.clone(),
102 usage_publisher: self.usage_publisher.clone(),
103 };
104 fasync::Task::local(async move {
105 while let Some(Ok(request)) = stream.next().await {
106 request_handler.handle_request(request).await;
107 }
108 })
109 .detach();
110 }
111}
112
113#[derive(Debug)]
114enum HandlerError {
115 AlreadySubscribed,
116 MissingConfig,
117 ControllerStopped,
118 Controller(SetupError),
119}
120
121impl From<&HandlerError> for ResponseType {
122 fn from(error: &HandlerError) -> Self {
123 match error {
124 HandlerError::AlreadySubscribed => ResponseType::AlreadySubscribed,
125 HandlerError::MissingConfig => ResponseType::InvalidArgument,
126 HandlerError::ControllerStopped => ResponseType::UnexpectedError,
127 HandlerError::Controller(e) => ResponseType::from(e),
128 }
129 }
130}
131
132struct RequestHandler {
133 subscriber: InfoSubscriber,
134 controller_tx: UnboundedSender<Request>,
135 usage_publisher: UsagePublisher<SetupInfo>,
136}
137
138impl RequestHandler {
139 async fn handle_request(&self, request: SetupRequest) {
140 match request {
141 SetupRequest::Watch { responder } => {
142 let usage_res = self.usage_publisher.request("Watch".to_string(), RequestType::Get);
143 if let Err((usage_res, responder)) =
144 self.subscriber.register2((usage_res, responder))
145 {
146 let e = HandlerError::AlreadySubscribed;
147 usage_res.respond(format!("Err({e:?})"), ResponseType::from(&e));
148 drop(responder);
149 }
150 }
151 SetupRequest::Set { settings, reboot_device, responder } => {
152 let usage_res = self.usage_publisher.request(
153 format!("Set{{settings:{settings:?},reboot_device:{reboot_device:?}}}"),
154 RequestType::Set,
155 );
156 if let Err(e) = self.set(settings, reboot_device).await {
157 usage_res.respond(format!("Err({e:?}"), ResponseType::from(&e));
158 let _ = responder.send(Err(SettingsError::Failed));
159 } else {
160 usage_res.respond("Ok(())".to_string(), ResponseType::OkNone);
161 let _ = responder.send(Ok(()));
162 }
163 }
164 }
165 }
166
167 async fn set(&self, settings: SetupSettings, reboot_device: bool) -> Result<(), HandlerError> {
168 let Some(enabled_config_interfaces) = settings.enabled_configuration_interfaces else {
169 return Err(HandlerError::MissingConfig);
170 };
171 let (set_tx, set_rx) = oneshot::channel();
172 self.controller_tx
173 .unbounded_send(Request::Set(
174 ConfigurationInterfaceFlags::from(enabled_config_interfaces),
175 reboot_device,
176 set_tx,
177 ))
178 .map_err(|_| HandlerError::ControllerStopped)?;
179 set_rx
180 .await
181 .map_err(|_| HandlerError::ControllerStopped)
182 .and_then(|res| res.map_err(HandlerError::Controller))
183 }
184}