wifi_ctrl/sta/
client.rs

1use super::*;
2
3/// A vector of ScanResult, wrapped in an Arc. If more than one client is awaiting the result of a
4/// scan, the result will be shared between them.
5pub type ScanResults = Arc<Vec<ScanResult>>;
6
7#[derive(Debug)]
8/// Result from selecting a network, including a success or a specific failure (eg: incorect psk).
9/// Timeout does not necessarily mean failure; it only means that we did not received a parseable response.
10/// It could be that some valid message isn't being parsed by the library.
11pub enum SelectResult {
12    Success,
13    WrongPsk,
14    NotFound,
15    PendingSelect,
16    InvalidNetworkId,
17    Timeout,
18    AlreadyConnected,
19}
20
21use std::fmt;
22
23impl fmt::Display for SelectResult {
24    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25        let s = match self {
26            SelectResult::Success => "success",
27            SelectResult::WrongPsk => "wrong_psk",
28            SelectResult::NotFound => "network_not_found",
29            SelectResult::PendingSelect => "select_already_pending",
30            SelectResult::InvalidNetworkId => "invalid_network_id",
31            SelectResult::Timeout => "select_timeout",
32            SelectResult::AlreadyConnected => "already_connected",
33        };
34        write!(f, "{s}")
35    }
36}
37
38#[derive(Debug)]
39pub(crate) enum Request {
40    Custom(String, oneshot::Sender<Result<String>>),
41    Status(oneshot::Sender<Result<Status>>),
42    Networks(oneshot::Sender<Result<Vec<NetworkResult>>>),
43    Scan(oneshot::Sender<Result<ScanResults>>),
44    AddNetwork(oneshot::Sender<Result<usize>>),
45    SetNetwork(usize, SetNetwork, oneshot::Sender<Result>),
46    SaveConfig(oneshot::Sender<Result>),
47    RemoveNetwork(usize, oneshot::Sender<Result>),
48    RemoveAllNetworks(oneshot::Sender<Result>),
49    SelectNetwork(usize, oneshot::Sender<Result<SelectResult>>),
50    Shutdown,
51    SelectTimeout,
52}
53
54impl ShutdownSignal for Request {
55    fn is_shutdown(&self) -> bool {
56        matches!(self, Request::Shutdown)
57    }
58    fn inform_of_shutdown(self) {
59        match self {
60            Request::Custom(_, response) => {
61                let _ = response.send(Err(error::Error::StartupAborted));
62            }
63            Request::Status(response) => {
64                let _ = response.send(Err(error::Error::StartupAborted));
65            }
66            Request::Networks(response) => {
67                let _ = response.send(Err(error::Error::StartupAborted));
68            }
69            Request::Scan(response) => {
70                let _ = response.send(Err(error::Error::StartupAborted));
71            }
72            Request::AddNetwork(response) => {
73                let _ = response.send(Err(error::Error::StartupAborted));
74            }
75            Request::SetNetwork(_, _, response) => {
76                let _ = response.send(Err(error::Error::StartupAborted));
77            }
78            Request::SaveConfig(response) => {
79                let _ = response.send(Err(error::Error::StartupAborted));
80            }
81            Request::RemoveNetwork(_, response) => {
82                let _ = response.send(Err(error::Error::StartupAborted));
83            }
84            Request::RemoveAllNetworks(response) => {
85                let _ = response.send(Err(error::Error::StartupAborted));
86            }
87            Request::SelectNetwork(_, response) => {
88                let _ = response.send(Err(error::Error::StartupAborted));
89            }
90            Request::Shutdown => {}
91            Request::SelectTimeout => {}
92        }
93    }
94}
95
96#[derive(Debug)]
97pub(crate) enum SetNetwork {
98    Ssid(String),
99    Bssid(String),
100    Psk(String),
101    KeyMgmt(KeyMgmt),
102}
103
104#[derive(Clone)]
105/// Request client wraps the request events, awaiting oneshot channels when appropriate
106pub struct RequestClient {
107    sender: mpsc::Sender<Request>,
108}
109
110impl RequestClient {
111    pub(crate) fn new(sender: mpsc::Sender<Request>) -> RequestClient {
112        RequestClient { sender }
113    }
114
115    async fn send_request(&self, request: Request) -> Result {
116        self.sender
117            .send(request)
118            .await
119            .map_err(|_| error::Error::WifiStationRequestChannelClosed)?;
120        Ok(())
121    }
122
123    pub async fn send_custom(&self, custom: String) -> Result<String> {
124        let (response, request) = oneshot::channel();
125        self.send_request(Request::Custom(custom, response)).await?;
126        request.await?
127    }
128
129    pub async fn get_scan(&self) -> Result<Arc<Vec<ScanResult>>> {
130        let (response, request) = oneshot::channel();
131        self.send_request(Request::Scan(response)).await?;
132        request.await?
133    }
134
135    pub async fn get_networks(&self) -> Result<Vec<NetworkResult>> {
136        let (response, request) = oneshot::channel();
137        self.send_request(Request::Networks(response)).await?;
138        request.await?
139    }
140
141    pub async fn get_status(&self) -> Result<Status> {
142        let (response, request) = oneshot::channel();
143        self.send_request(Request::Status(response)).await?;
144        request.await?
145    }
146
147    pub async fn add_network(&self) -> Result<usize> {
148        let (response, request) = oneshot::channel();
149        self.send_request(Request::AddNetwork(response)).await?;
150        request.await?
151    }
152
153    pub async fn set_network_psk(&self, network_id: usize, psk: String) -> Result {
154        let (response, request) = oneshot::channel();
155        self.send_request(Request::SetNetwork(
156            network_id,
157            SetNetwork::Psk(psk),
158            response,
159        ))
160        .await?;
161        request.await?
162    }
163
164    pub async fn set_network_ssid(&self, network_id: usize, ssid: String) -> Result {
165        let (response, request) = oneshot::channel();
166        self.send_request(Request::SetNetwork(
167            network_id,
168            SetNetwork::Ssid(ssid),
169            response,
170        ))
171        .await?;
172        request.await?
173    }
174
175    pub async fn set_network_bssid(&self, network_id: usize, bssid: String) -> Result {
176        let (response, request) = oneshot::channel();
177        self.send_request(Request::SetNetwork(
178            network_id,
179            SetNetwork::Bssid(bssid),
180            response,
181        ))
182        .await?;
183        request.await?
184    }
185
186    pub async fn set_network_keymgmt(&self, network_id: usize, mgmt: KeyMgmt) -> Result {
187        let (response, request) = oneshot::channel();
188        self.send_request(Request::SetNetwork(
189            network_id,
190            SetNetwork::KeyMgmt(mgmt),
191            response,
192        ))
193        .await?;
194        request.await?
195    }
196
197    pub async fn save_config(&self) -> Result {
198        let (response, request) = oneshot::channel();
199        self.send_request(Request::SaveConfig(response)).await?;
200        request.await?
201    }
202
203    pub async fn remove_network(&self, network_id: usize) -> Result {
204        let (response, request) = oneshot::channel();
205        self.send_request(Request::RemoveNetwork(network_id, response))
206            .await?;
207        request.await?
208    }
209
210    pub async fn remove_all_networks(&self) -> Result {
211        let (response, request) = oneshot::channel();
212        self.send_request(Request::RemoveAllNetworks(response))
213            .await?;
214        request.await?
215    }
216
217    pub async fn select_network(&self, network_id: usize) -> Result<SelectResult> {
218        let (response, request) = oneshot::channel();
219        self.send_request(Request::SelectNetwork(network_id, response))
220            .await?;
221        request.await?
222    }
223
224    pub async fn shutdown(&self) -> Result {
225        self.send_request(Request::Shutdown).await?;
226        Ok(())
227    }
228}
229
230/// Broadcast events are unexpected, such as losing connection to the host network.
231#[derive(Debug, Clone)]
232pub enum Broadcast {
233    Connected,
234    Disconnected,
235    NetworkNotFound,
236    WrongPsk,
237    Ready,
238    Unknown(String),
239}
240
241/// Channel for broadcasting events. Subscribing to this channel is equivalent to
242/// "wpa_ctrl_attach". Can be temporarily silenced using broadcast::Receiver's unsubscribe
243pub type BroadcastReceiver = broadcast::Receiver<Broadcast>;