diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..e3b5525 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,28 @@ +name: Push or PR + +on: + [push, pull_request] + +env: + CARGO_TERM_COLOR: always + +jobs: + build_n_test: + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v3 + - name: rustfmt + run: cargo fmt --all -- --check + - name: check + run: cargo check --verbose + - name: clippy + run: cargo clippy --all-targets --all-features -- -D warnings + - name: Build + run: cargo build --verbose --examples --tests --all-features + - name: Test + run: cargo test --all-features --examples diff --git a/.gitignore b/.gitignore index f128f5e..0683989 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.vscode/ +.VSCodeCounter/ /target/ Cargo.lock .DS_Store diff --git a/Cargo.toml b/Cargo.toml index bc128f0..58e953a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,8 +9,12 @@ repository = 'https://github.com/narrowlink/ipstack' # homepage = 'https://github.com/narrowlink/ipstack' readme = "README.md" +[features] +default = [] +log = ["tracing/log"] + [dependencies] -tokio = { version = "1.33", features = [ +tokio = { version = "1.35", features = [ "sync", "rt", "time", @@ -19,16 +23,17 @@ tokio = { version = "1.33", features = [ ], default-features = false } etherparse = { version = "0.13", default-features = false } thiserror = { version = "1.0", default-features = false } -tracing = { version = "0.1.40", default-features = false } +tracing = { version = "0.1", default-features = false, features = [ + "log", +], optional = true } [dev-dependencies] -udp-stream = { version = "0.0.9", default-features = false } - -[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dev-dependencies] -tun = { version = "0.6.1", features = ["async"], default-features = false } - -[target.'cfg(target_os = "windows")'.dev-dependencies] -wintun = { version = "0.3", default-features = false } +clap = { version = "4.4", features = ["derive"] } +udp-stream = { version = "0.0", default-features = false } +tun2 = { version = "0.6", features = ["async"] } +tokio = { version = "1.35", features = [ + "rt-multi-thread", +], default-features = false } [profile.release] opt-level = 'z' # Optimize for size. diff --git a/README.md b/README.md index 0fb6ed0..fd9a620 100644 --- a/README.md +++ b/README.md @@ -6,46 +6,45 @@ Unstable, under development. use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use udp_stream::UdpStream; use tokio::io{AsyncRead, AsyncWrite}; -async fn copy_from_lhs_to_rhs(lhs:impl AsyncRead + AsyncWrite, rhs:impl AsyncRead + AsyncWrite){ - let (lhs_reader,lhs_writer) = tokio::io::split(lhs); - let (rhs_reader, rhs_writer) = tokio::io::split(rhs); - tokio::join! { - tokio::io::copy(&mut lhs_reader, &mut rhs_writer) , - tokio::io::copy(&mut rhs_reader, &mut lhs_writer), - } +async fn copy_from_lhs_to_rhs(lhs: impl AsyncRead + AsyncWrite, rhs: impl AsyncRead + AsyncWrite) { + let (mut lhs_reader, mut lhs_writer) = tokio::io::split(lhs); + let (mut rhs_reader, mut rhs_writer) = tokio::io::split(rhs); + let _r = tokio::join! { + tokio::io::copy(&mut lhs_reader, &mut rhs_writer) , + tokio::io::copy(&mut rhs_reader, &mut lhs_writer), + }; } #[tokio::main] async fn main(){ - const MTU: u16 = 1500; - let ipv4 = Ipv4Addr::new(10, 0, 0, 1); - let mut config = tun::Configuration::default(); - config - .address(ipv4) - .netmask((255, 255, 255, 0)) - .mtu(MTU as i32) - .up(); + const MTU: u16 = 1500; + let ipv4 = Ipv4Addr::new(10, 0, 0, 1); + let netmask = Ipv4Addr::new(255, 255, 255, 0); + let mut config = tun::Configuration::default(); + config.address(ipv4).netmask(netmask).mtu(MTU as i32).up(); + + let mut ipstack_config = ipstack::IpStackConfig::default(); + ipstack_config.mtu(MTU); + ipstack_config.packet_information(cfg!(unix)); + let mut ip_stack = ipstack::IpStack::new(ipstack_config, tun::create_as_async(&config).unwrap()); - let mut ipstack_config = ipstack::IpStackConfig::default(); - ipstack_config.mtu(MTU); - ipstack_config.packet_info(cfg!(target_family = "unix")); - let mut ip_stack = ipstack::IpStack::new(ipstack_config,tun::create_as_async(&config).unwrap()); - while let Ok(stream) = ip_stack.accept().await{ - match stream{ - IpStackStream::Tcp(tcp) => { - let rhs = TcpStream::connect("1.1.1.1:80").await.unwrap(); - tokio::spawn(async move { - copy_from_lhs_to_rhs(tcp,rhs).await; - }); - } - IpStackStream::Udp(udp) => { - let rhs = UdpStream::connect(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)), 53)).await.unwrap(); - tokio::spawn(async move { - copy_from_lhs_to_rhs(udp,rhs).await; - }); - } - } - } + while let Ok(stream) = ip_stack.accept().await { + match stream { + IpStackStream::Tcp(tcp) => { + let rhs = TcpStream::connect("1.1.1.1:80").await.unwrap(); + tokio::spawn(async move { + copy_from_lhs_to_rhs(tcp, rhs).await; + }); + } + IpStackStream::Udp(udp) => { + let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)), 53); + let rhs = UdpStream::connect(addr).await.unwrap(); + tokio::spawn(async move { + copy_from_lhs_to_rhs(udp, rhs).await; + }); + } + } + } } ```` -We also suggest that you take a look at the complete [examples](https://github.com/narrowlink/ipstack/tree/main/examples). +We also suggest that you take a look at the complete [examples](examples). \ No newline at end of file diff --git a/examples/echo.rs b/examples/echo.rs new file mode 100644 index 0000000..d1ece4d --- /dev/null +++ b/examples/echo.rs @@ -0,0 +1,76 @@ +// +// tokio = { version = "1.33", features = ["full"] } +// +use std::{env, error::Error, io}; +use tokio::{ + io::{AsyncReadExt, AsyncWriteExt}, + net::{TcpListener, UdpSocket}, +}; + +const TCP_TIMEOUT: u64 = 10 * 1000; // 10sec + +async fn tcp_main(addr: &str) -> io::Result<()> { + let listener = TcpListener::bind(addr).await?; + println!("[TCP] listening on: {}", addr); + loop { + let (mut socket, peer) = listener.accept().await?; + tokio::spawn(async move { + let block = async move { + let mut buf = vec![0; 1024]; + println!("[TCP] incoming peer {}", peer); + loop { + let duration = std::time::Duration::from_millis(TCP_TIMEOUT); + let n = tokio::time::timeout(duration, socket.read(&mut buf)).await??; + if n == 0 { + println!("[TCP] {} exit", peer); + break; + } + let amt = socket.write(&buf[0..n]).await?; + println!("[TCP] Echoed {}/{} bytes to {}", amt, n, peer); + } + Ok::<(), io::Error>(()) + }; + if let Err(err) = block.await { + println!("[TCP] {}", err); + } + }); + } +} + +async fn udp_main(addr: &str) -> io::Result<()> { + let socket = UdpSocket::bind(&addr).await?; + println!("[UDP] Listening on: {}", socket.local_addr()?); + + let mut buf = vec![0; 1024]; + let mut to_send = None; + + loop { + if let Some((size, peer)) = to_send { + let amt = socket.send_to(&buf[..size], &peer).await?; + println!("[UDP] Echoed {}/{} bytes to {}", amt, size, peer); + } + + to_send = Some(socket.recv_from(&mut buf).await?); + } +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string()); + + let addr1 = addr.clone(); + let tcp = tokio::spawn(async move { + tcp_main(&addr1).await?; + Ok::<(), io::Error>(()) + }); + + let udp = tokio::spawn(async move { + udp_main(&addr).await?; + Ok::<(), io::Error>(()) + }); + + tcp.await??; + udp.await??; + + Ok(()) +} diff --git a/examples/tun.rs b/examples/tun.rs index 59c9969..2af5e20 100644 --- a/examples/tun.rs +++ b/examples/tun.rs @@ -1,73 +1,111 @@ -use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +//! +//! Build: `cargo build --examples` +//! +//! Usage: +//! +//! This example must be run as root or administrator privileges. +//! ``` +//! sudo target/debug/examples/tun --server-addr 127.0.0.1:8080 # Linux or macOS +//! ``` +//! Then please run the `echo` example server, which listens on TCP & UDP ports 127.0.0.1:8080. +//! ``` +//! target/debug/examples/echo 127.0.0.1:8080 +//! ``` +//! To route traffic to the tun interface, run the following command with root or administrator privileges: +//! ``` +//! sudo ip route add 1.2.3.4/32 dev utun3 # Linux +//! route add 1.2.3.4 mask 255.255.255.255 10.0.0.1 metric 100 # Windows +//! sudo route add 1.2.3.4/32 10.0.0.1 # Apple macOS +//! ``` +//! Now you can test it with `nc 1.2.3.4 any_port` or `nc -u 1.2.3.4 any_port`. +//! You can watch the echo information in the `nc` console. +//! ``` +//! nc 1.2.3.4 2323 # TCP +//! nc -u 1.2.3.4 2323 # UDP +//! ``` +//! +use clap::Parser; use ipstack::stream::IpStackStream; +use std::net::{Ipv4Addr, SocketAddr}; use tokio::{join, net::TcpStream}; use udp_stream::UdpStream; // const MTU: u16 = 1500; const MTU: u16 = u16::MAX; -#[tokio::main(flavor = "current_thread")] -async fn main() { - let ipv4 = Ipv4Addr::new(10, 0, 0, 1); +#[derive(Parser)] +#[command(author, version, about = "Testing app for tun.", long_about = None)] +struct Args { + /// echo server address, likes `127.0.0.1:8080` + #[arg(short, long, value_name = "IP:port")] + server_addr: SocketAddr, +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + let args = Args::parse(); + + let ipv4 = Ipv4Addr::new(10, 0, 0, 33); + let netmask = Ipv4Addr::new(255, 255, 255, 0); + let gateway = Ipv4Addr::new(10, 0, 0, 1); - let mut config = tun::Configuration::default(); - config - .address(ipv4) - .netmask((255, 255, 255, 0)) - .mtu(MTU as i32) - .up(); + let mut config = tun2::Configuration::default(); + config.address(ipv4).netmask(netmask).mtu(MTU as i32).up(); + config.destination(gateway).name("utun3"); #[cfg(target_os = "linux")] config.platform(|config| { config.packet_information(true); }); + #[cfg(target_os = "windows")] + config.platform(|config| { + config.initialize(Some(12324323423423434234_u128)); + }); + let mut ipstack_config = ipstack::IpStackConfig::default(); ipstack_config.mtu(MTU); - ipstack_config.packet_info(cfg!(target_family = "unix")); + ipstack_config.packet_information(cfg!(unix)); - let mut ip_stack = - ipstack::IpStack::new(ipstack_config, tun::create_as_async(&config).unwrap()); + let mut ip_stack = ipstack::IpStack::new(ipstack_config, tun2::create_as_async(&config)?); - #[cfg(target_os = "macos")] - { - let s = format!("sudo route -n add -net 10.0.0.0/24 {}", ipv4); - let command = std::process::Command::new("sh") - .arg("-c") - .arg(s) - .output() - .unwrap(); - if !command.status.success() { - panic!("cannot establish route to tun device"); - } - }; + let server_addr = args.server_addr; loop { - match ip_stack.accept().await.unwrap() { + match ip_stack.accept().await? { IpStackStream::Tcp(tcp) => { - let s = TcpStream::connect("1.1.1.1:80").await.unwrap(); + let s = TcpStream::connect(server_addr).await; + if let Err(ref err) = s { + println!("connect TCP server failed \"{}\"", err); + continue; + } + println!("==== New TCP connection ===="); let (mut t_rx, mut t_tx) = tokio::io::split(tcp); - let (mut s_rx, mut s_tx) = tokio::io::split(s); + let (mut s_rx, mut s_tx) = tokio::io::split(s?); tokio::spawn(async move { - join! { + let _r = join! { tokio::io::copy(&mut t_rx, &mut s_tx) , tokio::io::copy(&mut s_rx, &mut t_tx), - } + }; + println!("====== end tcp connection ======"); }); } IpStackStream::Udp(udp) => { - let s = - UdpStream::connect(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)), 53)) - .await - .unwrap(); + let s = UdpStream::connect(server_addr).await; + if let Err(ref err) = s { + println!("connect UDP server failed \"{}\"", err); + continue; + } + println!("==== New UDP connection ===="); let (mut t_rx, mut t_tx) = tokio::io::split(udp); - let (mut s_rx, mut s_tx) = tokio::io::split(s); + let (mut s_rx, mut s_tx) = tokio::io::split(s?); tokio::spawn(async move { - join! { + let _r = join! { tokio::io::copy(&mut t_rx, &mut s_tx) , tokio::io::copy(&mut s_rx, &mut t_tx), - } + }; + println!("==== end UDP connection ===="); }); } }; diff --git a/examples/wintun.rs b/examples/wintun.rs deleted file mode 100644 index ae0bc54..0000000 --- a/examples/wintun.rs +++ /dev/null @@ -1,151 +0,0 @@ -use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - -use ipstack::stream::IpStackStream; -use tokio::{join, net::TcpStream}; -use udp_stream::UdpStream; - -// const MTU: u16 = 1500; -const MTU: u16 = u16::MAX; - -#[tokio::main(flavor = "current_thread")] -async fn main() { - let ipv4 = Ipv4Addr::new(10, 0, 0, 1); - #[cfg(not(target_os = "windows"))] - let mut config = tun::Configuration::default(); - #[cfg(not(target_os = "windows"))] - config - .address(ipv4) - .netmask((255, 255, 255, 0)) - .mtu(MTU as i32) - .up(); - - #[cfg(target_os = "linux")] - config.platform(|config| { - config.packet_information(true); - }); - - let mut ipstack_config = ipstack::IpStackConfig::default(); - ipstack_config.mtu(MTU); - ipstack_config.packet_info(cfg!(target_family = "unix")); - - #[cfg(not(target_os = "windows"))] - let mut ip_stack = - ipstack::IpStack::new(ipstack_config, tun::create_as_async(&config).unwrap()); - - #[cfg(target_os = "windows")] - let mut ip_stack = ipstack::IpStack::new( - ipstack_config, - wintun::WinTunDevice::new(ipv4, Ipv4Addr::new(255, 255, 255, 0)), - ); - - loop { - match ip_stack.accept().await.unwrap() { - IpStackStream::Tcp(tcp) => { - let s = TcpStream::connect("1.1.1.1:80").await.unwrap(); - let (mut t_rx, mut t_tx) = tokio::io::split(tcp); - let (mut s_rx, mut s_tx) = tokio::io::split(s); - tokio::spawn(async move { - join! { - tokio::io::copy(&mut t_rx, &mut s_tx) , - tokio::io::copy(&mut s_rx, &mut t_tx), - } - }); - } - IpStackStream::Udp(udp) => { - let s = - UdpStream::connect(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)), 53)) - .await - .unwrap(); - let (mut t_rx, mut t_tx) = tokio::io::split(udp); - let (mut s_rx, mut s_tx) = tokio::io::split(s); - tokio::spawn(async move { - join! { - tokio::io::copy(&mut t_rx, &mut s_tx) , - tokio::io::copy(&mut s_rx, &mut t_tx), - } - }); - } - }; - } -} - -#[cfg(target_os = "windows")] -mod wintun { - use std::{net::Ipv4Addr, sync::Arc, task::ready, thread}; - - use tokio::io::{AsyncRead, AsyncWrite}; - - pub struct WinTunDevice { - session: Arc, - receiver: tokio::sync::mpsc::UnboundedReceiver>, - _task: thread::JoinHandle<()>, - } - - impl WinTunDevice { - pub fn new(ip: Ipv4Addr, netmask: Ipv4Addr) -> WinTunDevice { - let wintun = unsafe { wintun::load() }.unwrap(); - let adapter = wintun::Adapter::create(&wintun, "IpStack", "Tunnel", None).unwrap(); - adapter.set_address(ip).unwrap(); - adapter.set_netmask(netmask).unwrap(); - let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap()); - let (receiver_tx, receiver_rx) = tokio::sync::mpsc::unbounded_channel::>(); - let session_reader = session.clone(); - let task = thread::spawn(move || { - loop { - let packet = session_reader.receive_blocking().unwrap(); - let bytes = packet.bytes().to_vec(); - // dbg!(&bytes); - receiver_tx.send(bytes).unwrap(); - } - }); - WinTunDevice { - session, - receiver: receiver_rx, - _task: task, - } - } - } - - impl AsyncRead for WinTunDevice { - fn poll_read( - mut self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - buf: &mut tokio::io::ReadBuf<'_>, - ) -> std::task::Poll> { - match ready!(self.receiver.poll_recv(cx)) { - Some(bytes) => { - buf.put_slice(&bytes); - std::task::Poll::Ready(Ok(())) - } - None => std::task::Poll::Ready(Ok(())), - } - } - } - - impl AsyncWrite for WinTunDevice { - fn poll_write( - self: std::pin::Pin<&mut Self>, - _cx: &mut std::task::Context<'_>, - buf: &[u8], - ) -> std::task::Poll> { - let mut write_pack = self.session.allocate_send_packet(buf.len() as u16)?; - write_pack.bytes_mut().copy_from_slice(buf.as_ref()); - self.session.send_packet(write_pack); - std::task::Poll::Ready(Ok(buf.len())) - } - - fn poll_flush( - self: std::pin::Pin<&mut Self>, - _cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - std::task::Poll::Ready(Ok(())) - } - - fn poll_shutdown( - self: std::pin::Pin<&mut Self>, - _cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - std::task::Poll::Ready(Ok(())) - } - } -} diff --git a/src/error.rs b/src/error.rs index 89f1f3e..2b7f242 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,19 +1,30 @@ -use etherparse::WriteError; -use thiserror::Error; - #[allow(dead_code)] -#[derive(Error, Debug)] +#[derive(thiserror::Error, Debug)] pub enum IpStackError { #[error("The transport protocol is not supported")] UnsupportedTransportProtocol, #[error("The packet is invalid")] InvalidPacket, #[error("Write error: {0}")] - PacketWriteError(WriteError), + PacketWriteError(etherparse::WriteError), #[error("Invalid Tcp packet")] InvalidTcpPacket, #[error("IO error: {0}")] IoError(#[from] std::io::Error), #[error("Accept Error")] AcceptError, + + #[error("Send Error {0}")] + SendError(#[from] tokio::sync::mpsc::error::SendError), } + +impl From for std::io::Error { + fn from(e: IpStackError) -> Self { + match e { + IpStackError::IoError(e) => e, + _ => std::io::Error::new(std::io::ErrorKind::Other, e), + } + } +} + +pub type Result = std::result::Result; diff --git a/src/lib.rs b/src/lib.rs index 3741124..6bfc485 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -pub use error::IpStackError; +pub use error::{IpStackError, Result}; use packet::{NetworkPacket, NetworkTuple}; use std::{ collections::{ @@ -13,6 +13,7 @@ use tokio::{ select, sync::mpsc::{self, UnboundedReceiver, UnboundedSender}, }; +#[cfg(feature = "log")] use tracing::{error, trace}; use crate::{ @@ -25,13 +26,13 @@ pub mod stream; const DROP_TTL: u8 = 0; -#[cfg(not(target_os = "windows"))] +#[cfg(unix)] const TTL: u8 = 64; -#[cfg(target_os = "windows")] +#[cfg(windows)] const TTL: u8 = 128; -#[cfg(not(target_os = "windows"))] +#[cfg(unix)] const TUN_FLAGS: [u8; 2] = [0x00, 0x00]; #[cfg(target_os = "linux")] @@ -46,7 +47,7 @@ const TUN_PROTO_IP4: [u8; 2] = [0x00, 0x02]; pub struct IpStackConfig { pub mtu: u16, - pub packet_info: bool, + pub packet_information: bool, pub tcp_timeout: Duration, pub udp_timeout: Duration, } @@ -55,7 +56,7 @@ impl Default for IpStackConfig { fn default() -> Self { IpStackConfig { mtu: u16::MAX, - packet_info: false, + packet_information: false, tcp_timeout: Duration::from_secs(60), udp_timeout: Duration::from_secs(30), } @@ -72,8 +73,8 @@ impl IpStackConfig { pub fn mtu(&mut self, mtu: u16) { self.mtu = mtu; } - pub fn packet_info(&mut self, packet_info: bool) { - self.packet_info = packet_info; + pub fn packet_information(&mut self, packet_information: bool) { + self.packet_information = packet_information; } } @@ -97,9 +98,10 @@ impl IpStack { // dbg!(streams.len()); select! { Ok(n) = device.read(&mut buffer) => { - let offset = if config.packet_info && cfg!(not(target_os = "windows")) {4} else {0}; + let offset = if config.packet_information && cfg!(unix) {4} else {0}; // dbg!(&buffer[offset..n]); - let Ok(packet) = NetworkPacket::parse(&buffer[offset..n])else{ + let Ok(packet) = NetworkPacket::parse(&buffer[offset..n]) else { + #[cfg(feature = "log")] trace!("parse error"); continue; }; @@ -107,6 +109,7 @@ impl IpStack { Occupied(entry) =>{ let t = packet.transport_protocol(); if let Err(_x) = entry.get().send(packet){ + #[cfg(feature = "log")] trace!("{}", _x); match t{ IpStackPacketProtocol::Tcp(_t) => { @@ -125,17 +128,18 @@ impl IpStack { match IpStackTcpStream::new(packet.src_addr(),packet.dst_addr(),h, pkt_sender.clone(),config.mtu,config.tcp_timeout).await{ Ok(stream) => { entry.insert(stream.stream_sender()); - accept_sender.send(IpStackStream::Tcp(stream)).unwrap(); + accept_sender.send(IpStackStream::Tcp(stream))?; } - Err(e) => { - error!("{}",e); + Err(_e) => { + #[cfg(feature = "log")] + error!("{}", _e); } } } IpStackPacketProtocol::Udp => { let stream = IpStackUdpStream::new(packet.src_addr(),packet.dst_addr(),packet.payload, pkt_sender.clone(),config.mtu,config.udp_timeout); entry.insert(stream.stream_sender()); - accept_sender.send(IpStackStream::Udp(stream)).unwrap(); + accept_sender.send(IpStackStream::Udp(stream))?; } } } @@ -146,29 +150,27 @@ impl IpStack { streams.remove(&packet.reverse_network_tuple()); continue; } - #[cfg(not(target_os = "windows"))] + #[allow(unused_mut)] let Ok(mut packet_byte) = packet.to_bytes() else{ + #[cfg(feature = "log")] trace!("to_bytes error"); continue; }; - #[cfg(target_os = "windows")] - let Ok(packet_byte) = packet.to_bytes() else{ - trace!("to_bytes error"); - continue; - }; - #[cfg(not(target_os = "windows"))] - if config.packet_info { + #[cfg(unix)] + if config.packet_information { if packet.src_addr().is_ipv4(){ packet_byte.splice(0..0, [TUN_FLAGS, TUN_PROTO_IP4].concat()); } else{ packet_byte.splice(0..0, [TUN_FLAGS, TUN_PROTO_IP6].concat()); } } - device.write_all(&packet_byte).await.unwrap(); + device.write_all(&packet_byte).await?; // device.flush().await.unwrap(); } } } + #[allow(unreachable_code)] + Ok::<(), IpStackError>(()) }); IpStack { accept_receiver } diff --git a/src/stream/tcp.rs b/src/stream/tcp.rs index 85c39cf..c3d6fd0 100644 --- a/src/stream/tcp.rs +++ b/src/stream/tcp.rs @@ -21,6 +21,7 @@ use tokio::{ Notify, }, }; +#[cfg(feature = "log")] use tracing::{trace, warn}; use crate::packet::NetworkPacket; @@ -191,6 +192,7 @@ impl AsyncRead for IpStackTcpStream { Pin::new(&mut self.tcb.timeout).poll(cx), std::task::Poll::Ready(_) ) { + #[cfg(feature = "log")] trace!("timeout reached for {:?}", self.dst_addr); self.packet_sender .send(self.create_rev_packet( @@ -469,14 +471,17 @@ impl AsyncWrite for IpStackTcpStream { .send(packet) .map_err(|_| Error::from(ErrorKind::UnexpectedEof))?; self.tcb.retransmission = None; - } else if let Some(i) = self.tcb.retransmission { - warn!(i); - warn!(self.tcb.seq); - warn!(self.tcb.last_ack); - warn!(self.tcb.ack); - for p in self.tcb.inflight_packets.iter() { - warn!(p.seq); - warn!("{}", p.payload.len()); + } else if let Some(_i) = self.tcb.retransmission { + #[cfg(feature = "log")] + { + warn!(_i); + warn!(self.tcb.seq); + warn!(self.tcb.last_ack); + warn!(self.tcb.ack); + for p in self.tcb.inflight_packets.iter() { + warn!(p.seq); + warn!("{}", p.payload.len()); + } } panic!("Please report these values at: https://github.com/narrowlink/ipstack/"); }