use crate::unix_bsd::bind::*;
use crate::unix_bsd::{
add_or_del_route_req, create_route_socket, deserialize_res, deserialize_res_change,
list_routes, m_rtmsg,
};
use crate::Route;
use crate::{AsyncRoute, RouteChange};
use std::collections::VecDeque;
use std::io;
use std::io::{Read, Write};
use std::os::unix::net::UnixStream;
pub struct AsyncRouteListener {
list: VecDeque<RouteChange>,
route_socket: AsyncRoute<UnixStream>,
}
impl AsyncRouteListener {
pub fn new() -> io::Result<Self> {
let route_socket = create_route_socket()?;
let route_socket = AsyncRoute::new(route_socket)?;
Ok(AsyncRouteListener {
list: Default::default(),
route_socket,
})
}
pub async fn listen(&mut self) -> io::Result<RouteChange> {
if let Some(route) = self.list.pop_front() {
return Ok(route);
}
let mut buf = [0u8; 2048];
let route_socket = &mut self.route_socket;
loop {
let read = route_socket.read_with(|s| s.read(&mut buf)).await?;
deserialize_res_change(
|route| {
self.list.push_back(route);
},
&buf[..read],
)?;
if let Some(route) = self.list.pop_front() {
return Ok(route);
}
}
}
}
pub struct AsyncRouteManager {
_private: std::marker::PhantomData<()>,
}
impl AsyncRouteManager {
pub fn new() -> io::Result<AsyncRouteManager> {
Ok(AsyncRouteManager {
_private: std::marker::PhantomData,
})
}
pub fn listener() -> io::Result<AsyncRouteListener> {
AsyncRouteListener::new()
}
pub async fn list(&mut self) -> io::Result<Vec<Route>> {
list_routes()
}
pub async fn add(&mut self, route: &Route) -> io::Result<()> {
add_route(route).await
}
pub async fn delete(&mut self, route: &Route) -> io::Result<()> {
delete_route(route).await
}
}
async fn add_route(route: &Route) -> io::Result<()> {
add_or_del_route(route, RTM_ADD as u8).await
}
async fn delete_route(route: &Route) -> io::Result<()> {
add_or_del_route(route, RTM_DELETE as u8).await
}
async fn add_or_del_route(route: &Route, rtm_type: u8) -> io::Result<()> {
let rtmsg = add_or_del_route_req(route, rtm_type)?;
let route_socket = create_route_socket()?;
let mut route_socket = AsyncRoute::new(route_socket)?;
route_socket
.write_with(|s| s.write_all(rtmsg.slice()))
.await?;
let mut buf = [0u8; std::mem::size_of::<m_rtmsg>()];
let len = route_socket.read_with(|s| s.read(&mut buf)).await?;
deserialize_res(|_, _| {}, &buf[..len])?;
Ok(())
}