Skip to content

Commit

Permalink
WifiAp example program and allow attach options (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
lthiery authored Oct 25, 2023
1 parent f2388b2 commit a0272d7
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 10 deletions.
65 changes: 65 additions & 0 deletions examples/wifi-ap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#![allow(clippy::result_large_err)]
use env_logger::Env;
use log::{error, info};
use network_interface::{NetworkInterface, NetworkInterfaceConfig};
use tokio::io;
use wifi_ctrl::{ap, Result};

#[tokio::main]
async fn main() -> Result {
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
info!("Starting wifi-ap example");

let mut network_interfaces = NetworkInterface::show().unwrap();
network_interfaces.sort_by(|a, b| a.index.cmp(&b.index));
for (i, itf) in network_interfaces.iter().enumerate() {
info!("[{:?}] {:?}", i, itf.name);
}
let user_input = read_until_break().await;
let index = user_input.trim().parse::<usize>()?;
let mut setup = ap::WifiSetup::new()?;

let proposed_path = format!("/var/run/hostapd/{}", network_interfaces[index].name);
info!("Connect to \"{proposed_path}\"? Type full new path or just press enter to accept.");

let user_input = read_until_break().await;
if user_input.trim().is_empty() {
setup.set_socket_path(proposed_path);
} else {
setup.set_socket_path(user_input.trim().to_string());
}

let broadcast = setup.get_broadcast_receiver();
let requester = setup.get_request_client();
let runtime = setup.complete();

let (_runtime, _app, _broadcast) = tokio::join!(
async move {
if let Err(e) = runtime.run().await {
error!("Error: {e}");
}
},
app(requester),
broadcast_listener(broadcast),
);
Ok(())
}

async fn app(_: ap::RequestClient) -> Result {
Ok(())
}

async fn broadcast_listener(mut broadcast_receiver: ap::BroadcastReceiver) -> Result {
while let Ok(broadcast) = broadcast_receiver.recv().await {
info!("Broadcast: {:?}", broadcast);
}
Ok(())
}

async fn read_until_break() -> String {
use futures::stream::StreamExt;
use tokio_util::codec::{FramedRead, LinesCodec};
let stdin = io::stdin();
let mut reader = FramedRead::new(stdin, LinesCodec::new());
reader.next().await.unwrap().unwrap()
}
3 changes: 2 additions & 1 deletion examples/wifi-sta.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(clippy::result_large_err)]
use env_logger::Env;
use log::{error, info};
use network_interface::{NetworkInterface, NetworkInterfaceConfig};
Expand All @@ -22,7 +23,7 @@ async fn main() -> Result {
info!("Connect to \"{proposed_path}\"? Type full new path or just press enter to accept.");

let user_input = read_until_break().await;
if user_input.trim().len() == 0 {
if user_input.trim().is_empty() {
setup.set_socket_path(proposed_path);
} else {
setup.set_socket_path(user_input.trim().to_string());
Expand Down
1 change: 1 addition & 0 deletions src/ap/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub enum Broadcast {
Ready,
Connected(String),
Disconnected(String),
UnknownEvent(String),
}

/// Channel for broadcasting events.
Expand Down
19 changes: 15 additions & 4 deletions src/ap/event_socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::*;

pub(crate) struct EventSocket {
socket_handle: SocketHandle<256>,
attach_options: Vec<String>,
/// Sends messages to client
sender: mpsc::Sender<Event>,
}
Expand All @@ -10,6 +11,7 @@ pub(crate) struct EventSocket {
pub(crate) enum Event {
ApStaConnected(String),
ApStaDisconnected(String),
Unknown(String),
}

pub(crate) type EventReceiver = mpsc::Receiver<Event>;
Expand All @@ -18,12 +20,13 @@ impl EventSocket {
pub(crate) async fn new<P>(
socket: P,
request_receiver: &mut mpsc::Receiver<Request>,
attach_options: &[String],
) -> Result<(EventReceiver, Vec<Request>, Self)>
where
P: AsRef<std::path::Path> + std::fmt::Debug,
{
let (socket_handle, deferred_requests) =
SocketHandle::open(socket, "mapper_hostapd_async.sock", request_receiver).await?;
SocketHandle::open(socket, "hostapd_async.sock", request_receiver).await?;

// setup the channel for client requests
let (sender, receiver) = mpsc::channel(32);
Expand All @@ -33,6 +36,7 @@ impl EventSocket {
Self {
socket_handle,
sender,
attach_options: attach_options.to_vec(),
},
))
}
Expand All @@ -46,10 +50,15 @@ impl EventSocket {
}

pub(crate) async fn run(mut self) -> Result {
let mut attach = self.socket_handle.command(b"ATTACH").await;
let mut command = "ATTACH".to_string();
for o in &self.attach_options {
command.push(' ');
command.push_str(o);
}
let mut attach = self.socket_handle.command(command.as_bytes()).await;
while attach.is_err() {
tokio::time::sleep(tokio::time::Duration::from_millis(250)).await;
attach = self.socket_handle.command(b"ATTACH").await;
attach = self.socket_handle.command(command.as_bytes()).await;
}

let mut log_level = self.socket_handle.command(b"LOG_LEVEL DEBUG").await;
Expand All @@ -68,7 +77,6 @@ impl EventSocket {
{
Ok(n) => {
let data_str = std::str::from_utf8(&self.socket_handle.buffer[..n])?.trim_end();
debug!("hostapd event: {data_str}");
if let Some(n) = data_str.find("AP-STA-DISCONNECTED") {
let index = n + "AP-STA-DISCONNECTED".len();
let mac = &data_str[index..];
Expand All @@ -79,6 +87,9 @@ impl EventSocket {
let mac = &data_str[index..];
self.send_event(Event::ApStaConnected(mac.to_string()))
.await?;
} else {
self.send_event(Event::Unknown(data_str.to_string()))
.await?;
}
}
Err(e) => {
Expand Down
19 changes: 15 additions & 4 deletions src/ap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const PATH_DEFAULT_SERVER: &str = "/var/run/hostapd/wlan1";
pub struct WifiAp {
/// Path to the socket
socket_path: std::path::PathBuf,
/// Options to pass to the hostapd attach command
attach_options: Vec<String>,
/// Channel for receiving requests
request_receiver: mpsc::Receiver<Request>,
#[allow(unused)]
Expand All @@ -30,8 +32,12 @@ pub struct WifiAp {
impl WifiAp {
pub async fn run(mut self) -> Result {
info!("Starting Wifi AP process");
let (event_receiver, mut deferred_requests, event_socket) =
EventSocket::new(&self.socket_path, &mut self.request_receiver).await?;
let (event_receiver, mut deferred_requests, event_socket) = EventSocket::new(
&self.socket_path,
&mut self.request_receiver,
&self.attach_options,
)
.await?;
// We start up a separate socket for receiving the "unexpected" events that
// gets forwarded to us via the event_receiver
let (socket_handle, next_deferred_requests) = SocketHandle::open(
Expand Down Expand Up @@ -90,12 +96,17 @@ impl WifiAp {
) -> Result {
match event_msg {
Event::ApStaConnected(mac) => {
if let Err(e) = broadcast_sender.send(client::Broadcast::Connected(mac)) {
if let Err(e) = broadcast_sender.send(Broadcast::Connected(mac)) {
warn!("error broadcasting: {e}");
}
}
Event::ApStaDisconnected(mac) => {
if let Err(e) = broadcast_sender.send(client::Broadcast::Disconnected(mac)) {
if let Err(e) = broadcast_sender.send(Broadcast::Disconnected(mac)) {
warn!("error broadcasting: {e}");
}
}
Event::Unknown(msg) => {
if let Err(e) = broadcast_sender.send(Broadcast::UnknownEvent(msg)) {
warn!("error broadcasting: {e}");
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/ap/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ impl<const C: usize, const B: usize> WifiSetupGeneric<C, B> {
Ok(Self {
wifi: WifiAp {
socket_path: PATH_DEFAULT_SERVER.into(),
attach_options: vec![],
request_receiver,
broadcast_sender,
self_sender,
Expand All @@ -39,6 +40,12 @@ impl<const C: usize, const B: usize> WifiSetupGeneric<C, B> {
self.wifi.socket_path = path.into();
}

pub fn add_attach_options(&mut self, options: &[&str]) {
for o in options {
self.wifi.attach_options.push(o.to_string());
}
}

pub fn get_broadcast_receiver(&self) -> BroadcastReceiver {
self.wifi.broadcast_sender.subscribe()
}
Expand Down
2 changes: 1 addition & 1 deletion src/sta/event_socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl EventSocket {
P: AsRef<std::path::Path> + std::fmt::Debug,
{
let (socket_handle, deferred_requests) =
SocketHandle::open(socket, "mapper_wpa_ctrl_async.sock", request_receiver).await?;
SocketHandle::open(socket, "wpa_ctrl_async.sock", request_receiver).await?;
// setup the channel for client requests
let (sender, receiver) = mpsc::channel(32);
Ok((
Expand Down

0 comments on commit a0272d7

Please sign in to comment.