settings_setup/
setup_fidl_handler.rs1use crate::setup_controller::{Request, SetupController, SetupError};
6use crate::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::StreamExt;
13use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
14use futures::channel::oneshot;
15use settings_common::inspect::event::{
16 HangingGetObserver, RequestType, ResponseType, UsagePublisher,
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 = HangingGetObserver<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, observer: SubscriberObject) -> bool {
90 let (usage_responder, responder) = observer.into_parts();
91 usage_responder.respond(format!("{info:?}"), ResponseType::OkSome);
92 if let Err(e) = responder.send(&SetupSettings::from(*info)) {
93 log::warn!("Failed to respond to watch request: {e:?}");
94 return false;
95 }
96 true
97 }
98
99 pub fn handle_stream(&mut self, mut stream: SetupRequestStream) {
100 let request_handler = RequestHandler {
101 subscriber: self.info_hanging_get.new_subscriber(),
102 controller_tx: self.controller_tx.clone(),
103 usage_publisher: self.usage_publisher.clone(),
104 };
105 fasync::Task::local(async move {
106 while let Some(Ok(request)) = stream.next().await {
107 request_handler.handle_request(request).await;
108 }
109 })
110 .detach();
111 }
112}
113
114#[derive(Debug)]
115enum HandlerError {
116 AlreadySubscribed,
117 MissingConfig,
118 ControllerStopped,
119 Controller(SetupError),
120}
121
122impl From<&HandlerError> for ResponseType {
123 fn from(error: &HandlerError) -> Self {
124 match error {
125 HandlerError::AlreadySubscribed => ResponseType::AlreadySubscribed,
126 HandlerError::MissingConfig => ResponseType::InvalidArgument,
127 HandlerError::ControllerStopped => ResponseType::UnexpectedError,
128 HandlerError::Controller(e) => ResponseType::from(e),
129 }
130 }
131}
132
133struct RequestHandler {
134 subscriber: InfoSubscriber,
135 controller_tx: UnboundedSender<Request>,
136 usage_publisher: UsagePublisher<SetupInfo>,
137}
138
139impl RequestHandler {
140 async fn handle_request(&self, request: SetupRequest) {
141 match request {
142 SetupRequest::Watch { responder } => {
143 let usage_res = self.usage_publisher.request("Watch".to_string(), RequestType::Get);
144 let observer = HangingGetObserver::new(usage_res, responder);
145 if let Err(observer) = self.subscriber.register2(observer) {
146 let e = HandlerError::AlreadySubscribed;
147 let (usage_res, responder) = observer.into_parts();
148 usage_res.respond(format!("Err({e:?})"), ResponseType::from(&e));
149 drop(responder);
150 }
151 }
152 SetupRequest::Set { settings, reboot_device, responder } => {
153 let usage_res = self.usage_publisher.request(
154 format!("Set{{settings:{settings:?},reboot_device:{reboot_device:?}}}"),
155 RequestType::Set,
156 );
157 if let Err(e) = self.set(settings, reboot_device).await {
158 usage_res.respond(format!("Err({e:?}"), ResponseType::from(&e));
159 let _ = responder.send(Err(SettingsError::Failed));
160 } else {
161 usage_res.respond("Ok(())".to_string(), ResponseType::OkNone);
162 let _ = responder.send(Ok(()));
163 }
164 }
165 }
166 }
167
168 async fn set(&self, settings: SetupSettings, reboot_device: bool) -> Result<(), HandlerError> {
169 let Some(enabled_config_interfaces) = settings.enabled_configuration_interfaces else {
170 return Err(HandlerError::MissingConfig);
171 };
172 let (set_tx, set_rx) = oneshot::channel();
173 self.controller_tx
174 .unbounded_send(Request::Set(
175 ConfigurationInterfaceFlags::from(enabled_config_interfaces),
176 reboot_device,
177 set_tx,
178 ))
179 .map_err(|_| HandlerError::ControllerStopped)?;
180 set_rx
181 .await
182 .map_err(|_| HandlerError::ControllerStopped)
183 .and_then(|res| res.map_err(HandlerError::Controller))
184 }
185}