支持排除tun

This commit is contained in:
lbl8603
2024-06-09 00:03:28 +08:00
parent 3045e239ff
commit dedc66875b
20 changed files with 460 additions and 465 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ signal-hook = "0.3.17"
winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] }
[features]
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "chacha20_poly1305", "ip_proxy", "port_mapping", "log", "command", "file_config", "lz4"]
default = ["vnt/inner_tun","server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "chacha20_poly1305", "ip_proxy", "port_mapping", "log", "command", "file_config", "lz4"]
openssl = ["vnt/openssl"]
openssl-vendored = ["vnt/openssl-vendored"]
ring-cipher = ["vnt/ring-cipher"]
+3 -2
View File
@@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tun = { path = "tun" }
tun = { path = "tun" ,optional = true}
packet = { path = "./packet" }
bytes = "1.5.0"
log = "0.4.17"
@@ -53,7 +53,7 @@ protoc-bin-vendored = "3.0.0"
cfg_aliases = "0.2.1"
[features]
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "chacha20_poly1305", "ip_proxy", "port_mapping", "lz4_compress", "zstd_compress"]
default = ["server_encrypt", "aes_gcm", "aes_cbc", "aes_ecb", "sm4_cbc", "chacha20_poly1305", "ip_proxy", "port_mapping", "lz4_compress", "zstd_compress","inner_tun"]
openssl = ["openssl-sys"]
# 从源码编译
openssl-vendored = ["openssl-sys/vendored"]
@@ -68,3 +68,4 @@ ip_proxy = ["tokio"]
port_mapping = ["tokio"]
lz4_compress = ["lz4_flex"]
zstd_compress = ["zstd"]
inner_tun = ["tun"]
+45 -41
View File
@@ -1,4 +1,3 @@
use anyhow::Context;
use std::collections::HashMap;
use std::net::Ipv4Addr;
use std::sync::Arc;
@@ -7,8 +6,6 @@ use std::time::Duration;
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::{Mutex, RwLock};
use rand::Rng;
#[cfg(not(target_os = "android"))]
use tun::device::IFace;
use crate::channel::context::ChannelContext;
use crate::channel::idle::Idle;
@@ -24,13 +21,13 @@ use crate::handle::maintain::PunchReceiver;
use crate::handle::recv_data::RecvDataHandler;
use crate::handle::{maintain, BaseConfigInfo, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo};
use crate::nat::NatTest;
#[cfg(feature = "inner_tun")]
use crate::tun_tap_device::tun_create_helper::{DeviceAdapter, TunDeviceHelper};
use crate::tun_tap_device::vnt_device::DeviceWrite;
use crate::util::{
Scheduler, SingleU64Adder, StopManager, U64Adder, WatchSingleU64Adder, WatchU64Adder,
};
use crate::{nat, VntCallback};
#[cfg(not(target_os = "android"))]
use crate::{tun_tap_device, DeviceInfo};
#[derive(Clone)]
pub struct Vnt {
@@ -47,7 +44,23 @@ pub struct Vnt {
}
impl Vnt {
#[cfg(feature = "inner_tun")]
pub fn new<Call: VntCallback>(config: Config, callback: Call) -> anyhow::Result<Self> {
Vnt::new_device0(config, callback, DeviceAdapter::default())
}
#[cfg(not(feature = "inner_tun"))]
pub fn new_device<Call: VntCallback, Device: DeviceWrite>(
config: Config,
callback: Call,
device: Device,
) -> anyhow::Result<Self> {
Vnt::new_device0(config, callback, device)
}
fn new_device0<Call: VntCallback, Device: DeviceWrite>(
config: Config,
callback: Call,
device: Device,
) -> anyhow::Result<Self> {
log::info!("config.toml:{:?}", config);
//服务端非对称加密
#[cfg(feature = "server_encrypt")]
@@ -85,6 +98,11 @@ impl Vnt {
config.device_id.clone(),
config.server_address_str.clone(),
config.name_servers.clone(),
config.mtu.unwrap_or(1420),
#[cfg(target_os = "windows")]
config.tap,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
config.device_name.clone(),
);
// 服务停止管理器
let stop_manager = {
@@ -129,21 +147,6 @@ impl Vnt {
udp_ports,
tcp_port,
);
// pc上先创建虚拟网卡
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
let device = {
log::info!("开始创建tun");
let device = tun_tap_device::create_device(&config).context("create tun failed")?;
log::info!("创建tun成功");
let tun_info = DeviceInfo::new(
device.name().unwrap_or("unknown".into()),
device.version().unwrap_or("unknown".into()),
);
log::info!("tun信息{:?}", tun_info);
callback.create_tun(tun_info);
device
};
// 定时器
let scheduler = Scheduler::new(stop_manager.clone())?;
let external_route = ExternalRoute::new(config.in_ips.clone());
@@ -172,24 +175,23 @@ impl Vnt {
);
let up_counter = SingleU64Adder::new();
let up_count_watcher = up_counter.watch();
let tun_helper = TunDeviceHelper::new(
stop_manager.clone(),
context.clone(),
current_device.clone(),
external_route.clone(),
#[cfg(feature = "ip_proxy")]
proxy_map.clone(),
client_cipher.clone(),
server_cipher.clone(),
config.parallel,
up_counter,
device_list.clone(),
config.compressor,
);
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
let device_adapter = DeviceAdapter::new(device.clone());
#[cfg(target_os = "android")]
let device_adapter = DeviceAdapter::new(tun_helper);
#[cfg(feature = "inner_tun")]
let tun_device_helper = {
TunDeviceHelper::new(
stop_manager.clone(),
context.clone(),
current_device.clone(),
external_route.clone(),
#[cfg(feature = "ip_proxy")]
proxy_map.clone(),
client_cipher.clone(),
server_cipher.clone(),
up_counter,
device_list.clone(),
config.compressor,
device.clone().into_device_adapter(),
)
};
let handler = RecvDataHandler::new(
#[cfg(feature = "server_encrypt")]
@@ -197,7 +199,7 @@ impl Vnt {
server_cipher.clone(),
client_cipher.clone(),
current_device.clone(),
device_adapter,
device,
device_list.clone(),
config_info.clone(),
nat_test.clone(),
@@ -210,6 +212,8 @@ impl Vnt {
proxy_map.clone(),
down_counter,
handshake.clone(),
#[cfg(feature = "inner_tun")]
tun_device_helper,
);
//初始化网络数据通道
@@ -225,8 +229,8 @@ impl Vnt {
nat_test.clone(),
);
#[cfg(not(target_os = "android"))]
tun_helper.start(device)?;
// #[cfg(not(target_os = "android"))]
// tun_helper.start(device)?;
maintain::idle_gateway(
&scheduler,
+1 -4
View File
@@ -32,13 +32,12 @@ pub struct Config {
#[cfg(feature = "ip_proxy")]
pub no_proxy: bool,
pub server_encrypt: bool,
pub parallel: usize,
pub cipher_model: CipherModel,
pub finger: bool,
pub punch_model: PunchModel,
pub ports: Option<Vec<u16>>,
pub first_latency: bool,
#[cfg(not(target_os = "android"))]
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
pub device_name: Option<String>,
pub use_channel_type: UseChannelType,
//控制丢包率
@@ -67,7 +66,6 @@ impl Config {
ip: Option<Ipv4Addr>,
#[cfg(feature = "ip_proxy")] no_proxy: bool,
server_encrypt: bool,
parallel: usize,
cipher_model: CipherModel,
finger: bool,
punch_model: PunchModel,
@@ -130,7 +128,6 @@ impl Config {
#[cfg(feature = "ip_proxy")]
no_proxy,
server_encrypt,
parallel,
cipher_model,
finger,
punch_model,
+26 -5
View File
@@ -189,9 +189,14 @@ impl Into<u8> for ErrorType {
}
}
#[cfg(target_os = "android")]
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct DeviceConfig {
#[cfg(target_os = "windows")]
pub tap: bool,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
pub device_name: Option<String>,
//虚拟网卡mtu值
pub mtu: u32,
//本机虚拟IP
pub virtual_ip: Ipv4Addr,
//子网掩码
@@ -204,9 +209,12 @@ pub struct DeviceConfig {
pub external_route: Vec<(Ipv4Addr, Ipv4Addr)>,
}
#[cfg(target_os = "android")]
impl DeviceConfig {
pub fn new(
#[cfg(target_os = "windows")] tap: bool,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
device_name: Option<String>,
mtu: u32,
virtual_ip: Ipv4Addr,
virtual_netmask: Ipv4Addr,
virtual_gateway: Ipv4Addr,
@@ -214,6 +222,11 @@ impl DeviceConfig {
external_route: Vec<(Ipv4Addr, Ipv4Addr)>,
) -> Self {
Self {
#[cfg(target_os = "windows")]
tap,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
device_name,
mtu,
virtual_ip,
virtual_netmask,
virtual_gateway,
@@ -223,7 +236,6 @@ impl DeviceConfig {
}
}
#[cfg(target_os = "android")]
impl Display for DeviceConfig {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!(
@@ -272,6 +284,7 @@ pub trait VntCallback: Clone + Send + Sync + 'static {
/// 创建网卡的信息
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
#[cfg(feature = "inner_tun")]
fn create_tun(&self, _info: DeviceInfo) {}
/// 连接
fn connect(&self, _info: ConnectInfo) {}
@@ -283,8 +296,16 @@ pub trait VntCallback: Clone + Send + Sync + 'static {
fn register(&self, _info: RegisterInfo) -> bool {
true
}
#[cfg(not(feature = "inner_tun"))]
fn create_device(
&self,
_channel_sender: crate::channel::sender::ChannelSender,
_info: DeviceConfig,
) {
}
#[cfg(target_os = "android")]
fn generate_tun(&self, _info: DeviceConfig) -> u32 {
#[cfg(feature = "inner_tun")]
fn generate_tun(&self, _info: DeviceConfig) -> usize {
0
}
fn peer_client_list(&self, _info: Vec<PeerClientInfo>) {}
+15 -6
View File
@@ -7,6 +7,7 @@ pub mod handshaker;
pub mod maintain;
pub mod recv_data;
pub mod registrar;
#[cfg(feature = "inner_tun")]
pub mod tun_tap;
const SELF_IP: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 2);
@@ -21,12 +22,6 @@ pub fn now_time() -> u64 {
}
}
/// 是否在一个网段
fn check_dest(dest: Ipv4Addr, virtual_netmask: Ipv4Addr, virtual_network: Ipv4Addr) -> bool {
u32::from_be_bytes(dest.octets()) & u32::from_be_bytes(virtual_netmask.octets())
== u32::from_be_bytes(virtual_network.octets())
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PeerDeviceInfo {
pub virtual_ip: Ipv4Addr,
@@ -64,6 +59,11 @@ pub struct BaseConfigInfo {
pub device_id: String,
pub server_addr: String,
pub name_servers: Vec<String>,
pub mtu: u32,
#[cfg(target_os = "windows")]
pub tap: bool,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
pub device_name: Option<String>,
}
impl BaseConfigInfo {
@@ -76,6 +76,10 @@ impl BaseConfigInfo {
device_id: String,
server_addr: String,
name_servers: Vec<String>,
mtu: u32,
#[cfg(target_os = "windows")] tap: bool,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
device_name: Option<String>,
) -> Self {
Self {
name,
@@ -86,6 +90,11 @@ impl BaseConfigInfo {
device_id,
server_addr,
name_servers,
mtu,
#[cfg(target_os = "windows")]
tap,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
device_name,
}
}
}
+7 -9
View File
@@ -9,8 +9,6 @@ use protobuf::Message;
use packet::icmp::{icmp, Kind};
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
use tun::device::IFace;
use crate::channel::context::ChannelContext;
use crate::channel::punch::NatInfo;
@@ -30,12 +28,12 @@ use crate::protocol::control_packet::ControlPacket;
use crate::protocol::{
control_packet, ip_turn_packet, other_turn_packet, NetPacket, Protocol, MAX_TTL,
};
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
use crate::tun_tap_device::vnt_device::DeviceWrite;
/// 处理来源于客户端的包
#[derive(Clone)]
pub struct ClientPacketHandler {
device: DeviceAdapter,
pub struct ClientPacketHandler<Device> {
device: Device,
client_cipher: Cipher,
punch_sender: PunchSender,
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
@@ -45,9 +43,9 @@ pub struct ClientPacketHandler {
ip_proxy_map: Option<IpProxyMap>,
}
impl ClientPacketHandler {
impl<Device: DeviceWrite> ClientPacketHandler<Device> {
pub fn new(
device: DeviceAdapter,
device: Device,
client_cipher: Cipher,
punch_sender: PunchSender,
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
@@ -68,7 +66,7 @@ impl ClientPacketHandler {
}
}
impl PacketHandler for ClientPacketHandler {
impl<Device: DeviceWrite> PacketHandler for ClientPacketHandler<Device> {
fn handle(
&self,
mut net_packet: NetPacket<&mut [u8]>,
@@ -110,7 +108,7 @@ impl PacketHandler for ClientPacketHandler {
}
}
impl ClientPacketHandler {
impl<Device: DeviceWrite> ClientPacketHandler<Device> {
fn ip_turn(
&self,
mut net_packet: NetPacket<&mut [u8]>,
+11 -7
View File
@@ -25,7 +25,7 @@ use crate::handle::{BaseConfigInfo, CurrentDeviceInfo, PeerDeviceInfo, SELF_IP};
use crate::ip_proxy::IpProxyMap;
use crate::nat::NatTest;
use crate::protocol::{NetPacket, HEAD_LEN};
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
use crate::tun_tap_device::vnt_device::DeviceWrite;
use crate::util::U64Adder;
mod client;
@@ -33,16 +33,16 @@ mod server;
mod turn;
#[derive(Clone)]
pub struct RecvDataHandler<Call> {
pub struct RecvDataHandler<Call, Device> {
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
turn: TurnPacketHandler,
client: ClientPacketHandler,
server: ServerPacketHandler<Call>,
client: ClientPacketHandler<Device>,
server: ServerPacketHandler<Call, Device>,
counter: U64Adder,
nat_test: NatTest,
}
impl<Call: VntCallback> RecvChannelHandler for RecvDataHandler<Call> {
impl<Call: VntCallback, Device: DeviceWrite> RecvChannelHandler for RecvDataHandler<Call, Device> {
fn handle(
&mut self,
buf: &mut [u8],
@@ -75,13 +75,13 @@ impl<Call: VntCallback> RecvChannelHandler for RecvDataHandler<Call> {
}
}
impl<Call: VntCallback> RecvDataHandler<Call> {
impl<Call: VntCallback, Device: DeviceWrite> RecvDataHandler<Call, Device> {
pub fn new(
#[cfg(feature = "server_encrypt")] rsa_cipher: Arc<Mutex<Option<RsaCipher>>>,
server_cipher: Cipher,
client_cipher: Cipher,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
device: DeviceAdapter,
device: Device,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
config_info: BaseConfigInfo,
nat_test: NatTest,
@@ -93,6 +93,8 @@ impl<Call: VntCallback> RecvDataHandler<Call> {
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
counter: U64Adder,
handshake: Handshake,
#[cfg(feature = "inner_tun")]
tun_device_helper: crate::tun_tap_device::tun_create_helper::TunDeviceHelper,
) -> Self {
let server = ServerPacketHandler::new(
#[cfg(feature = "server_encrypt")]
@@ -106,6 +108,8 @@ impl<Call: VntCallback> RecvDataHandler<Call> {
callback,
external_route.clone(),
handshake,
#[cfg(feature = "inner_tun")]
tun_device_helper,
);
let client = ClientPacketHandler::new(
device.clone(),
+85 -82
View File
@@ -12,8 +12,6 @@ use protobuf::Message;
use packet::icmp::{icmp, Kind};
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
use tun::device::IFace;
use crate::channel::context::ChannelContext;
use crate::channel::{Route, RouteKey};
@@ -35,41 +33,43 @@ use crate::protocol::body::ENCRYPTION_RESERVED;
use crate::protocol::control_packet::ControlPacket;
use crate::protocol::error_packet::InErrorPacket;
use crate::protocol::{ip_turn_packet, service_packet, NetPacket, Protocol, MAX_TTL};
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
use crate::tun_tap_device::vnt_device::DeviceWrite;
use crate::{proto, PeerClientInfo};
/// 处理来源于服务端的包
#[derive(Clone)]
pub struct ServerPacketHandler<Call> {
pub struct ServerPacketHandler<Call, Device> {
#[cfg(feature = "server_encrypt")]
rsa_cipher: Arc<Mutex<Option<RsaCipher>>>,
server_cipher: Cipher,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
device: DeviceAdapter,
device: Device,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
config_info: BaseConfigInfo,
nat_test: NatTest,
callback: Call,
#[cfg(feature = "server_encrypt")]
up_key_time: Arc<AtomicCell<Instant>>,
#[cfg(not(target_os = "android"))]
route_record: Arc<Mutex<Vec<(Ipv4Addr, Ipv4Addr)>>>,
external_route: ExternalRoute,
handshake: Handshake,
#[cfg(feature = "inner_tun")]
tun_device_helper: crate::tun_tap_device::tun_create_helper::TunDeviceHelper,
}
impl<Call> ServerPacketHandler<Call> {
impl<Call, Device> ServerPacketHandler<Call, Device> {
pub fn new(
#[cfg(feature = "server_encrypt")] rsa_cipher: Arc<Mutex<Option<RsaCipher>>>,
server_cipher: Cipher,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
device: DeviceAdapter,
device: Device,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
config_info: BaseConfigInfo,
nat_test: NatTest,
callback: Call,
external_route: ExternalRoute,
handshake: Handshake,
#[cfg(feature = "inner_tun")]
tun_device_helper: crate::tun_tap_device::tun_create_helper::TunDeviceHelper,
) -> Self {
Self {
#[cfg(feature = "server_encrypt")]
@@ -83,15 +83,15 @@ impl<Call> ServerPacketHandler<Call> {
callback,
#[cfg(feature = "server_encrypt")]
up_key_time: Arc::new(AtomicCell::new(Instant::now() - Duration::from_secs(60))),
#[cfg(not(target_os = "android"))]
route_record: Arc::new(Mutex::default()),
external_route,
handshake,
#[cfg(feature = "inner_tun")]
tun_device_helper,
}
}
}
impl<Call: VntCallback> PacketHandler for ServerPacketHandler<Call> {
impl<Call: VntCallback, Device: DeviceWrite> PacketHandler for ServerPacketHandler<Call, Device> {
fn handle(
&self,
mut net_packet: NetPacket<&mut [u8]>,
@@ -246,7 +246,7 @@ impl<Call: VntCallback> PacketHandler for ServerPacketHandler<Call> {
}
}
impl<Call: VntCallback> ServerPacketHandler<Call> {
impl<Call: VntCallback, Device: DeviceWrite> ServerPacketHandler<Call, Device> {
fn service(
&self,
context: &ChannelContext,
@@ -305,80 +305,83 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
if old.virtual_ip != Ipv4Addr::UNSPECIFIED {
log::info!("ip发生变化,old:{:?},response={:?}", old, response);
}
#[cfg(target_os = "android")]
let device_config = crate::handle::callback::DeviceConfig::new(
#[cfg(target_os = "windows")]
self.config_info.tap,
#[cfg(any(
target_os = "windows",
target_os = "linux",
target_os = "macos"
))]
self.config_info.device_name.clone(),
self.config_info.mtu,
virtual_ip,
virtual_netmask,
virtual_gateway,
virtual_network,
self.external_route.to_route(),
);
#[cfg(not(feature = "inner_tun"))]
self.callback.create_device(context.sender(), device_config);
#[cfg(feature = "inner_tun")]
{
let device_config = crate::handle::callback::DeviceConfig::new(
virtual_ip,
virtual_netmask,
virtual_gateway,
virtual_network,
self.external_route.to_route(),
);
let device_fd = self.callback.generate_tun(device_config);
if device_fd == 0 {
self.callback.error(ErrorInfo::new_msg(
ErrorType::Unknown,
"device_fd == 0".into(),
));
} else {
if let Err(e) = self.device.start(device_fd as _) {
self.tun_device_helper.stop();
#[cfg(any(
target_os = "windows",
target_os = "linux",
target_os = "macos"
))]
match crate::tun_tap_device::create_device(device_config) {
Ok(device) => {
use tun::device::IFace;
let tun_info = crate::handle::callback::DeviceInfo::new(
device.name().unwrap_or("unknown".into()),
device.version().unwrap_or("unknown".into()),
);
log::info!("tun信息{:?}", tun_info);
self.callback.create_tun(tun_info);
self.tun_device_helper.start(device)?;
}
Err(e) => {
log::error!("{:?}", e);
self.callback.error(e);
}
}
#[cfg(target_os = "android")]
{
let device_config = crate::handle::callback::DeviceConfig::new(
self.config_info.mtu,
virtual_ip,
virtual_netmask,
virtual_gateway,
virtual_network,
self.external_route.to_route(),
);
let device_fd = self.callback.generate_tun(device_config);
if device_fd == 0 {
self.callback.error(ErrorInfo::new_msg(
ErrorType::Unknown,
format!("{:?}", e),
"device_fd == 0".into(),
));
}
}
}
#[cfg(not(target_os = "android"))]
{
if let Err(e) = self.device.set_ip(virtual_ip, virtual_netmask) {
log::error!("LocalIpExists {:?}", e);
self.callback.error(ErrorInfo::new_msg(
ErrorType::LocalIpExists,
format!("set_ip {:?}", e),
));
return Ok(());
}
let mut guard = self.route_record.lock();
for (dest, mask) in guard.drain(..) {
if let Err(e) = self.device.delete_route(dest, mask) {
log::warn!("删除路由失败 ={:?}", e);
}
}
if let Err(e) =
self.device.add_route(virtual_network, virtual_netmask, 1)
{
log::warn!("添加默认路由失败 ={:?}", e);
} else {
guard.push((virtual_network, virtual_netmask));
}
if let Err(e) =
self.device
.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, 1)
{
log::warn!("添加广播路由失败 ={:?}", e);
} else {
guard.push((Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST));
}
if let Err(e) = self.device.add_route(
Ipv4Addr::from([224, 0, 0, 0]),
Ipv4Addr::from([240, 0, 0, 0]),
1,
) {
log::warn!("添加组播路由失败 ={:?}", e);
} else {
guard.push((
Ipv4Addr::from([224, 0, 0, 0]),
Ipv4Addr::from([240, 0, 0, 0]),
));
}
for (dest, mask) in self.external_route.to_route() {
if let Err(e) = self.device.add_route(dest, mask, 1) {
log::warn!("添加路由失败 ={:?}", e);
} else {
guard.push((dest, mask));
match tun::Device::new(device_fd as _) {
Ok(device) => {
if let Err(e) =
self.tun_device_helper.start(Arc::new(device))
{
self.callback.error(ErrorInfo::new_msg(
ErrorType::Unknown,
format!("{:?}", e),
));
}
}
Err(e) => {
self.callback.error(ErrorInfo::new_msg(
ErrorType::Unknown,
format!("{:?}", e),
));
}
}
}
}
}
-30
View File
@@ -1,30 +0,0 @@
use std::sync::mpsc::{sync_channel, Receiver, SendError, SyncSender};
pub fn channel_group<T>(size: usize, bound: usize) -> (GroupSyncSender<T>, Vec<Receiver<T>>) {
let mut senders = Vec::with_capacity(size);
let mut receivers = Vec::with_capacity(size);
for _ in 0..size {
let (s, r) = sync_channel(bound);
senders.push(s);
receivers.push(r);
}
(
GroupSyncSender {
count: 0,
base: senders,
},
receivers,
)
}
pub struct GroupSyncSender<T> {
count: usize,
base: Vec<SyncSender<T>>,
}
impl<T> GroupSyncSender<T> {
pub fn send(&mut self, t: T) -> Result<(), SendError<T>> {
self.count += 1;
self.base[self.count % self.base.len()].send(t)
}
}
+35 -1
View File
@@ -1,11 +1,45 @@
mod channel_group;
pub mod tun_handler;
#[cfg(unix)]
mod unix;
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::Mutex;
use std::sync::Arc;
#[cfg(unix)]
pub(crate) use unix::*;
#[cfg(target_os = "windows")]
mod windows;
#[cfg(target_os = "windows")]
pub(crate) use windows::*;
/// 仅仅是停止tun,不停止vnt
#[derive(Clone, Default)]
pub struct DeviceStop {
f: Arc<Mutex<Option<Box<dyn FnOnce() -> bool + Send>>>>,
stopped: Arc<AtomicCell<bool>>,
}
impl DeviceStop {
pub fn set_stop_fn<F>(&self, f: F)
where
F: FnOnce() -> bool + Send + 'static,
{
self.f.lock().replace(Box::new(f));
}
pub fn stop(&self) -> bool {
if let Some(f) = self.f.lock().take() {
f()
} else {
false
}
}
pub fn stopped(&self) {
self.stopped.store(true);
}
pub fn is_stop(&self) -> bool {
self.stopped.load()
}
}
+30 -83
View File
@@ -13,12 +13,11 @@ use tun::device::IFace;
use tun::Device;
use crate::channel::context::ChannelContext;
use crate::channel::BUFFER_SIZE;
use crate::cipher::Cipher;
use crate::compression::Compressor;
use crate::external_route::ExternalRoute;
use crate::handle::tun_tap::channel_group::channel_group;
use crate::handle::{check_dest, CurrentDeviceInfo, PeerDeviceInfo};
use crate::handle::tun_tap::DeviceStop;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::IpProxyMap;
#[cfg(feature = "ip_proxy")]
@@ -28,7 +27,11 @@ use crate::protocol::body::ENCRYPTION_RESERVED;
use crate::protocol::ip_turn_packet::BroadcastPacket;
use crate::protocol::{ip_turn_packet, NetPacket, MAX_TTL};
use crate::util::{SingleU64Adder, StopManager};
/// 是否在一个网段
fn check_dest(dest: Ipv4Addr, virtual_netmask: Ipv4Addr, virtual_network: Ipv4Addr) -> bool {
u32::from_be_bytes(dest.octets()) & u32::from_be_bytes(virtual_netmask.octets())
== u32::from_be_bytes(virtual_network.octets())
}
fn icmp(device_writer: &Device, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> anyhow::Result<()> {
if ipv4_packet.protocol() == Protocol::Icmp {
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
@@ -54,89 +57,33 @@ pub fn start(
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
client_cipher: Cipher,
server_cipher: Cipher,
parallel: usize,
mut up_counter: SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
device_stop: DeviceStop,
) -> io::Result<()> {
if parallel > 1 {
let (sender, receivers) = channel_group::<(Vec<u8>, usize)>(parallel, 16);
for (index, receiver) in receivers.into_iter().enumerate() {
let context = context.clone();
let device = device.clone();
let current_device = current_device.clone();
let ip_route = ip_route.clone();
#[cfg(feature = "ip_proxy")]
let ip_proxy_map = ip_proxy_map.clone();
let client_cipher = client_cipher.clone();
let server_cipher = server_cipher.clone();
let device_list = device_list.clone();
thread::Builder::new()
.name(format!("tunHandler-{}", index))
.spawn(move || {
let mut extend = [0; BUFFER_SIZE];
while let Ok((mut buf, len)) = receiver.recv() {
#[cfg(not(target_os = "macos"))]
let start = 0;
#[cfg(target_os = "macos")]
let start = 4;
match handle(
&context,
&mut buf[start..],
len,
&mut extend,
&device,
current_device.load(),
&ip_route,
#[cfg(feature = "ip_proxy")]
&ip_proxy_map,
&client_cipher,
&server_cipher,
&device_list,
&compressor,
) {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
}
})?;
}
thread::Builder::new()
.name("tunHandlerM".into())
.spawn(move || {
if let Err(e) = crate::handle::tun_tap::start_multi(
stop_manager,
device,
sender,
&mut up_counter,
) {
log::warn!("stop:{}", e);
}
})?;
} else {
thread::Builder::new()
.name("tunHandlerS".into())
.spawn(move || {
if let Err(e) = crate::handle::tun_tap::start_simple(
stop_manager,
&context,
device,
current_device,
ip_route,
#[cfg(feature = "ip_proxy")]
ip_proxy_map,
client_cipher,
server_cipher,
&mut up_counter,
device_list,
compressor,
) {
log::warn!("stop:{}", e);
}
})?;
}
thread::Builder::new()
.name("tunHandlerS".into())
.spawn(move || {
if let Err(e) = crate::handle::tun_tap::start_simple(
stop_manager,
&context,
device,
current_device,
ip_route,
#[cfg(feature = "ip_proxy")]
ip_proxy_map,
client_cipher,
server_cipher,
&mut up_counter,
device_list,
compressor,
device_stop,
) {
log::warn!("stop:{}", e);
}
})?;
Ok(())
}
+33 -67
View File
@@ -3,7 +3,7 @@ use crate::channel::BUFFER_SIZE;
use crate::cipher::Cipher;
use crate::compression::Compressor;
use crate::external_route::ExternalRoute;
use crate::handle::tun_tap::channel_group::GroupSyncSender;
use crate::handle::tun_tap::DeviceStop;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::IpProxyMap;
@@ -33,13 +33,38 @@ pub(crate) fn start_simple(
up_counter: &mut SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
device_stop: DeviceStop,
) -> anyhow::Result<()> {
let stop_all = Arc::new(AtomicCell::new(true));
let poll = Poll::new()?;
let waker = Arc::new(Waker::new(poll.registry(), STOP)?);
let _waker = waker.clone();
let worker = stop_manager.add_listener("tun_device".into(), move || {
let _ = waker.wake();
})?;
let device_cell = Arc::new(AtomicCell::new(Some(waker)));
let worker = {
let device_cell = device_cell.clone();
stop_manager.add_listener("tun_device".into(), move || {
if let Some(waker) = device_cell.take() {
if let Err(e) = waker.wake() {
log::warn!("{:?}", e);
}
}
})?
};
{
let stop_all = stop_all.clone();
device_stop.set_stop_fn(move || {
if let Some(waker) = device_cell.take() {
stop_all.store(false);
if let Err(e) = waker.wake() {
log::warn!("{:?}", e);
return false;
}
true
} else {
false
}
});
}
if let Err(e) = start_simple0(
poll,
context,
@@ -56,7 +81,10 @@ pub(crate) fn start_simple(
) {
log::error!("{:?}", e);
};
worker.stop_all();
device_stop.stopped();
if stop_all.load() {
worker.stop_all();
}
drop(_waker);
Ok(())
}
@@ -131,65 +159,3 @@ fn start_simple0(
}
}
}
pub(crate) fn start_multi(
stop_manager: StopManager,
device: Arc<Device>,
group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
up_counter: &mut SingleU64Adder,
) -> anyhow::Result<()> {
let poll = Poll::new()?;
let waker = Arc::new(Waker::new(poll.registry(), STOP)?);
let _waker = waker.clone();
let worker = stop_manager.add_listener("tun_device".into(), move || {
let _ = waker.wake();
})?;
if let Err(e) = start_multi0(poll, device, group_sync_sender, up_counter) {
log::error!("{:?}", e);
};
worker.stop_all();
drop(_waker);
Ok(())
}
fn start_multi0(
mut poll: Poll,
device: Arc<Device>,
mut group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
up_counter: &mut SingleU64Adder,
) -> anyhow::Result<()> {
let fd = device.as_tun_fd();
fd.set_nonblock()?;
SourceFd(&fd.as_raw_fd()).register(poll.registry(), FD, Interest::READABLE)?;
let mut evnets = Events::with_capacity(4);
let mut buf = vec![0; 1024 * 16];
#[cfg(not(target_os = "macos"))]
let start = 12;
#[cfg(target_os = "macos")]
let start = 12 - 4;
loop {
poll.poll(&mut evnets, None)?;
for event in evnets.iter() {
if event.token() == STOP {
return Ok(());
}
loop {
let len = match fd.read(&mut buf[start..]) {
Ok(len) => len + start,
Err(e) => {
if e.kind() == io::ErrorKind::WouldBlock {
break;
}
Err(e)?
}
};
//单线程的
up_counter.add(len as u64);
if group_sync_sender.send((buf, len)).is_err() {
return Ok(());
}
buf = vec![0; 1024 * 16];
}
}
}
}
+29 -40
View File
@@ -3,7 +3,7 @@ use crate::channel::BUFFER_SIZE;
use crate::cipher::Cipher;
use crate::compression::Compressor;
use crate::external_route::ExternalRoute;
use crate::handle::tun_tap::channel_group::GroupSyncSender;
use crate::handle::tun_tap::DeviceStop;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::IpProxyMap;
@@ -26,15 +26,35 @@ pub(crate) fn start_simple(
up_counter: &mut SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
device_stop: DeviceStop,
) -> anyhow::Result<()> {
let device_cell = Arc::new(AtomicCell::new(Some(device.clone())));
let stop_all = Arc::new(AtomicCell::new(true));
let worker = {
let device = device.clone();
let device_cell = device_cell.clone();
stop_manager.add_listener("tun_device".into(), move || {
if let Err(e) = device.shutdown() {
log::warn!("{:?}", e);
if let Some(device) = device_cell.take() {
if let Err(e) = device.shutdown() {
log::warn!("{:?}", e);
}
}
})?
};
{
let stop_all = stop_all.clone();
device_stop.set_stop_fn(move || {
if let Some(device) = device_cell.take() {
stop_all.store(false);
if let Err(e) = device.shutdown() {
log::warn!("{:?}", e);
return false;
}
true
} else {
false
}
});
}
if let Err(e) = start_simple0(
context,
device,
@@ -50,9 +70,13 @@ pub(crate) fn start_simple(
) {
log::error!("{:?}", e);
}
worker.stop_all();
device_stop.stopped();
if stop_all.load() {
worker.stop_all();
}
Ok(())
}
fn start_simple0(
context: &ChannelContext,
device: Arc<Device>,
@@ -95,38 +119,3 @@ fn start_simple0(
}
}
}
pub(crate) fn start_multi(
stop_manager: StopManager,
device: Arc<Device>,
group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
up_counter: &mut SingleU64Adder,
) -> anyhow::Result<()> {
let worker = {
let device = device.clone();
stop_manager.add_listener("tun_device_multi".into(), move || {
if let Err(e) = device.shutdown() {
log::warn!("{:?}", e);
}
})?
};
if let Err(e) = start_multi0(device, group_sync_sender, up_counter) {
log::error!("{:?}", e);
};
worker.stop_all();
Ok(())
}
fn start_multi0(
device: Arc<Device>,
mut group_sync_sender: GroupSyncSender<(Vec<u8>, usize)>,
up_counter: &mut SingleU64Adder,
) -> anyhow::Result<()> {
loop {
let mut buf = vec![0; 1024 * 16];
let len = device.read(&mut buf[12..])? + 12;
//单线程的
up_counter.add(len as u64);
if group_sync_sender.send((buf, len)).is_err() {
return Ok(());
}
}
}
+44 -10
View File
@@ -1,4 +1,6 @@
use crate::{DeviceConfig, ErrorInfo, ErrorType};
use std::io;
use std::net::Ipv4Addr;
use std::sync::Arc;
use tun::device::IFace;
use tun::Device;
@@ -8,8 +10,47 @@ const DEFAULT_TUN_NAME: &str = "vnt-tun";
#[cfg(target_os = "windows")]
const DEFAULT_TAP_NAME: &str = "vnt-tap";
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
pub fn create_device(config: &crate::core::Config) -> io::Result<Arc<Device>> {
pub fn create_device(config: DeviceConfig) -> Result<Arc<Device>, ErrorInfo> {
let device = match create_device0(&config) {
Ok(device) => device,
Err(e) => {
return Err(ErrorInfo::new_msg(
ErrorType::Unknown,
format!("create device {:?}", e),
));
}
};
if let Err(e) = device.set_ip(config.virtual_ip, config.virtual_netmask) {
log::error!("LocalIpExists {:?}", e);
return Err(ErrorInfo::new_msg(
ErrorType::LocalIpExists,
format!("set_ip {:?}", e),
));
}
if let Err(e) = device.add_route(config.virtual_network, config.virtual_netmask, 1) {
log::warn!("添加默认路由失败 ={:?}", e);
}
if let Err(e) = device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, 1) {
log::warn!("添加广播路由失败 ={:?}", e);
}
if let Err(e) = device.add_route(
Ipv4Addr::from([224, 0, 0, 0]),
Ipv4Addr::from([240, 0, 0, 0]),
1,
) {
log::warn!("添加组播路由失败 ={:?}", e);
}
for (dest, mask) in config.external_route {
if let Err(e) = device.add_route(dest, mask, 1) {
log::warn!("添加路由失败 ={:?}", e);
}
}
Ok(device)
}
fn create_device0(config: &DeviceConfig) -> io::Result<Arc<Device>> {
#[cfg(target_os = "windows")]
let default_name: &str = if config.tap {
DEFAULT_TAP_NAME
@@ -37,14 +78,7 @@ pub fn create_device(config: &crate::core::Config) -> io::Result<Arc<Device>> {
.unwrap_or(default_name.to_string()),
config.tap,
)?);
let mtu = config.mtu.unwrap_or_else(|| {
if config.password.is_none() {
1450
} else {
1410
}
});
device.set_mtu(mtu)?;
device.set_mtu(config.mtu)?;
Ok(device)
}
+5
View File
@@ -1,6 +1,11 @@
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
#[cfg(feature = "inner_tun")]
pub use create_device::create_device;
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
#[cfg(feature = "inner_tun")]
mod create_device;
#[cfg(feature = "inner_tun")]
pub mod tun_create_helper;
pub mod vnt_device;
+81 -74
View File
@@ -4,69 +4,60 @@ use std::sync::Arc;
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::Mutex;
use tun::device::IFace;
use tun::Device;
use crate::channel::context::ChannelContext;
use crate::cipher::Cipher;
use crate::compression::Compressor;
use crate::external_route::ExternalRoute;
use crate::handle::tun_tap::DeviceStop;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::IpProxyMap;
use crate::tun_tap_device::vnt_device::DeviceWrite;
use crate::util::{SingleU64Adder, StopManager};
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
#[repr(transparent)]
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct DeviceAdapter {
tun: Arc<Device>,
tun: Arc<Mutex<Option<Arc<Device>>>>,
}
impl DeviceAdapter {
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
pub fn new(tun: Arc<Device>) -> Self {
Self { tun }
pub fn insert(&self, device: Arc<Device>) {
let r = self.tun.lock().replace(device);
assert!(r.is_none());
}
#[cfg(target_os = "android")]
pub fn new(tun_device_helper: TunDeviceHelper) -> Self {
Self {
tun: Arc::new(AtomicCell::new(-1 as _)),
tun_device_helper,
/// 要保证先remove 再insert
pub fn remove(&self) {
drop(self.tun.lock().take());
}
}
impl DeviceWrite for DeviceAdapter {
#[inline]
fn write(&self, buf: &[u8]) -> io::Result<usize> {
if let Some(tun) = self.tun.lock().as_ref() {
tun.write(buf)
} else {
Err(io::Error::new(io::ErrorKind::NotFound, "not tun device"))
}
}
}
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
impl std::ops::Deref for DeviceAdapter {
type Target = Arc<Device>;
fn deref(&self) -> &Self::Target {
&self.tun
}
}
#[cfg(target_os = "android")]
#[derive(Clone)]
pub struct DeviceAdapter {
tun: Arc<AtomicCell<std::os::fd::RawFd>>,
tun_device_helper: TunDeviceHelper,
}
#[cfg(target_os = "android")]
impl DeviceAdapter {
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let fd = self.tun.load();
tun::Fd(fd).write(buf)
}
pub fn start(&self, fd: std::os::fd::RawFd) -> io::Result<()> {
//安卓端fd是由外部释放的,所以这里这么搞免得加锁
self.tun_device_helper.start(Arc::new(Device::new(fd)?))?;
self.tun.store(fd);
Ok(())
fn into_device_adapter(self) -> DeviceAdapter {
self
}
}
#[derive(Clone)]
pub struct TunDeviceHelper {
inner: Arc<AtomicCell<Option<TunDeviceHelperInner>>>,
inner: Arc<Mutex<TunDeviceHelperInner>>,
device_adapter: DeviceAdapter,
device_stop: Arc<Mutex<Option<DeviceStop>>>,
}
#[derive(Clone)]
struct TunDeviceHelperInner {
stop_manager: StopManager,
context: ChannelContext,
@@ -76,7 +67,6 @@ struct TunDeviceHelperInner {
ip_proxy_map: Option<IpProxyMap>,
client_cipher: Cipher,
server_cipher: Cipher,
parallel: usize,
up_counter: SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
@@ -91,48 +81,65 @@ impl TunDeviceHelper {
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
client_cipher: Cipher,
server_cipher: Cipher,
parallel: usize,
up_counter: SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
compressor: Compressor,
device_adapter: DeviceAdapter,
) -> Self {
let inner = TunDeviceHelperInner {
stop_manager,
context,
current_device,
ip_route,
#[cfg(feature = "ip_proxy")]
ip_proxy_map,
client_cipher,
server_cipher,
up_counter,
device_list,
compressor,
};
Self {
inner: Arc::new(AtomicCell::new(Some(TunDeviceHelperInner {
stop_manager,
context,
current_device,
ip_route,
#[cfg(feature = "ip_proxy")]
ip_proxy_map,
client_cipher,
server_cipher,
parallel,
up_counter,
device_list,
compressor,
}))),
inner: Arc::new(Mutex::new(inner)),
device_adapter,
device_stop: Default::default(),
}
}
pub fn start(&self, device: Arc<Device>) -> io::Result<()> {
if let Some(inner) = self.inner.take() {
crate::handle::tun_tap::tun_handler::start(
inner.stop_manager,
inner.context,
device,
inner.current_device,
inner.ip_route,
#[cfg(feature = "ip_proxy")]
inner.ip_proxy_map,
inner.client_cipher,
inner.server_cipher,
inner.parallel,
inner.up_counter,
inner.device_list,
inner.compressor,
)?;
Ok(())
} else {
Err(io::Error::new(io::ErrorKind::Other, "Repeated start"))
pub fn stop(&self) {
//先停止旧的,再启动新的,改变旧网卡的IP太麻烦
if let Some(device_stop) = self.device_stop.lock().take() {
self.device_adapter.remove();
loop {
device_stop.stop();
std::thread::sleep(std::time::Duration::from_millis(300));
//确保停止了
if device_stop.is_stop() {
break;
}
}
}
}
/// 要保证先stop 再start
pub fn start(&self, device: Arc<Device>) -> io::Result<()> {
self.device_adapter.insert(device.clone());
let device_stop = DeviceStop::default();
let s = self.device_stop.lock().replace(device_stop.clone());
assert!(s.is_none());
let inner = self.inner.lock().clone();
crate::handle::tun_tap::tun_handler::start(
inner.stop_manager,
inner.context,
device,
inner.current_device,
inner.ip_route,
#[cfg(feature = "ip_proxy")]
inner.ip_proxy_map,
inner.client_cipher,
inner.server_cipher,
inner.up_counter,
inner.device_list,
inner.compressor,
device_stop,
)
}
}
+7
View File
@@ -0,0 +1,7 @@
use std::io;
pub trait DeviceWrite: Clone + Send + Sync + 'static {
fn write(&self, buf: &[u8]) -> io::Result<usize>;
#[cfg(feature = "inner_tun")]
fn into_device_adapter(self) -> crate::tun_tap_device::tun_create_helper::DeviceAdapter;
}
+1
View File
@@ -8,6 +8,7 @@ pub struct U64Adder {
inner: Arc<U64AdderInner>,
index: usize,
}
#[derive(Clone)]
pub struct SingleU64Adder {
inner: Arc<SingleU64AdderInner>,
}
+1 -3
View File
@@ -62,9 +62,7 @@ impl IntoRawFd for Fd {
impl Drop for Fd {
fn drop(&mut self) {
unsafe {
if self.0 >= 0 {
libc::close(self.0);
}
libc::close(self.0);
}
}
}