Skip to main content

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    AlreadyConnected,
16}
17
18use std::fmt;
19
20impl fmt::Display for SelectResult {
21    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22        let s = match self {
23            SelectResult::Success => "success",
24            SelectResult::WrongPsk => "wrong_psk",
25            SelectResult::NotFound => "network_not_found",
26            SelectResult::AlreadyConnected => "already_connected",
27        };
28        write!(f, "{s}")
29    }
30}
31
32#[derive(Debug)]
33pub(crate) enum RemoveNetwork {
34    Id(usize),
35    All,
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    ReloadConfig(oneshot::Sender<Result>),
48    RemoveNetwork(RemoveNetwork, oneshot::Sender<Result>),
49    SelectNetwork(usize, oneshot::Sender<Result<SelectResult>>),
50    Shutdown,
51}
52
53impl ShutdownSignal for Request {
54    fn is_shutdown(&self) -> bool {
55        matches!(self, Request::Shutdown)
56    }
57}
58
59#[derive(Debug)]
60pub(crate) enum SetNetwork {
61    Ssid(String),
62    Bssid(Bssid),
63    Psk(Psk),
64    KeyMgmt(KeyMgmt),
65}
66
67#[derive(Clone)]
68/// Request client wraps the request events, awaiting oneshot channels when appropriate
69pub struct RequestClient {
70    sender: mpsc::Sender<Request>,
71}
72
73impl RequestClient {
74    pub(crate) fn new(sender: mpsc::Sender<Request>) -> RequestClient {
75        RequestClient { sender }
76    }
77
78    async fn request<T>(
79        &self,
80        build_request: impl FnOnce(oneshot::Sender<Result<T>>) -> Request,
81    ) -> Result<T> {
82        let (response, request) = oneshot::channel();
83        self.sender.send(build_request(response)).await?;
84        request.await?
85    }
86
87    pub async fn send_custom(&self, custom: String) -> Result<String> {
88        self.request(|response| Request::Custom(custom, response))
89            .await
90    }
91
92    pub async fn get_scan(&self) -> Result<Arc<Vec<ScanResult>>> {
93        self.request(Request::Scan).await
94    }
95
96    pub async fn get_networks(&self) -> Result<Vec<NetworkResult>> {
97        self.request(Request::Networks).await
98    }
99
100    pub async fn get_status(&self) -> Result<Status> {
101        self.request(Request::Status).await
102    }
103
104    pub async fn add_network(&self) -> Result<usize> {
105        self.request(Request::AddNetwork).await
106    }
107
108    /// Set the network's pre-shared key. See [`Psk`] for the accepted forms.
109    pub async fn set_network_psk(&self, network_id: usize, psk: Psk) -> Result {
110        self.request(|response| Request::SetNetwork(network_id, SetNetwork::Psk(psk), response))
111            .await
112    }
113
114    pub async fn set_network_ssid(&self, network_id: usize, ssid: String) -> Result {
115        self.request(|response| Request::SetNetwork(network_id, SetNetwork::Ssid(ssid), response))
116            .await
117    }
118
119    /// Pin the network to a specific access point by [`Bssid`].
120    pub async fn set_network_bssid(&self, network_id: usize, bssid: Bssid) -> Result {
121        self.request(|response| Request::SetNetwork(network_id, SetNetwork::Bssid(bssid), response))
122            .await
123    }
124
125    /// Set the network's key management mode; see [`KeyMgmt`].
126    pub async fn set_network_keymgmt(&self, network_id: usize, mgmt: KeyMgmt) -> Result {
127        self.request(|response| {
128            Request::SetNetwork(network_id, SetNetwork::KeyMgmt(mgmt), response)
129        })
130        .await
131    }
132
133    pub async fn save_config(&self) -> Result {
134        self.request(Request::SaveConfig).await
135    }
136
137    pub async fn reload_config(&self) -> Result {
138        self.request(Request::ReloadConfig).await
139    }
140
141    pub async fn remove_network(&self, id: usize) -> Result {
142        self.request(|response| Request::RemoveNetwork(RemoveNetwork::Id(id), response))
143            .await
144    }
145
146    pub async fn remove_all_networks(&self) -> Result {
147        self.request(|response| Request::RemoveNetwork(RemoveNetwork::All, response))
148            .await
149    }
150
151    pub async fn select_network(&self, network_id: usize) -> Result<SelectResult> {
152        self.request(|response| Request::SelectNetwork(network_id, response))
153            .await
154    }
155
156    pub async fn shutdown(&self) -> Result {
157        self.sender.send(Request::Shutdown).await?;
158        Ok(())
159    }
160}
161
162/// Broadcast events are unexpected, such as losing connection to the host network.
163#[derive(Debug, Clone)]
164pub enum Broadcast {
165    Connected,
166    Disconnected,
167    NetworkNotFound,
168    WrongPsk,
169    Ready,
170    Unknown(String),
171}
172
173/// Channel for broadcasting events. Subscribing to this channel is equivalent to
174/// "wpa_ctrl_attach". Can be temporarily silenced using broadcast::Receiver's unsubscribe
175pub type BroadcastReceiver = broadcast::Receiver<Broadcast>;