wifi_ctrl/ap/
mod.rs

1use super::*;
2
3mod types;
4pub use types::*;
5
6mod client;
7pub use client::*;
8
9mod setup;
10pub use setup::*;
11
12mod event_socket;
13use event_socket::*;
14
15const PATH_DEFAULT_SERVER: &str = "/var/run/hostapd/wlan1";
16
17/// Instance that runs the Wifi process
18pub struct WifiAp {
19    /// Path to the socket
20    socket_path: std::path::PathBuf,
21    /// Options to pass to the hostapd attach command
22    attach_options: Vec<String>,
23    /// Channel for receiving requests
24    request_receiver: mpsc::Receiver<Request>,
25    #[allow(unused)]
26    /// Channel for broadcasting alerts
27    broadcast_sender: broadcast::Sender<Broadcast>,
28    /// Channel for sending requests to itself
29    self_sender: mpsc::Sender<Request>,
30}
31
32impl WifiAp {
33    pub async fn run(mut self) -> Result {
34        info!("Starting Wifi AP process");
35        let (event_receiver, mut deferred_requests, event_socket) = EventSocket::new(
36            &self.socket_path,
37            &mut self.request_receiver,
38            &self.attach_options,
39        )
40        .await?;
41        // We start up a separate socket for receiving the "unexpected" events that
42        // gets forwarded to us via the event_receiver
43        let (socket_handle, next_deferred_requests) = SocketHandle::open(
44            &self.socket_path,
45            "mapper_hostapd_sync.sock",
46            &mut self.request_receiver,
47        )
48        .await?;
49        deferred_requests.extend(next_deferred_requests);
50        for request in deferred_requests {
51            let _ = self.self_sender.send(request).await;
52        }
53        self.broadcast_sender.send(Broadcast::Ready)?;
54        tokio::select!(
55            resp = event_socket.run() => resp,
56            resp = self.run_internal(event_receiver, socket_handle) => resp,
57        )
58    }
59
60    async fn run_internal(
61        mut self,
62        mut event_receiver: EventReceiver,
63        mut socket_handle: SocketHandle<2048>,
64    ) -> Result {
65        enum EventOrRequest {
66            Event(Option<Event>),
67            Request(Option<Request>),
68        }
69
70        loop {
71            let event_or_request = tokio::select!(
72                event = event_receiver.recv() => EventOrRequest::Event(event),
73                request = self.request_receiver.recv() => EventOrRequest::Request(request),
74            );
75            match event_or_request {
76                EventOrRequest::Event(event) => match event {
77                    Some(event) => {
78                        Self::handle_event(&mut socket_handle, &self.broadcast_sender, event)
79                            .await?
80                    }
81                    None => return Err(error::Error::WifiApEventChannelClosed),
82                },
83                EventOrRequest::Request(request) => match request {
84                    Some(Request::Shutdown) => return Ok(()),
85                    Some(request) => Self::handle_request(&mut socket_handle, request).await?,
86                    None => return Err(error::Error::WifiApRequestChannelClosed),
87                },
88            }
89        }
90    }
91
92    async fn handle_event<const N: usize>(
93        _socket_handle: &mut SocketHandle<N>,
94        broadcast_sender: &broadcast::Sender<Broadcast>,
95        event_msg: Event,
96    ) -> Result {
97        match event_msg {
98            Event::ApStaConnected(mac) => {
99                if let Err(e) = broadcast_sender.send(Broadcast::Connected(mac)) {
100                    warn!("error broadcasting: {e}");
101                }
102            }
103            Event::ApStaDisconnected(mac) => {
104                if let Err(e) = broadcast_sender.send(Broadcast::Disconnected(mac)) {
105                    warn!("error broadcasting: {e}");
106                }
107            }
108            Event::Unknown(msg) => {
109                if let Err(e) = broadcast_sender.send(Broadcast::UnknownEvent(msg)) {
110                    warn!("error broadcasting: {e}");
111                }
112            }
113        };
114        Ok(())
115    }
116
117    async fn handle_request<const N: usize>(
118        socket_handle: &mut SocketHandle<N>,
119        request: Request,
120    ) -> Result {
121        debug!("Handling request: {request:?}");
122        match request {
123            Request::Custom(custom, response_channel) => {
124                let _n = socket_handle.socket.send(custom.as_bytes()).await?;
125                let n = socket_handle.socket.recv(&mut socket_handle.buffer).await?;
126                let data_str = std::str::from_utf8(&socket_handle.buffer[..n])?.trim_end();
127                debug!("Custom request response: {data_str}");
128                if response_channel.send(Ok(data_str.into())).is_err() {
129                    error!("Custom request response channel closed before response sent");
130                }
131            }
132            Request::Status(response_channel) => {
133                let _n = socket_handle.socket.send(b"STATUS").await?;
134                let n = socket_handle.socket.recv(&mut socket_handle.buffer).await?;
135                let data_str = std::str::from_utf8(&socket_handle.buffer[..n])?.trim_end();
136                let status = Status::from_response(data_str)?;
137
138                if response_channel.send(Ok(status)).is_err() {
139                    error!("Status request response channel closed before response sent");
140                }
141            }
142            Request::Config(response_channel) => {
143                let _n = socket_handle.socket.send(b"GET_CONFIG").await?;
144                let n = socket_handle.socket.recv(&mut socket_handle.buffer).await?;
145                let data_str = std::str::from_utf8(&socket_handle.buffer[..n])?.trim_end();
146                let config = Config::from_response(data_str)?;
147
148                if response_channel.send(Ok(config)).is_err() {
149                    error!("Config request response channel closed before response sent");
150                }
151            }
152            Request::Enable(response_channel) => {
153                Self::ok_fail_request(socket_handle, b"ENABLE", response_channel).await?
154            }
155            Request::Disable(response_channel) => {
156                Self::ok_fail_request(socket_handle, b"DISABLE", response_channel).await?
157            }
158            Request::SetValue(key, value, response_channel) => {
159                let request_string = format!("SET {key} {value}");
160                Self::ok_fail_request(socket_handle, request_string.as_bytes(), response_channel)
161                    .await?
162            }
163            Request::Shutdown => (), //shutdown is handled at the scope above
164        }
165        Ok(())
166    }
167
168    async fn ok_fail_request<const N: usize>(
169        socket_handle: &mut SocketHandle<N>,
170        request: &[u8],
171        response_channel: oneshot::Sender<Result>,
172    ) -> Result {
173        let _n = socket_handle.socket.send(request).await?;
174        let n = socket_handle.socket.recv(&mut socket_handle.buffer).await?;
175        let data_str = std::str::from_utf8(&socket_handle.buffer[..n])?.trim_end();
176        let response = if data_str == "OK" {
177            Ok(())
178        } else {
179            Err(error::Error::UnexpectedWifiApRepsonse(data_str.into()))
180        };
181
182        if response_channel.send(response).is_err() {
183            error!("Config request response channel closed before response sent");
184        }
185        Ok(())
186    }
187}