Skip to main content

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    /// Channel for broadcasting alerts
26    broadcast_sender: broadcast::Sender<Broadcast>,
27    /// Channel for sending requests to itself
28    self_sender: mpsc::Sender<Request>,
29    /// How long to wait for a reply to a control command/request
30    command_timeout: std::time::Duration,
31    /// How many times to retry the ATTACH/LOG_LEVEL handshake before giving up
32    attach_retries: usize,
33    /// How long to wait between attach handshake attempts
34    attach_retry_delay: std::time::Duration,
35}
36
37impl WifiAp {
38    pub async fn run(&mut self) -> SocketResult {
39        info!("Starting Wifi AP process");
40        let (mut deferred_requests, event_socket) = EventSocket::new(
41            &self.socket_path,
42            &mut self.request_receiver,
43            &self.attach_options,
44            self.command_timeout,
45            self.attach_retries,
46            self.attach_retry_delay,
47        )
48        .await?;
49        // We start up a separate socket for receiving the "unexpected" events that
50        // gets forwarded to us via the event_receiver
51        let (socket_handle, next_deferred_requests) = SocketHandle::open(
52            &self.socket_path,
53            "mapper_hostapd_sync.sock",
54            &mut self.request_receiver,
55            self.command_timeout,
56        )
57        .await?;
58        deferred_requests.extend(next_deferred_requests);
59        for request in deferred_requests {
60            self.self_sender
61                .send(request)
62                .await
63                .expect("self_sender should never close as same struct owns both ends");
64        }
65        self.broadcast(Broadcast::Ready);
66        self.run_internal(event_socket, socket_handle).await
67    }
68
69    fn broadcast(&self, event: Broadcast) {
70        if self.broadcast_sender.send(event).is_err() {
71            debug!("broadcast listener closed")
72        }
73    }
74
75    async fn run_internal(
76        &mut self,
77        mut event_socket: EventSocket,
78        mut socket_handle: SocketHandle<2048>,
79    ) -> SocketResult {
80        enum EventOrRequest {
81            Event(Event),
82            Request(Option<Request>),
83        }
84
85        loop {
86            let event_or_request = tokio::select!(
87                event = event_socket.recv() => EventOrRequest::Event(event?),
88                request = self.request_receiver.recv() => EventOrRequest::Request(request),
89            );
90            match event_or_request {
91                EventOrRequest::Event(event) => self.handle_event(event),
92                EventOrRequest::Request(request) => match request {
93                    Some(Request::Shutdown) => return Ok(()),
94                    Some(request) => Self::handle_request(&mut socket_handle, request).await?,
95                    None => return Err(error::SocketError::ClientChannelClosed),
96                },
97            }
98        }
99    }
100
101    fn handle_event(&self, event_msg: Event) {
102        match event_msg {
103            Event::ApStaConnected(mac) => self.broadcast(Broadcast::Connected(mac)),
104            Event::ApStaDisconnected(mac) => self.broadcast(Broadcast::Disconnected(mac)),
105            Event::Unknown(msg) => self.broadcast(Broadcast::UnknownEvent(msg)),
106        };
107    }
108
109    async fn handle_request<const N: usize>(
110        socket_handle: &mut SocketHandle<N>,
111        request: Request,
112    ) -> SocketResult {
113        // A SetValue value may be a secret (e.g. wpa_passphrase), so keep it out
114        // of the log; the key is a config field name and safe to show.
115        match &request {
116            Request::SetValue(key, _, _) => {
117                debug!("Handling request: SetValue({key:?}, <redacted>)")
118            }
119            _ => debug!("Handling request: {request:?}"),
120        }
121        match request {
122            Request::Custom(custom, response_channel) => {
123                let data_str = socket_handle.request(&custom, TryInto::try_into).await?;
124                debug!("Custom request response: {data_str:?}");
125                let _ = response_channel.send(data_str);
126            }
127            Request::Status(response_channel) => {
128                let status = socket_handle
129                    .request("STATUS", Status::from_response)
130                    .await?;
131
132                let _ = response_channel.send(status);
133            }
134            Request::Config(response_channel) => {
135                let config = socket_handle
136                    .request("GET_CONFIG", Config::from_response)
137                    .await?;
138                let _ = response_channel.send(config);
139            }
140            Request::Enable(response_channel) => {
141                let _ = response_channel.send(socket_handle.command(b"ENABLE").await?);
142            }
143            Request::Disable(response_channel) => {
144                let _ = response_channel.send(socket_handle.command(b"DISABLE").await?);
145            }
146            Request::SetValue(key, value, response_channel) => {
147                let request_string = format!("SET {key} {value}");
148                let _ =
149                    response_channel.send(socket_handle.command(request_string.as_bytes()).await?);
150            }
151            Request::Shutdown => (), //shutdown is handled at the scope above
152        }
153        Ok(())
154    }
155}