pub use crate::packet::*;
use crate::raw::*;
use crate::*;
use ipnet::{AddrParseError, IpNet};
use smol::Task;
use std::convert::TryInto;
use std::fs::File;
use std::io::{Error, Read, Write};
use async_std::prelude::*;
use std::thread::{JoinHandle, Thread};
pub struct Systun {
raw: RawTun,
mtu: u32,
}
pub struct Reader {
read_loop: JoinHandle<()>,
raw: channel::Reader<Result<Packet>>,
closer: channel::Closer<()>,
}
impl Reader {
fn new(closer: channel::Closer<()>, mut fd: File, mtu: usize) -> Reader {
let (s, r) = channel::unbound();
let read_loop = std::thread::spawn(move || loop {
match Self::handle_read(&mut fd, mtu) {
Ok(pkt) => match smol::block_on(s.write(Ok(pkt))) {
true => {}
false => break,
},
Err(err) => {
smol::block_on(s.write(Err(err)));
break;
}
};
});
Reader {
read_loop,
raw: r,
closer,
}
}
fn handle_read(fd: &mut File, mtu: usize) -> Result<Packet> {
let mut buf = Vec::with_capacity(mtu as _);
unsafe { buf.set_len(buf.capacity()) };
let size = fd.read(&mut buf).context(ReadError)?;
Ok(Packet::new(&buf[0..size]))
}
pub async fn read(&self) -> Option<Packet> {
match self.raw.read().await {
Some(result) => match result {
Ok(pkt) => Some(pkt),
Err(err) => {
eprintln!("error read from tun: {}", err);
None
}
},
None => None,
}
}
pub async fn read_safe(&self) -> Option<Result<Packet>> {
self.raw.read().await
}
pub fn closer(&self) -> channel::Closer<Result<Packet>> {
self.raw.closer()
}
pub async fn close(self) {
self.closer.close().await
}
}
use std::sync::Arc;
#[derive(Clone)]
pub struct Writer {
raw: channel::Writer<Packet>,
write_loop: Arc<JoinHandle<()>>,
closer: channel::Closer<()>,
}
impl Writer {
fn new(closer: channel::Closer<()>, mut fd: File) -> Writer {
let (s, r) = channel::unbound::<Packet>();
let write_loop = std::thread::spawn(move || {
let mut n = 0;
loop {
let pkt = match smol::block_on(r.read()) {
Some(pkt) => pkt,
None => {
break;
}
};
let out = pkt.out();
if let Err(write_err) = fd.write(&out) {
eprintln!("write to tun fail: {:?}", write_err);
break;
}
n += 1;
if n > 10 {
println!("exit");
break;
}
}
});
Writer {
raw: s,
write_loop: Arc::new(write_loop),
closer,
}
}
pub async fn write(&self, pkt: Packet) -> bool {
self.raw.write(pkt).await
}
fn closer(&self) -> channel::Closer<Packet> {
self.raw.closer()
}
pub async fn close(self) {
self.closer.close().await
}
}
#[derive(Clone)]
pub struct Closer {
raw: channel::Writer<()>,
}
impl Closer {
pub fn new(raw: channel::Writer<()>) -> Closer {
Closer { raw }
}
pub async fn close(self) {
self.raw.close().await
}
}
pub struct Config {}
impl Systun {
pub async fn from_ipnet(ipnet: &IpNet) -> Result<Systun> {
let raw = RawTun::new().await?;
let mtu: u32 = 1500;
let ipnet = ipnet.trunc();
raw.init(&ipnet, mtu)?;
Ok(Systun { raw, mtu })
}
pub async fn new<Addr: AsRef<str>>(addr: Addr) -> Result<Systun> {
let ipnet = addr.as_ref().parse::<IpNet>().context(ParseAddrFail)?;
Self::from_ipnet(&ipnet).await
}
pub fn split(mut self) -> (Reader, Writer) {
let raw = &mut self.raw;
let (close_writer, close_reader) = channel::closer();
let raw_reader = raw.take_reader().unwrap();
let reader = Reader::new(close_writer.clone(), raw_reader, self.mtu as _);
let raw_writer = raw.take_writer().unwrap();
let writer = Writer::new(close_writer, raw_writer);
let reader_closer = reader.closer();
let writer_closer = writer.closer();
Task::spawn(async move {
close_reader.read().await;
reader_closer.close().await;
writer_closer.close().await;
})
.detach();
(reader, writer)
}
}