#![allow(unused_imports)]
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
use std::time::Duration;
use pnet_packet::ip::IpNextHeaderProtocols;
use pnet_packet::Packet;
#[cfg(any(
target_os = "windows",
target_os = "macos",
all(target_os = "linux", not(target_env = "ohos")),
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
))]
use tun_rs::DeviceBuilder;
use tun_rs::SyncDevice;
#[cfg(any(
target_os = "windows",
target_os = "macos",
all(target_os = "linux", not(target_env = "ohos")),
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
))]
#[cfg(not(any(feature = "async_tokio", feature = "async_io")))]
#[test]
fn test_udp_v4() {
let test_msg = "test udp";
let device = DeviceBuilder::new()
.ipv4("10.26.1.100", 24, None)
.build_sync()
.unwrap();
let device = Arc::new(device);
let _device = device.clone();
let test_udp_v4 = Arc::new(AtomicBool::new(false));
let test_udp_v4_c = test_udp_v4.clone();
let recv_flag = Arc::new(AtomicBool::new(false));
let recv_flag_c = recv_flag.clone();
std::thread::spawn(move || {
let mut buf = [0; 65535];
loop {
let len = device.recv(&mut buf).unwrap();
if let Some(ipv4_packet) = pnet_packet::ipv4::Ipv4Packet::new(&buf[..len]) {
if ipv4_packet.get_next_level_protocol() == IpNextHeaderProtocols::Udp {
if let Some(udp_packet) =
pnet_packet::udp::UdpPacket::new(ipv4_packet.payload())
{
if udp_packet.payload() == test_msg.as_bytes() {
test_udp_v4.store(true, Ordering::Relaxed);
}
}
}
}
if test_udp_v4.load(Ordering::Relaxed) {
recv_flag.store(true, Ordering::Release);
break;
}
}
});
std::thread::sleep(Duration::from_secs(6));
let udp_socket = std::net::UdpSocket::bind("10.26.1.100:0").unwrap();
udp_socket
.send_to(test_msg.as_bytes(), "10.26.1.101:8080")
.unwrap();
let time_now = std::time::Instant::now();
while !recv_flag_c.load(Ordering::Acquire) {
if time_now.elapsed().as_secs() > 2 {
let v4 = test_udp_v4_c.load(Ordering::Relaxed);
assert!(v4, "timeout: test_udp_v4 = {v4}");
return;
}
}
let v4 = test_udp_v4_c.load(Ordering::Relaxed);
assert!(v4);
}
#[cfg(any(
target_os = "windows",
target_os = "macos",
all(target_os = "linux", not(target_env = "ohos")),
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
))]
#[cfg(not(any(feature = "async_tokio", feature = "async_io")))]
#[test]
fn test_udp_v6() {
let test_msg = "test udp";
let device = DeviceBuilder::new()
.ipv6("fd12:3456:789a:1111:2222:3333:4444:5555", 64)
.build_sync()
.unwrap();
let device = Arc::new(device);
let _device = device.clone();
let test_udp_v6 = Arc::new(AtomicBool::new(false));
let test_udp_v6_c = test_udp_v6.clone();
let recv_flag = Arc::new(AtomicBool::new(false));
let recv_flag_c = recv_flag.clone();
std::thread::spawn(move || {
let mut buf = [0; 65535];
loop {
let len = device.recv(&mut buf).unwrap();
if let Some(ipv6_packet) = pnet_packet::ipv6::Ipv6Packet::new(&buf[..len]) {
if ipv6_packet.get_next_header() == IpNextHeaderProtocols::Udp {
if let Some(udp_packet) =
pnet_packet::udp::UdpPacket::new(ipv6_packet.payload())
{
if udp_packet.payload() == test_msg.as_bytes() {
test_udp_v6.store(true, Ordering::Relaxed);
}
}
}
}
if test_udp_v6.load(Ordering::Relaxed) {
recv_flag.store(true, Ordering::Release);
break;
}
}
});
std::thread::sleep(Duration::from_secs(6));
let udp_socket =
std::net::UdpSocket::bind("[fd12:3456:789a:1111:2222:3333:4444:5555]:0").unwrap();
udp_socket
.send_to(
test_msg.as_bytes(),
"[fd12:3456:789a:1111:2222:3333:4444:5556]:8080",
)
.unwrap();
let time_now = std::time::Instant::now();
while !recv_flag_c.load(Ordering::Acquire) {
if time_now.elapsed().as_secs() > 2 {
let v6 = test_udp_v6_c.load(Ordering::Relaxed);
assert!(v6, "timeout: test_udp_v6 = {v6}");
return;
}
}
let v6 = test_udp_v6_c.load(Ordering::Relaxed);
assert!(v6);
}
#[cfg(any(
target_os = "windows",
target_os = "macos",
all(target_os = "linux", not(target_env = "ohos")),
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
))]
#[cfg(feature = "async_tokio")]
#[tokio::test]
async fn test_udp_v4() {
let test_msg = "test udp";
let device = DeviceBuilder::new()
.ipv4("10.26.1.100", 24, None)
.build_async()
.unwrap();
let device = Arc::new(device);
let _device = device.clone();
let test_udp_v4 = Arc::new(AtomicBool::new(false));
let test_udp_v4_c = test_udp_v4.clone();
let recv_flag = Arc::new(AtomicBool::new(false));
let recv_flag_c = recv_flag.clone();
let handler = tokio::spawn(async move {
let mut buf = [0; 65535];
loop {
let len = device.recv(&mut buf).await.unwrap();
if let Some(ipv4_packet) = pnet_packet::ipv4::Ipv4Packet::new(&buf[..len]) {
if ipv4_packet.get_next_level_protocol() == IpNextHeaderProtocols::Udp {
if let Some(udp_packet) =
pnet_packet::udp::UdpPacket::new(ipv4_packet.payload())
{
if udp_packet.payload() == test_msg.as_bytes() {
test_udp_v4.store(true, Ordering::Relaxed);
}
}
}
}
if test_udp_v4.load(Ordering::Relaxed) {
recv_flag.store(true, Ordering::Release);
break;
}
}
});
tokio::time::sleep(Duration::from_secs(6)).await;
let udp_socket = tokio::net::UdpSocket::bind("10.26.1.200:0").await.unwrap();
udp_socket
.send_to(test_msg.as_bytes(), "10.26.1.101:8080")
.await
.unwrap();
tokio::select! {
_=tokio::time::sleep(Duration::from_secs(2))=>{
let v4 = test_udp_v4_c.load(Ordering::Relaxed);
assert!(v4, "timeout: test_udp_v4 = {v4}");
}
_=handler=>{
let flag = recv_flag_c.load(Ordering::Acquire); assert!(flag, "recv_flag = {flag}");
let v4 = test_udp_v4_c.load(Ordering::Relaxed);
assert!(v4);
}
}
}
#[cfg(any(
target_os = "windows",
target_os = "macos",
all(target_os = "linux", not(target_env = "ohos")),
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
))]
#[cfg(feature = "async_tokio")]
#[tokio::test]
async fn test_udp_v6() {
let test_msg = "test udp";
let device = DeviceBuilder::new()
.ipv6("fd12:3456:789a:1111:2222:3333:4444:5555", 64)
.build_async()
.unwrap();
let device = Arc::new(device);
let _device = device.clone();
let test_udp_v6 = Arc::new(AtomicBool::new(false));
let test_udp_v6_c = test_udp_v6.clone();
let recv_flag = Arc::new(AtomicBool::new(false));
let recv_flag_c = recv_flag.clone();
let handler = tokio::spawn(async move {
let mut buf = [0; 65535];
loop {
let len = device.recv(&mut buf).await.unwrap();
if let Some(ipv6_packet) = pnet_packet::ipv6::Ipv6Packet::new(&buf[..len]) {
if ipv6_packet.get_next_header() == IpNextHeaderProtocols::Udp {
if let Some(udp_packet) =
pnet_packet::udp::UdpPacket::new(ipv6_packet.payload())
{
if udp_packet.payload() == test_msg.as_bytes() {
test_udp_v6.store(true, Ordering::Relaxed);
}
}
}
}
if test_udp_v6.load(Ordering::Relaxed) {
recv_flag.store(true, Ordering::Release);
break;
}
}
});
tokio::time::sleep(Duration::from_secs(6)).await;
let udp_socket = tokio::net::UdpSocket::bind("[fd12:3456:789a:1111:2222:3333:4444:5555]:0")
.await
.unwrap();
udp_socket
.send_to(
test_msg.as_bytes(),
"[fd12:3456:789a:1111:2222:3333:4444:5556]:8080",
)
.await
.unwrap();
tokio::select! {
_=tokio::time::sleep(Duration::from_secs(2))=>{
let v6 = test_udp_v6_c.load(Ordering::Relaxed);
assert!(v6, "timeout: test_udp_v6 = {v6}");
}
_=handler=>{
let flag = recv_flag_c.load(Ordering::Acquire); assert!(flag, "recv_flag = {flag}");
let v6 = test_udp_v6_c.load(Ordering::Relaxed);
assert!(v6 );
}
}
}
#[cfg(any(
target_os = "windows",
target_os = "macos",
all(target_os = "linux", not(target_env = "ohos")),
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
))]
#[test]
fn test_op() {
let device = DeviceBuilder::new()
.ipv4("10.26.2.100", 24, None)
.ipv6("fd12:3456:789a:5555:2222:3333:4444:5555", 120)
.build_sync()
.unwrap();
#[cfg(any(target_os = "macos", target_os = "openbsd"))]
device.set_ignore_packet_info(true);
#[cfg(any(target_os = "macos", target_os = "openbsd"))]
assert!(device.ignore_packet_info());
device.set_mtu(1500).unwrap();
assert_eq!(device.mtu().unwrap(), 1500);
#[cfg(target_os = "macos")]
device.set_associate_route(true);
#[cfg(target_os = "macos")]
assert!(device.associate_route());
let vec = device.addresses().unwrap();
assert!(vec
.iter()
.any(|ip| *ip == "10.26.2.100".parse::<std::net::Ipv4Addr>().unwrap()));
assert!(vec.iter().any(|ip| *ip
== "fd12:3456:789a:5555:2222:3333:4444:5555"
.parse::<std::net::Ipv6Addr>()
.unwrap()));
device.set_network_address("10.26.3.200", 24, None).unwrap();
let vec = device.addresses().unwrap();
assert!(vec
.iter()
.any(|ip| *ip == "10.26.3.200".parse::<std::net::Ipv4Addr>().unwrap()));
assert!(vec.iter().any(|ip| *ip
== "fd12:3456:789a:5555:2222:3333:4444:5555"
.parse::<std::net::Ipv6Addr>()
.unwrap()));
assert!(!vec.contains(&"10.26.2.100".parse::<std::net::IpAddr>().unwrap()));
device.add_address_v4("10.6.0.1", 24).unwrap();
let vec = device.addresses().unwrap();
assert!(vec.contains(&"10.6.0.1".parse::<std::net::IpAddr>().unwrap()));
assert!(vec.contains(&"10.26.3.200".parse::<std::net::IpAddr>().unwrap()));
device
.remove_address("10.6.0.1".parse::<std::net::IpAddr>().unwrap())
.unwrap();
let vec = device.addresses().unwrap();
assert!(!vec.contains(&"10.6.0.1".parse::<std::net::IpAddr>().unwrap()));
assert!(vec.contains(&"10.26.3.200".parse::<std::net::IpAddr>().unwrap()));
device
.add_address_v6("fdab:cdef:1234:5678:9abc:def0:1234:5678", 64)
.unwrap();
let vec = device.addresses().unwrap();
assert!(vec.contains(
&"fdab:cdef:1234:5678:9abc:def0:1234:5678"
.parse::<std::net::IpAddr>()
.unwrap()
));
device.enabled(true).unwrap();
#[cfg(any(
target_os = "windows",
all(target_os = "linux", not(target_env = "ohos"))
))]
device.set_name("tun666").unwrap();
#[cfg(any(
target_os = "windows",
all(target_os = "linux", not(target_env = "ohos"))
))]
assert_eq!(device.name().unwrap(), "tun666");
assert!(device.if_index().is_ok());
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
assert!(device.is_running().unwrap());
}
#[cfg(any(
target_os = "windows",
target_os = "macos",
all(target_os = "linux", not(target_env = "ohos")),
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
))]
#[test]
fn create_tun() {
#[cfg(not(target_os = "macos"))]
let name = "tun12";
#[cfg(target_os = "macos")]
let name = "utun12";
let device = DeviceBuilder::new().name(name).build_sync().unwrap();
let dev_name = device.name().unwrap();
assert_eq!(dev_name.as_str(), name);
#[cfg(unix)]
{
use std::os::fd::IntoRawFd;
let fd = device.into_raw_fd();
unsafe {
let sync_device = SyncDevice::from_fd(fd).unwrap();
let dev_name = sync_device.name().unwrap();
assert_eq!(dev_name, name);
}
}
}
#[cfg(any(
target_os = "windows",
target_os = "macos",
all(target_os = "linux", not(target_env = "ohos")),
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
))]
#[test]
fn create_tap() {
#[cfg(not(target_os = "macos"))]
let name = "tap12";
#[cfg(target_os = "macos")]
let name = "feth12";
let device = DeviceBuilder::new()
.name(name)
.layer(tun_rs::Layer::L2)
.build_sync()
.unwrap();
let dev_name = device.name().unwrap();
assert_eq!(dev_name.as_str(), name);
#[cfg(all(unix, not(target_os = "macos")))]
{
use std::os::fd::IntoRawFd;
let fd = device.into_raw_fd();
unsafe {
let sync_device = SyncDevice::from_fd(fd).unwrap();
let dev_name = sync_device.name().unwrap();
assert_eq!(dev_name, name);
}
}
}