fission_shell_winit/
wifi.rs1use fission_core::{
2 WifiAvailability, WifiConnectRequest, WifiConnection, WifiDisconnectRequest, WifiError,
3 WifiNetwork, WifiPermission, WifiPermissionRequest, WifiScanRequest, WifiScanResult,
4 WifiSecurity, CONNECT_WIFI_NETWORK, DISCONNECT_WIFI_NETWORK, GET_WIFI_AVAILABILITY,
5 REQUEST_WIFI_PERMISSION, SCAN_WIFI_NETWORKS,
6};
7use fission_shell::async_host::AsyncRegistry;
8use std::sync::Arc;
9
10pub trait WifiHost: Send + Sync + 'static {
12 fn availability(&self) -> Result<WifiAvailability, WifiError>;
14 fn request_permission(
16 &self,
17 request: WifiPermissionRequest,
18 ) -> Result<WifiPermission, WifiError>;
19 fn scan_networks(&self, request: WifiScanRequest) -> Result<WifiScanResult, WifiError>;
21 fn connect_network(&self, request: WifiConnectRequest) -> Result<WifiConnection, WifiError>;
23 fn disconnect_network(&self, request: WifiDisconnectRequest) -> Result<(), WifiError>;
25}
26
27#[derive(Debug, Default)]
28pub struct UnsupportedWifiHost;
29
30impl WifiHost for UnsupportedWifiHost {
31 fn availability(&self) -> Result<WifiAvailability, WifiError> {
32 Ok(WifiAvailability {
33 permission: WifiPermission::Denied,
34 enabled: false,
35 connected_network: None,
36 })
37 }
38
39 fn request_permission(
40 &self,
41 _request: WifiPermissionRequest,
42 ) -> Result<WifiPermission, WifiError> {
43 Err(WifiError::unsupported("request_permission"))
44 }
45
46 fn scan_networks(&self, _request: WifiScanRequest) -> Result<WifiScanResult, WifiError> {
47 Err(WifiError::unsupported("scan_networks"))
48 }
49
50 fn connect_network(&self, _request: WifiConnectRequest) -> Result<WifiConnection, WifiError> {
51 Err(WifiError::unsupported("connect_network"))
52 }
53
54 fn disconnect_network(&self, _request: WifiDisconnectRequest) -> Result<(), WifiError> {
55 Err(WifiError::unsupported("disconnect_network"))
56 }
57}
58
59#[derive(Debug, Clone)]
60pub struct MemoryWifiHost {
61 availability: WifiAvailability,
62 networks: Vec<WifiNetwork>,
63}
64
65impl MemoryWifiHost {
66 pub fn new(availability: WifiAvailability, networks: Vec<WifiNetwork>) -> Self {
67 Self {
68 availability,
69 networks,
70 }
71 }
72}
73
74impl Default for MemoryWifiHost {
75 fn default() -> Self {
76 let network = WifiNetwork {
77 ssid: "Fission".into(),
78 bssid: Some("00:11:22:33:44:55".into()),
79 rssi: Some(-45),
80 frequency_mhz: Some(5_200),
81 security: WifiSecurity::Wpa3,
82 connected: true,
83 };
84 Self::new(
85 WifiAvailability {
86 permission: WifiPermission::Granted,
87 enabled: true,
88 connected_network: Some(network.clone()),
89 },
90 vec![network],
91 )
92 }
93}
94
95impl WifiHost for MemoryWifiHost {
96 fn availability(&self) -> Result<WifiAvailability, WifiError> {
97 Ok(self.availability.clone())
98 }
99
100 fn request_permission(
101 &self,
102 _request: WifiPermissionRequest,
103 ) -> Result<WifiPermission, WifiError> {
104 Ok(self.availability.permission)
105 }
106
107 fn scan_networks(&self, _request: WifiScanRequest) -> Result<WifiScanResult, WifiError> {
108 Ok(WifiScanResult {
109 networks: self.networks.clone(),
110 })
111 }
112
113 fn connect_network(&self, request: WifiConnectRequest) -> Result<WifiConnection, WifiError> {
114 let network = self
115 .networks
116 .iter()
117 .find(|network| network.ssid == request.ssid)
118 .cloned()
119 .ok_or_else(|| WifiError::new("not_found", "Wi-Fi network not found"))?;
120 Ok(WifiConnection { network })
121 }
122
123 fn disconnect_network(&self, _request: WifiDisconnectRequest) -> Result<(), WifiError> {
124 Ok(())
125 }
126}
127
128pub(crate) fn register_wifi_capabilities(
129 async_registry: &mut AsyncRegistry,
130 host: Arc<dyn WifiHost>,
131) {
132 let availability_host = host.clone();
133 async_registry.register_operation_capability(GET_WIFI_AVAILABILITY, move |(), _| {
134 let host = availability_host.clone();
135 async move { host.availability() }
136 });
137
138 let permission_host = host.clone();
139 async_registry.register_operation_capability(REQUEST_WIFI_PERMISSION, move |request, _| {
140 let host = permission_host.clone();
141 async move { host.request_permission(request) }
142 });
143
144 let scan_host = host.clone();
145 async_registry.register_operation_capability(SCAN_WIFI_NETWORKS, move |request, _| {
146 let host = scan_host.clone();
147 async move { host.scan_networks(request) }
148 });
149
150 let connect_host = host.clone();
151 async_registry.register_operation_capability(CONNECT_WIFI_NETWORK, move |request, _| {
152 let host = connect_host.clone();
153 async move { host.connect_network(request) }
154 });
155
156 async_registry.register_operation_capability(DISCONNECT_WIFI_NETWORK, move |request, _| {
157 let host = host.clone();
158 async move { host.disconnect_network(request) }
159 });
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165
166 #[test]
167 fn unsupported_host_reports_errors() {
168 let host = UnsupportedWifiHost;
169 assert!(host.scan_networks(WifiScanRequest::default()).is_err());
170 }
171
172 #[test]
173 fn memory_host_scans_and_connects() {
174 let host = MemoryWifiHost::default();
175 let scan = host.scan_networks(WifiScanRequest::default()).unwrap();
176 assert_eq!(scan.networks.len(), 1);
177
178 let connection = host
179 .connect_network(WifiConnectRequest {
180 ssid: "Fission".into(),
181 security: WifiSecurity::Wpa3,
182 ..Default::default()
183 })
184 .unwrap();
185 assert_eq!(connection.network.ssid, "Fission");
186 }
187}