修改安卓端逻辑

This commit is contained in:
lbl8603
2024-04-19 10:49:47 +08:00
parent 84824731a7
commit 8dfc3b8c43
26 changed files with 1191 additions and 186 deletions
@@ -12,8 +12,10 @@ public interface CallBack {
* 连接成功的回调
*/
void success();
/**
* 创建虚拟网卡成功的回调方法
* 仅在 windows/linux/macos上使用
*
* @param info 网卡信息
*/
@@ -42,6 +44,24 @@ public interface CallBack {
*/
boolean register(RegisterInfo info);
/**
* 创建网卡回调
* 仅在android上使用
*
* @param info 创建配置
* @return 网卡fd
*/
int generateTun(DeviceConfig info);
/**
* 对端用户列表
*
* @param infoArray
*/
void peerClientList(PeerClientInfo[] infoArray);
/**
* 异常回调
*
@@ -5,13 +5,13 @@ package top.wherewego.vnt.jni;
*
* @author https://github.com/lbl8603/vnt
*/
public class PeerDeviceInfo {
public class PeerRouteInfo {
private final int virtualIp;
private final String name;
private final String status;
private final Route route;
public PeerDeviceInfo(int virtualIp, String name, String status, Route route) {
public PeerRouteInfo(int virtualIp, String name, String status, Route route) {
this.virtualIp = virtualIp;
this.name = name;
this.status = status;
+13 -2
View File
@@ -6,16 +6,26 @@ package top.wherewego.vnt.jni;
* @author https://github.com/lbl8603/vnt
*/
public class Route {
/**
* 是否使用tcp
*/
private final boolean tcp;
private final String address;
private final byte metric;
private final int rt;
public Route(String address, byte metric, int rt) {
public Route(boolean tcp, String address, byte metric, int rt) {
this.tcp = tcp;
this.address = address;
this.metric = metric;
this.rt = rt;
}
public boolean isTcp() {
return tcp;
}
public String getAddress() {
return address;
}
@@ -31,7 +41,8 @@ public class Route {
@Override
public String toString() {
return "Route{" +
"address='" + address + '\'' +
"tcp=" + tcp +
", address='" + address + '\'' +
", metric=" + metric +
", rt=" + rt +
'}';
+5 -2
View File
@@ -13,6 +13,9 @@ public class Vnt implements Closeable {
public Vnt(Config config, CallBack callBack) throws Exception{
this.raw = new0(config, callBack);
if (this.raw == 0) {
throw new RuntimeException();
}
}
public void stop() {
@@ -23,7 +26,7 @@ public class Vnt implements Closeable {
wait0(raw);
}
public PeerDeviceInfo[] list() {
public PeerRouteInfo[] list() {
return list0(raw);
}
@@ -35,7 +38,7 @@ public class Vnt implements Closeable {
private native void drop0(long raw);
private native PeerDeviceInfo[] list0(long raw);
private native PeerRouteInfo[] list0(long raw);
@Override
public void close() throws IOException {
@@ -0,0 +1,60 @@
package top.wherewego.vnt.jni.param;
import top.wherewego.vnt.jni.IpUtils;
/**
* 创建网卡所需信息,仅在android上使用
*
* @author https://github.com/lbl8603/vnt
*/
public class DeviceConfig {
/**
* 虚拟IP
*/
public final int virtualIp;
/**
* 掩码
*/
public final int virtualNetmask;
/**
* 网关
*/
public final int virtualGateway;
/**
* 虚拟网段
*/
public final int virtualNetwork;
public DeviceConfig(int virtualIp, int virtualNetmask, int virtualGateway, int virtualNetwork) {
this.virtualIp = virtualIp;
this.virtualNetmask = virtualNetmask;
this.virtualGateway = virtualGateway;
this.virtualNetwork = virtualNetwork;
}
public int getVirtualIp() {
return virtualIp;
}
public int getVirtualNetmask() {
return virtualNetmask;
}
public int getVirtualGateway() {
return virtualGateway;
}
public int getVirtualNetwork() {
return virtualNetwork;
}
@Override
public String toString() {
return "DeviceConfig{" +
"virtualIp=" + IpUtils.intToIpAddress(virtualIp) +
", virtualNetmask=" + IpUtils.intToIpAddress(virtualNetmask) +
", virtualGateway=" + IpUtils.intToIpAddress(virtualGateway) +
", virtualNetwork=" + IpUtils.intToIpAddress(virtualNetwork) +
'}';
}
}
@@ -1,7 +1,7 @@
package top.wherewego.vnt.jni.param;
/**
* 网卡信息
* 网卡信息 仅在 windows/linux/macos上使用
*
* @author https://github.com/lbl8603/vnt
*/
@@ -16,15 +16,25 @@ public class ErrorInfo {
public final String msg;
public ErrorInfo(int code, String msg) {
this.code = switch (code) {
case 1 -> ErrorCodeEnum.TokenError;
case 2 -> ErrorCodeEnum.Disconnect;
case 3 -> ErrorCodeEnum.AddressExhausted;
case 4 -> ErrorCodeEnum.IpAlreadyExists;
case 5 -> ErrorCodeEnum.InvalidIp;
case 6 -> ErrorCodeEnum.Unknown;
default -> null;
};
switch (code) {
case 1:
this.code = ErrorCodeEnum.TokenError;
break;
case 2:
this.code = ErrorCodeEnum.Disconnect;
break;
case 3:
this.code = ErrorCodeEnum.AddressExhausted;
break;
case 4:
this.code = ErrorCodeEnum.IpAlreadyExists;
break;
case 5:
this.code = ErrorCodeEnum.InvalidIp;
break;
default:
this.code = ErrorCodeEnum.Unknown;
}
this.msg = msg;
}
@@ -0,0 +1,60 @@
package top.wherewego.vnt.jni.param;
import top.wherewego.vnt.jni.IpUtils;
/**
* 创建网卡所需信息,仅在android上使用
*
* @author https://github.com/lbl8603/vnt
*/
public class PeerClientInfo {
/**
* 虚拟IP
*/
public final int virtualIp;
/**
* 名称
*/
public final String name;
/**
* 是否在线
*/
public final boolean online;
/**
* 是否开启客户端加密,不同加密状态的不能通信
*/
public final boolean clientSecret;
public PeerClientInfo(int virtualIp, String name, boolean online, boolean clientSecret) {
this.virtualIp = virtualIp;
this.name = name;
this.online = online;
this.clientSecret = clientSecret;
}
public int getVirtualIp() {
return virtualIp;
}
public String getName() {
return name;
}
public boolean isOnline() {
return online;
}
public boolean isClientSecret() {
return clientSecret;
}
@Override
public String toString() {
return "PeerDeviceInfo{" +
"virtualIp=" + IpUtils.intToIpAddress(virtualIp) +
", name='" + name + '\'' +
", online=" + online +
", clientSecret=" + clientSecret +
'}';
}
}
@@ -1,5 +1,7 @@
package top.wherewego.vnt.jni.param;
import top.wherewego.vnt.jni.IpUtils;
/**
* 注册回调信息
*
@@ -9,40 +11,40 @@ public class RegisterInfo {
/**
* 虚拟IP
*/
public final String virtualIp;
public final int virtualIp;
/**
* 掩码
*/
public final String virtualNetmask;
public final int virtualNetmask;
/**
* 网关
*/
public final String virtualGateway;
public final int virtualGateway;
public RegisterInfo(String virtualIp, String virtualNetmask, String virtualGateway) {
public RegisterInfo(int virtualIp, int virtualNetmask, int virtualGateway) {
this.virtualIp = virtualIp;
this.virtualNetmask = virtualNetmask;
this.virtualGateway = virtualGateway;
}
public String getVirtualIp() {
public int getVirtualIp() {
return virtualIp;
}
public String getVirtualNetmask() {
public int getVirtualNetmask() {
return virtualNetmask;
}
public String getVirtualGateway() {
public int getVirtualGateway() {
return virtualGateway;
}
@Override
public String toString() {
return "RegisterInfo{" +
"virtualIp='" + virtualIp + '\'' +
", virtualNetmask='" + virtualNetmask + '\'' +
", virtualGateway='" + virtualGateway + '\'' +
"virtualIp='" + IpUtils.intToIpAddress(virtualIp) + '\'' +
", virtualNetmask='" + IpUtils.intToIpAddress(virtualNetmask) + '\'' +
", virtualGateway='" + IpUtils.intToIpAddress(virtualGateway) + '\'' +
'}';
}
}
+136 -21
View File
@@ -1,40 +1,87 @@
use std::sync::Arc;
use jni::objects::{GlobalRef, JString, JValue};
use jni::objects::{GlobalRef, JClass, JObject, JString, JValue};
use jni::{JNIEnv, JavaVM};
use spki::der::pem::LineEnding;
use spki::EncodePublicKey;
use vnt::handle::callback::ConnectInfo;
use vnt::{DeviceInfo, ErrorInfo, HandshakeInfo, RegisterInfo, VntCallback};
#[cfg(target_os = "android")]
use vnt::handle::callback::DeviceConfig;
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
use vnt::DeviceInfo;
use vnt::{ErrorInfo, HandshakeInfo, PeerClientInfo, RegisterInfo, VntCallback};
#[derive(Clone)]
pub struct CallBack {
jvm: Arc<JavaVM>,
this: GlobalRef,
connect_info_class: GlobalRef,
handshake_info_class: GlobalRef,
error_info_class: GlobalRef,
register_info_class: GlobalRef,
#[cfg(target_os = "android")]
device_config_class: GlobalRef,
peer_client_info_class: GlobalRef,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
device_info_class: GlobalRef,
}
unsafe impl Send for CallBack {}
fn find_class_global_ref(env: &mut JNIEnv, class: &str) -> jni::errors::Result<GlobalRef> {
let class = env.find_class(class)?;
env.new_global_ref(class)
}
impl CallBack {
pub fn new(jvm: JavaVM, this: GlobalRef) -> Self {
Self {
pub fn new(jvm: JavaVM, this: GlobalRef) -> jni::errors::Result<Self> {
let mut env = jvm.attach_current_thread_as_daemon()?;
let connect_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/ConnectInfo")?;
let handshake_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/HandshakeInfo")?;
let error_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/ErrorInfo")?;
let register_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/RegisterInfo")?;
#[cfg(target_os = "android")]
let device_config_class = crate::callback::find_class_global_ref(
&mut env,
"top/wherewego/vnt/jni/param/DeviceConfig",
)?;
let peer_client_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/PeerClientInfo")?;
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
let device_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/DeviceInfo")?;
Ok(Self {
jvm: Arc::new(jvm),
this,
}
connect_info_class,
handshake_info_class,
error_info_class,
register_info_class,
#[cfg(target_os = "android")]
device_config_class,
peer_client_info_class,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
device_info_class,
})
}
}
impl CallBack {
fn success0(&self) -> jni::errors::Result<()> {
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
let mut env = self.jvm.attach_current_thread_as_daemon()?;
env.call_method(&self.this, "success", "()V", &[])?;
Ok(())
}
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
fn create_tun0(&self, info: DeviceInfo) -> jni::errors::Result<()> {
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.device_info_class.as_raw()) };
let param = env.new_object(
"top/wherewego/vnt/jni/param/DeviceInfo",
class,
"(Ljava/lang/String;Ljava/lang/String;)V",
&[
JValue::Object(&env.new_string(info.name)?.into()),
@@ -50,9 +97,10 @@ impl CallBack {
Ok(())
}
fn connect0(&self, info: ConnectInfo) -> jni::errors::Result<()> {
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.connect_info_class.as_raw()) };
let param = env.new_object(
"top/wherewego/vnt/jni/param/ConnectInfo",
class,
"(JLjava/lang/String;)V",
&[
JValue::Long(info.count as _),
@@ -68,7 +116,7 @@ impl CallBack {
Ok(())
}
fn handshake0(&self, info: HandshakeInfo) -> jni::errors::Result<bool> {
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let public_key = if let Some(public_key) = info.public_key {
match public_key.to_public_key_pem(LineEnding::CRLF) {
Ok(public_key) => env.new_string(public_key)?,
@@ -85,8 +133,10 @@ impl CallBack {
} else {
JString::default()
};
let class = unsafe { JClass::from_raw(self.handshake_info_class.as_raw()) };
let param = env.new_object(
"top/wherewego/vnt/jni/param/HandshakeInfo",
class,
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
&[
JValue::Object(&public_key),
@@ -103,14 +153,15 @@ impl CallBack {
rs.z()
}
fn register0(&self, info: RegisterInfo) -> jni::errors::Result<bool> {
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.register_info_class.as_raw()) };
let param = env.new_object(
"top/wherewego/vnt/jni/param/RegisterInfo",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
class,
"(III)V",
&[
JValue::Object(&env.new_string(info.virtual_ip.to_string())?.into()),
JValue::Object(&env.new_string(info.virtual_netmask.to_string())?.into()),
JValue::Object(&env.new_string(info.virtual_gateway.to_string())?.into()),
JValue::Int(Into::<u32>::into(info.virtual_ip) as _),
JValue::Int(Into::<u32>::into(info.virtual_netmask) as _),
JValue::Int(Into::<u32>::into(info.virtual_gateway) as _),
],
)?;
let rs = env.call_method(
@@ -121,16 +172,66 @@ impl CallBack {
)?;
rs.z()
}
#[cfg(target_os = "android")]
fn generate_tun0(&self, info: DeviceConfig) -> jni::errors::Result<u32> {
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.device_config_class.as_raw()) };
let param = env.new_object(
class,
"(IIII)V",
&[
JValue::Int(Into::<u32>::into(info.virtual_ip) as _),
JValue::Int(Into::<u32>::into(info.virtual_netmask) as _),
JValue::Int(Into::<u32>::into(info.virtual_gateway) as _),
JValue::Int(Into::<u32>::into(info.virtual_network) as _),
],
)?;
let rs = env.call_method(
&self.this,
"generateTun",
"(Ltop/wherewego/vnt/jni/param/DeviceConfig;)I",
&[JValue::Object(&param)],
)?;
rs.i().map(|v| v as _)
}
fn peer_client_list0(&self, info_vec: Vec<PeerClientInfo>) -> jni::errors::Result<()> {
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.peer_client_info_class.as_raw()) };
let object_array = env.new_object_array(info_vec.len() as _, &class, JObject::null())?;
for (index, info) in info_vec.into_iter().enumerate() {
let param = env.new_object(
&class,
"(ILjava/lang/String;ZZ)V",
&[
JValue::Int(Into::<u32>::into(info.virtual_ip) as _),
JValue::Object(&env.new_string(info.name)?.into()),
JValue::Bool(info.status.is_online() as _),
JValue::Bool(info.client_secret as _),
],
)?;
env.set_object_array_element(&object_array, index as _, &param)?;
}
env.call_method(
&self.this,
"peerClientList",
"([Ltop/wherewego/vnt/jni/param/PeerClientInfo;)V",
&[JValue::Object(&object_array)],
)?;
Ok(())
}
fn error0(&self, info: ErrorInfo) -> jni::errors::Result<()> {
let code: u8 = info.code.into();
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.error_info_class.as_raw()) };
let msg = if let Some(msg) = info.msg {
env.new_string(msg)?
} else {
JString::default()
};
let param = env.new_object(
"top/wherewego/vnt/jni/param/ErrorInfo",
class,
"(ILjava/lang/String;)V",
&[JValue::Int(code as _), JValue::Object(&msg.into())],
)?;
@@ -143,7 +244,7 @@ impl CallBack {
Ok(())
}
fn stop0(&self) -> jni::errors::Result<()> {
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
let mut env = self.jvm.attach_current_thread_as_daemon()?;
env.call_method(&self.this, "stop", "()V", &[])?;
Ok(())
}
@@ -155,6 +256,7 @@ impl VntCallback for CallBack {
log::warn!("success {:?}", e);
}
}
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
fn create_tun(&self, info: DeviceInfo) {
if let Err(e) = self.create_tun0(info) {
log::warn!("create_tun {:?}", e);
@@ -180,6 +282,19 @@ impl VntCallback for CallBack {
false
})
}
#[cfg(target_os = "android")]
fn generate_tun(&self, info: DeviceConfig) -> u32 {
self.generate_tun0(info).unwrap_or_else(|e| {
log::warn!("generate_tun {:?}", e);
0
})
}
fn peer_client_list(&self, info: Vec<PeerClientInfo>) {
if let Err(e) = self.peer_client_list0(info) {
log::warn!("peer_client_list {:?}", e);
}
}
fn error(&self, info: ErrorInfo) {
if let Err(e) = self.error0(info) {
-4
View File
@@ -107,8 +107,6 @@ pub fn new_config(env: &mut JNIEnv, config: JObject) -> Result<Config, Error> {
};
#[cfg(not(target_os = "android"))]
let device_name = to_string(env, &config, "deviceName")?;
#[cfg(target_os = "android")]
let device_fd = env.get_field(&config, "deviceFd", "I")?.i()? as i32;
let config = match Config::new(
#[cfg(any(target_os = "windows", target_os = "linux"))]
tap,
@@ -134,8 +132,6 @@ pub fn new_config(env: &mut JNIEnv, config: JObject) -> Result<Config, Error> {
first_latency,
#[cfg(not(target_os = "android"))]
device_name,
#[cfg(target_os = "android")]
device_fd,
UseChannelType::from_str(&use_channel.unwrap_or_default()).unwrap_or_default(),
packet_loss_rate,
packet_delay,
+16 -11
View File
@@ -2,7 +2,7 @@ use std::ptr;
use jni::errors::Error;
use jni::objects::{JClass, JObject, JValue};
use jni::sys::{jbyte, jint, jlong, jobject, jobjectArray, jsize};
use jni::sys::{jint, jlong, jobject, jobjectArray, jsize};
use jni::JNIEnv;
use vnt::channel::Route;
@@ -30,7 +30,13 @@ pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_new0(
} else {
return 0;
};
let vnt_util = match Vnt::new(config, CallBack::new(jvm, call_back)) {
let call_back = match CallBack::new(jvm, call_back) {
Ok(call_back) => call_back,
Err(_) => {
return 0;
}
};
let vnt_util = match Vnt::new(config, call_back) {
Ok(vnt_util) => vnt_util,
Err(e) => {
env.throw_new(
@@ -58,6 +64,7 @@ pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_stop0(
let vnt = raw_vnt as *mut Vnt;
let _ = (&*vnt).stop();
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_wait0(
_env: JNIEnv,
@@ -90,7 +97,7 @@ pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_list0(
let arr = match env.new_object_array(
list.len() as jsize,
"top/wherewego/vnt/jni/PeerDeviceInfo",
"top/wherewego/vnt/jni/PeerRouteInfo",
JObject::null(),
) {
Ok(arr) => arr,
@@ -131,16 +138,14 @@ pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_list0(
}
fn route_parse(env: &mut JNIEnv, route: Route) -> Result<jobject, Error> {
let address = route.addr.to_string();
let metric = route.metric;
let rt = route.rt;
let rs = env.new_object(
"top/wherewego/vnt/jni/Route",
"(Ljava/lang/String;BI)V",
"(ZLjava/lang/String;BI)V",
&[
JValue::Object(&env.new_string(address)?.into()),
JValue::Byte(metric as jbyte),
JValue::Int(rt as jint),
JValue::Bool(route.is_tcp as _),
JValue::Object(&env.new_string(route.addr.to_string())?.into()),
JValue::Byte(route.metric as _),
JValue::Int(route.rt as _),
],
)?;
Ok(rs.as_raw())
@@ -155,7 +160,7 @@ fn peer_device_info_parse(
let name = peer.name.to_string();
let status = format!("{:?}", peer.status);
let rs = env.new_object(
"top/wherewego/vnt/jni/PeerDeviceInfo",
"top/wherewego/vnt/jni/PeerRouteInfo",
"(ILjava/lang/String;Ljava/lang/String;Ltop/wherewego/vnt/jni/Route;)V",
&[
JValue::Int(virtual_ip as jint),
+1 -1
View File
@@ -31,7 +31,7 @@ openssl-sys = { git = "https://github.com/lbl8603/rust-openssl" ,optional = true
libsm = {git="https://github.com/lbl8603/libsm" ,optional = true}
mio = {version = "0.8.10",features = ["os-poll","net"]}
crossbeam-queue = "0.3.11"
[target.'cfg(target_os = "windows")'.dependencies]
libloading = "0.8.0"
+39 -26
View File
@@ -7,7 +7,7 @@ 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::Context;
@@ -22,14 +22,15 @@ use crate::external_route::{AllowExternalRoute, ExternalRoute};
use crate::handle::handshaker::Handshake;
use crate::handle::maintain::PunchReceiver;
use crate::handle::recv_data::RecvDataHandler;
use crate::handle::{
maintain, tun_tap, BaseConfigInfo, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo,
};
use crate::handle::{maintain, BaseConfigInfo, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo};
use crate::nat::NatTest;
use crate::tun_tap_device::tun_create_helper::{DeviceAdapter, TunDeviceHelper};
use crate::util::{
Scheduler, SingleU64Adder, StopManager, U64Adder, WatchSingleU64Adder, WatchU64Adder,
};
use crate::{nat, tun_tap_device, DeviceInfo, VntCallback};
use crate::{nat, VntCallback};
#[cfg(not(target_os = "android"))]
use crate::{tun_tap_device, DeviceInfo};
#[derive(Clone)]
pub struct Vnt {
@@ -113,10 +114,14 @@ impl Vnt {
tcp_port,
);
// 虚拟网卡
let device = tun_tap_device::create_device(&config)?;
let tun_info = DeviceInfo::new(device.name()?, device.version()?);
callback.create_tun(tun_info);
// pc上先创建虚拟网卡
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
let device = {
let device = tun_tap_device::create_device(&config)?;
let tun_info = DeviceInfo::new(device.name()?, device.version()?);
callback.create_tun(tun_info);
device
};
// 服务停止管理器
let stop_manager = {
let callback = callback.clone();
@@ -146,13 +151,33 @@ impl Vnt {
U64Adder::with_capacity(config.ports.as_ref().map(|v| v.len()).unwrap_or_default() + 8);
let down_count_watcher = down_counter.watch();
let handshake = Handshake::new(rsa_cipher.clone());
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(),
);
#[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);
let handler = RecvDataHandler::new(
#[cfg(feature = "server_encrypt")]
rsa_cipher,
server_cipher.clone(),
client_cipher.clone(),
current_device.clone(),
device.clone(),
device_adapter,
device_list.clone(),
config_info.clone(),
nat_test.clone(),
@@ -177,22 +202,10 @@ impl Vnt {
config.tcp,
tcp_socket_sender.clone(),
);
let up_counter = SingleU64Adder::new();
let up_count_watcher = up_counter.watch();
tun_tap::tun_handler::start(
stop_manager.clone(),
context.clone(),
device.clone(),
current_device.clone(),
external_route,
#[cfg(feature = "ip_proxy")]
proxy_map,
client_cipher.clone(),
server_cipher.clone(),
config.parallel,
up_counter,
device_list.clone(),
)?;
#[cfg(not(target_os = "android"))]
tun_helper.start(device)?;
maintain::idle_gateway(
&scheduler,
context.clone(),
-5
View File
@@ -36,8 +36,6 @@ pub struct Config {
pub first_latency: bool,
#[cfg(not(target_os = "android"))]
pub device_name: Option<String>,
#[cfg(target_os = "android")]
pub device_fd: i32,
pub use_channel_type: UseChannelType,
//控制丢包率
pub packet_loss_rate: Option<f64>,
@@ -68,7 +66,6 @@ impl Config {
ports: Option<Vec<u16>>,
first_latency: bool,
#[cfg(not(target_os = "android"))] device_name: Option<String>,
#[cfg(target_os = "android")] device_fd: i32,
use_channel_type: UseChannelType,
packet_loss_rate: Option<f64>,
packet_delay: u32,
@@ -113,8 +110,6 @@ impl Config {
first_latency,
#[cfg(not(target_os = "android"))]
device_name,
#[cfg(target_os = "android")]
device_fd,
use_channel_type,
packet_loss_rate,
packet_delay,
+89
View File
@@ -1,21 +1,25 @@
use crate::handle::PeerDeviceStatus;
#[cfg(feature = "server_encrypt")]
use rsa::RsaPublicKey;
use std::fmt::{Display, Formatter};
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
#[derive(Debug)]
pub struct DeviceInfo {
pub name: String,
pub version: String,
}
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
impl Display for DeviceInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!("name={} ,version={}", self.name, self.version))
}
}
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
impl DeviceInfo {
pub fn new(name: String, version: String) -> Self {
return Self { name, version };
@@ -68,6 +72,7 @@ impl Display for HandshakeInfo {
f.write_str(&format!("server version={}", self.version))
}
}
#[cfg(feature = "server_encrypt")]
impl HandshakeInfo {
pub fn new(public_key: RsaPublicKey, finger: String, version: String) -> Self {
@@ -85,6 +90,7 @@ impl HandshakeInfo {
}
}
}
#[cfg(not(feature = "server_encrypt"))]
impl HandshakeInfo {
pub fn new_no_secret(version: String) -> Self {
@@ -183,11 +189,89 @@ impl Into<u8> for ErrorType {
}
}
#[cfg(target_os = "android")]
#[derive(Debug)]
pub struct DeviceConfig {
//本机虚拟IP
pub virtual_ip: Ipv4Addr,
//子网掩码
pub virtual_netmask: Ipv4Addr,
//虚拟网关
pub virtual_gateway: Ipv4Addr,
//虚拟网段
pub virtual_network: Ipv4Addr,
// 额外的路由
pub external_route: Vec<(Ipv4Addr, Ipv4Addr)>,
}
#[cfg(target_os = "android")]
impl DeviceConfig {
pub fn new(
virtual_ip: Ipv4Addr,
virtual_netmask: Ipv4Addr,
virtual_gateway: Ipv4Addr,
virtual_network: Ipv4Addr,
external_route: Vec<(Ipv4Addr, Ipv4Addr)>,
) -> Self {
Self {
virtual_ip,
virtual_netmask,
virtual_gateway,
virtual_network,
external_route,
}
}
}
#[cfg(target_os = "android")]
impl Display for DeviceConfig {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!(
"ip={} ,netmask={} ,gateway={}, external_route={:?}",
self.virtual_ip, self.virtual_netmask, self.virtual_gateway, self.external_route
))
}
}
#[derive(Debug)]
pub struct PeerClientInfo {
pub virtual_ip: Ipv4Addr,
pub name: String,
pub status: PeerDeviceStatus,
pub client_secret: bool,
}
impl PeerClientInfo {
pub fn new(
virtual_ip: Ipv4Addr,
name: String,
status: PeerDeviceStatus,
client_secret: bool,
) -> Self {
Self {
virtual_ip,
name,
status,
client_secret,
}
}
}
impl Display for PeerClientInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!(
"ip={} ,name={} ,status={:?}, client_secret={}",
self.virtual_ip, self.name, self.status, self.client_secret
))
}
}
pub trait VntCallback: Clone + Send + Sync + 'static {
/// 启动成功
fn success(&self) {}
/// 创建网卡的信息
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
fn create_tun(&self, _info: DeviceInfo) {}
/// 连接
fn connect(&self, _info: ConnectInfo) {}
@@ -199,6 +283,11 @@ pub trait VntCallback: Clone + Send + Sync + 'static {
fn register(&self, _info: RegisterInfo) -> bool {
true
}
#[cfg(target_os = "android")]
fn generate_tun(&self, _info: DeviceConfig) -> u32 {
0
}
fn peer_client_list(&self, _info: Vec<PeerClientInfo>) {}
/// 异常信息
fn error(&self, _info: ErrorInfo) {}
/// 服务停止
+216
View File
@@ -0,0 +1,216 @@
use std::net::Ipv4Addr;
use std::{io, process, thread};
use std::sync::Arc;
use std::sync::mpsc::{Receiver, SyncSender, TrySendError};
use crossbeam_utils::atomic::AtomicCell;
use tun::Device;
use tun::device::IFace;
use crate::handle::callback::DeviceConfig;
use crate::protocol::NetPacket;
use crate::util::{BufBlock, BufPool, GroupSyncSender, StopManager};
pub struct TunAdapter {
#[cfg(any(target_os = "windows", target_os = "linux"))] is_tap: bool,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] device_name: Option<String>,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] mtu: u32,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] route_record: Vec<(Ipv4Addr, Ipv4Addr)>,
device: Option<Arc<Device>>,
buf_pool: BufPool,
stop_manager: StopManager,
receiver_stage: Option<Receiver<NetPacket<BufBlock>>>,
sender_stage: Option<SyncSender<NetPacket<BufBlock>>>,
}
impl TunAdapter {
pub fn new(
#[cfg(any(target_os = "windows", target_os = "linux"))] is_tap: bool,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] device_name: Option<String>,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] mtu: u32,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] route_record: Vec<(Ipv4Addr, Ipv4Addr)>,
buf_pool: BufPool,
stop_manager: StopManager,
receiver: Receiver<NetPacket<BufBlock>>,
sender: SyncSender<NetPacket<BufBlock>>,
)->Self{
Self{
#[cfg(any(target_os = "windows", target_os = "linux"))] is_tap,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] device_name,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] mtu,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] route_record,
device: None,
buf_pool,
stop_manager,
receiver_stage: Some(receiver),
sender_stage: Some(sender),
}
}
}
impl TunAdapter {
pub fn device(&mut self, #[cfg(target_os = "android")] device_fd: u32) -> io::Result<()> {
if self.device.is_some() {
return Ok(());
} else {
let device = create_device(#[cfg(any(target_os = "windows", target_os = "linux"))] self.is_tap,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] self.device_name.clone(),
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] self.mtu,
#[cfg(target_os = "android")] device_fd, )?;
let device = Arc::new(device);
self.device.replace(device);
{
let device = device.clone();
let buf_pool = self.buf_pool.clone();
let stop_manager = self.stop_manager.clone();
let sender = self.sender_stage.take().unwrap();
thread::Builder::new().name("tun-read".into()).spawn(move || {
loop {
let mut buf_block = buf_pool.alloc();
#[cfg(not(target_os = "macos"))]
let start = 12;
#[cfg(target_os = "macos")]
let start = 8;
match device.read(&mut buf_block.as_mut()[start..]) {
Ok(len) => {
buf_block.as_mut()[..12].fill(0);
buf_block.set_data_len(start + len);
if let Err(e) = sender.try_send(buf_block) {
match e {
TrySendError::Full(_) => {
log::warn!("发生丢包");
}
TrySendError::Disconnected(_) => {
break;
}
}
}
}
Err(e) => {
log::warn!("{:?}",e);
break;
}
}
}
stop_manager.stop();
}).unwrap();
}
{
let device = device.clone();
let stop_manager = self.stop_manager.clone();
let receiver = self.receiver_stage.take().unwrap();
thread::Builder::new().name("tun-write".into()).spawn(move || {
while let Ok(data) = receiver.recv() {
if let Err(e) = device.write(data.as_data()) {
log::warn!("写入网卡失败:{}",e);
break;
}
}
stop_manager.stop();
}).unwrap();
}
}
}
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
pub fn change_ip(&mut self, info: DeviceConfig) -> io::Result<()> {
let device = if let Some(device) = &self.device {
device
} else {
return Err(io::Error::new(io::ErrorKind::NotFound, "IFace"));
};
device.set_ip(info.virtual_ip, info.virtual_netmask)?;
for (dest, mask) in self.route_record.drain(..) {
if let Err(e) = self.device.delete_route(dest, mask) {
log::warn!("删除路由失败 ={:?}", e);
}
}
if let Err(e) = device.add_route(info.virtual_network, info.virtual_netmask, 1)
{
log::warn!("添加默认路由失败 ={:?}", e);
} else {
self.route_record.push((info.virtual_network, info.virtual_netmask));
}
if let Err(e) = device
.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, 1)
{
log::warn!("添加广播路由失败 ={:?}", e);
} else {
self.route_record.push((Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST));
}
if let Err(e) = device.add_route(
Ipv4Addr::from([224, 0, 0, 0]),
Ipv4Addr::from([240, 0, 0, 0]),
1,
) {
log::warn!("添加组播路由失败 ={:?}", e);
} else {
self.route_record.push((
Ipv4Addr::from([224, 0, 0, 0]),
Ipv4Addr::from([240, 0, 0, 0]),
));
}
for (dest, mask) in info.external_route {
if let Err(e) = self.device.add_route(dest, mask, 1) {
log::warn!("添加路由失败 ={:?}", e);
} else {
self.route_record.push((dest, mask));
}
}
Ok(())
}
}
#[cfg(any(target_os = "windows", target_os = "linux"))]
const DEFAULT_TUN_NAME: &str = "vnt-tun";
#[cfg(any(target_os = "windows", target_os = "linux"))]
const DEFAULT_TAP_NAME: &str = "vnt-tap";
pub fn create_device(#[cfg(any(target_os = "windows", target_os = "linux"))] is_tap: bool,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] device_name: Option<String>,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] mtu: u32,
#[cfg(target_os = "android")] device_fd: u32, ) -> io::Result<Device> {
#[cfg(any(target_os = "windows", target_os = "linux"))]
let default_name: &str = if is_tap {
DEFAULT_TAP_NAME
} else {
DEFAULT_TUN_NAME
};
#[cfg(target_os = "linux")]
let device = {
let device_name = device_name
.unwrap_or(default_name.to_string());
if &device_name == default_name {
delete_device(default_name);
}
Device::new(Some(device_name), is_tap)?
};
#[cfg(target_os = "macos")]
let device = Device::new(device_name)?;
#[cfg(target_os = "windows")]
let device = Device::new(
device_name
.unwrap_or(default_name.to_string()),
is_tap,
)?;
#[cfg(target_os = "android")]
let device = Device::new(device_fd as _)?;
#[cfg(not(target_os = "android"))]
device.set_mtu(mtu)?;
Ok(device)
}
#[cfg(target_os = "linux")]
fn delete_device(name: &str) {
// 删除默认网卡,此操作有风险,后续可能去除
use std::process::Command;
let cmd = format!("ip link delete {}", name);
let delete_tun = Command::new("sh")
.arg("-c")
.arg(&cmd)
.output()
.expect("sh exec error!");
if !delete_tun.status.success() {
log::info!("{},{:?}",cmd, delete_tun);
}
}
+242
View File
@@ -0,0 +1,242 @@
use std::{io, thread};
use std::net::Ipv4Addr;
use std::sync::Arc;
use std::sync::mpsc::Receiver;
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::Mutex;
use packet::icmp::icmp::IcmpPacket;
use packet::icmp::Kind;
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use packet::ip::ipv4::protocol::Protocol;
use crate::channel::context::Context;
use crate::cipher::Cipher;
use crate::external_route::ExternalRoute;
use crate::handle::{check_dest, CurrentDeviceInfo, PeerDeviceInfo};
use crate::ip_proxy::{IpProxyMap, ProxyHandler};
use crate::protocol;
use crate::protocol::{ip_turn_packet, MAX_TTL, NetPacket, Version};
use crate::protocol::body::ENCRYPTION_RESERVED;
use crate::protocol::ip_turn_packet::BroadcastPacket;
use crate::util::{BufBlock, SingleU64Adder, StopManager};
pub mod adapter;
pub fn start(
receivers: Vec<Receiver<BufBlock>>,
context: Context,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
#[cfg(feature = "ip_proxy")] ip_proxy_map: Option<IpProxyMap>,
client_cipher: Cipher,
server_cipher: Cipher,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
) -> io::Result<()> {
for (index,receiver) in receivers.into_iter().enumerate() {
let context = context.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!("IFace-{}", index))
.spawn(move || {
while let Ok(mut data) = receiver.recv() {
let data_len = data.data_len();
let buf = data.as_start_mut();
if data_len==0{
break;
}
match handle(
&context,
buf,
data_len,
current_device.load(),
&ip_route,
#[cfg(feature = "ip_proxy")]
&ip_proxy_map,
&client_cipher,
&server_cipher,
&device_list,
) {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
}
})?;
}
Ok(())
}
/// 实现一个原地发送,必须保证是如下结构
/// |12字节开头|ip报文|至少1024字节结尾|
///
pub fn handle(
context: &Context,
buf: &mut [u8],
data_len: usize, //数据总长度=12+ip包长度
current_device: CurrentDeviceInfo,
ip_route: &ExternalRoute,
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
client_cipher: &Cipher,
server_cipher: &Cipher,
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
) -> io::Result<()> {
let ipv4_packet = IpV4Packet::new(&buf[12..data_len])?;
let protocol = ipv4_packet.protocol();
let src_ip = ipv4_packet.source_ip();
let mut dest_ip = ipv4_packet.destination_ip();
let mut net_packet = NetPacket::new0(data_len, buf)?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(protocol::Protocol::IpTurn);
net_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4.into());
net_packet.first_set_ttl(6);
net_packet.set_source(src_ip);
net_packet.set_destination(dest_ip);
if dest_ip == current_device.virtual_gateway {
// 发到网关的加密方式不一样,要单独处理
if protocol == Protocol::Icmp {
net_packet.set_gateway_flag(true);
server_cipher.encrypt_ipv4(&mut net_packet)?;
context.send_default(net_packet.buffer(), current_device.connect_server)?;
}
return Ok(());
}
if dest_ip.is_multicast() {
//当作广播处理
dest_ip = Ipv4Addr::BROADCAST;
net_packet.set_destination(Ipv4Addr::BROADCAST);
}
if dest_ip.is_broadcast() || current_device.broadcast_ip == dest_ip {
// 广播 发送到直连目标
client_cipher.encrypt_ipv4(&mut net_packet)?;
broadcast(
server_cipher,
context,
&mut net_packet,
&current_device,
device_list,
)?;
return Ok(());
}
if !check_dest(
dest_ip,
current_device.virtual_netmask,
current_device.virtual_network,
) {
if let Some(r_dest_ip) = ip_route.route(&dest_ip) {
//路由的目标不能是自己
if r_dest_ip == src_ip {
return Ok(());
}
//需要修改目的地址
dest_ip = r_dest_ip;
net_packet.set_destination(r_dest_ip);
} else {
return Ok(());
}
}
#[cfg(feature = "ip_proxy")]
if let Some(proxy_map) = proxy_map {
let mut ipv4_packet = IpV4Packet::new(net_packet.payload_mut())?;
proxy_map.send_handle(&mut ipv4_packet)?;
}
client_cipher.encrypt_ipv4(&mut net_packet)?;
context.send_ipv4_by_id(
net_packet.buffer(),
&dest_ip,
current_device.connect_server,
current_device.status.online(),
)
}
fn broadcast(
server_cipher: &Cipher,
sender: &Context,
net_packet: &mut NetPacket<&mut [u8]>,
current_device: &CurrentDeviceInfo,
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
) -> io::Result<()> {
let list: Vec<Ipv4Addr> = device_list
.lock()
.1
.iter()
.filter(|info| info.status.is_online())
.map(|info| info.virtual_ip)
.collect();
const MAX_COUNT: usize = 8;
let mut p2p_ips = Vec::with_capacity(8);
let mut relay_ips = Vec::with_capacity(8);
let mut overflow = false;
for (index, peer_ip) in list.into_iter().enumerate() {
if index > MAX_COUNT {
overflow = true;
break;
}
if let Some(route) = sender.route_table.route_one_p2p(&peer_ip) {
if sender
.send_by_key(net_packet.buffer(), route.route_key())
.is_ok()
{
p2p_ips.push(peer_ip);
continue;
}
}
relay_ips.push(peer_ip);
}
if !overflow && relay_ips.is_empty() {
//全部p2p,不需要服务器中转
return Ok(());
}
if p2p_ips.is_empty() {
//都没有p2p则直接由服务器转发
if current_device.status.online() {
sender.send_default(net_packet.buffer(), current_device.connect_server)?;
}
return Ok(());
}
if !overflow && relay_ips.len() == 2 {
// 如果转发的ip数不多就直接发
for peer_ip in relay_ips {
//非直连的广播要改变目的地址,不然服务端收到了会再次广播
net_packet.set_destination(peer_ip);
sender.send_ipv4_by_id(
net_packet.buffer(),
&peer_ip,
current_device.connect_server,
current_device.status.online(),
)?;
}
return Ok(());
}
if current_device.status.offline() {
//离线的不再转发
return Ok(());
}
let buf = vec![0u8; 12 + 1 + p2p_ips.len() * 4 + net_packet.data_len() + ENCRYPTION_RESERVED];
//剩余的发送到服务端,需要告知哪些已发送过
let mut server_packet = NetPacket::new_encrypt(buf)?;
server_packet.set_version(Version::V1);
server_packet.set_gateway_flag(true);
server_packet.first_set_ttl(MAX_TTL);
server_packet.set_source(net_packet.source());
//使用对应的目的地址
server_packet.set_destination(net_packet.destination());
server_packet.set_protocol(protocol::Protocol::IpTurn);
server_packet.set_transport_protocol(ip_turn_packet::Protocol::Ipv4Broadcast.into());
let mut broadcast = BroadcastPacket::unchecked(server_packet.payload_mut());
broadcast.set_address(&p2p_ips)?;
broadcast.set_data(net_packet.buffer())?;
server_cipher.encrypt_ipv4(&mut server_packet)?;
sender.send_default(server_packet.buffer(), current_device.connect_server)
}
+7 -8
View File
@@ -1,16 +1,13 @@
use parking_lot::RwLock;
use protobuf::Message;
use std::collections::HashMap;
use std::io;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::sync::Arc;
use parking_lot::RwLock;
use protobuf::Message;
use packet::icmp::{icmp, Kind};
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use tun::device::IFace;
use tun::Device;
use crate::channel::context::Context;
use crate::channel::punch::NatInfo;
@@ -29,11 +26,13 @@ use crate::protocol::control_packet::ControlPacket;
use crate::protocol::{
control_packet, ip_turn_packet, other_turn_packet, NetPacket, Protocol, Version, MAX_TTL,
};
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
use tun::device::IFace;
/// 处理来源于客户端的包
#[derive(Clone)]
pub struct ClientPacketHandler {
device: Arc<Device>,
device: DeviceAdapter,
client_cipher: Cipher,
punch_sender: PunchSender,
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
@@ -45,7 +44,7 @@ pub struct ClientPacketHandler {
impl ClientPacketHandler {
pub fn new(
device: Arc<Device>,
device: DeviceAdapter,
client_cipher: Cipher,
punch_sender: PunchSender,
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
+2 -3
View File
@@ -6,8 +6,6 @@ use std::{io, thread};
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::{Mutex, RwLock};
use tun::Device;
use crate::channel::context::Context;
use crate::channel::handler::RecvChannelHandler;
use crate::channel::punch::NatInfo;
@@ -27,6 +25,7 @@ use crate::handle::{BaseConfigInfo, CurrentDeviceInfo, PeerDeviceInfo, SELF_IP};
use crate::ip_proxy::IpProxyMap;
use crate::nat::NatTest;
use crate::protocol::NetPacket;
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
use crate::util::U64Adder;
mod client;
@@ -56,7 +55,7 @@ impl<Call: VntCallback> RecvDataHandler<Call> {
server_cipher: Cipher,
client_cipher: Cipher,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
device: Arc<Device>,
device: DeviceAdapter,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
config_info: BaseConfigInfo,
nat_test: NatTest,
+45 -9
View File
@@ -11,8 +11,6 @@ use protobuf::Message;
use packet::icmp::{icmp, Kind};
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use tun::device::IFace;
use tun::Device;
use crate::channel::context::Context;
use crate::channel::{Route, RouteKey};
@@ -29,12 +27,15 @@ use crate::handle::{
registrar, BaseConfigInfo, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo, GATEWAY_IP,
};
use crate::nat::NatTest;
use crate::proto;
use crate::proto::message::{DeviceList, HandshakeResponse, RegistrationResponse};
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, Version, MAX_TTL};
use crate::tun_tap_device::tun_create_helper::DeviceAdapter;
use crate::{proto, PeerClientInfo};
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
use tun::device::IFace;
/// 处理来源于服务端的包
#[derive(Clone)]
@@ -43,13 +44,14 @@ pub struct ServerPacketHandler<Call> {
rsa_cipher: Arc<Mutex<Option<RsaCipher>>>,
server_cipher: Cipher,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
device: Arc<Device>,
device: DeviceAdapter,
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,
@@ -60,7 +62,7 @@ impl<Call> ServerPacketHandler<Call> {
#[cfg(feature = "server_encrypt")] rsa_cipher: Arc<Mutex<Option<RsaCipher>>>,
server_cipher: Cipher,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
device: Arc<Device>,
device: DeviceAdapter,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
config_info: BaseConfigInfo,
nat_test: NatTest,
@@ -80,6 +82,7 @@ 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,
@@ -299,6 +302,31 @@ 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(
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 {
let device = Arc::new(tun::Device::new(device_fd as _)?);
if let Err(e) = self.device.start(device) {
self.callback.error(ErrorInfo::new_msg(
ErrorType::Unknown,
format!("{:?}", e),
));
}
}
}
#[cfg(not(target_os = "android"))]
{
if let Err(e) = self.device.set_ip(virtual_ip, virtual_netmask) {
@@ -393,10 +421,18 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
)
})
.collect();
let mut dev = self.device_list.lock();
//这里可能会收到旧的消息,但是随着时间推移总会收到新的
dev.0 = epoch;
dev.1 = ip_list;
{
let mut dev = self.device_list.lock();
//这里可能会收到旧的消息,但是随着时间推移总会收到新的
dev.0 = epoch;
dev.1 = ip_list.clone();
}
self.callback.peer_client_list(
ip_list
.into_iter()
.map(|v| PeerClientInfo::new(v.virtual_ip, v.name, v.status, v.client_secret))
.collect(),
);
}
fn register(&self, current_device: &CurrentDeviceInfo, context: &Context) -> io::Result<()> {
if current_device.status.online() {
+2 -2
View File
@@ -87,14 +87,14 @@ pub fn start(
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
) -> io::Result<()> {
let worker = {
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "android"))]
let current_device = current_device.clone();
let device = device.clone();
stop_manager.add_listener("tun_device".into(), move || {
if let Err(e) = device.shutdown() {
log::warn!("{:?}", e);
}
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "android"))]
{
let ip = current_device.load().virtual_ip;
if let Ok(udp) = std::net::UdpSocket::bind("0.0.0.0:0") {
+1 -1
View File
@@ -13,4 +13,4 @@ pub mod protocol;
pub mod tun_tap_device;
pub mod util;
pub use handle::callback::{DeviceInfo, ErrorInfo, HandshakeInfo, RegisterInfo, VntCallback};
pub use handle::callback::*;
+64
View File
@@ -0,0 +1,64 @@
use std::io;
use std::sync::Arc;
use tun::device::IFace;
use tun::Device;
#[cfg(any(target_os = "windows", target_os = "linux"))]
const DEFAULT_TUN_NAME: &str = "vnt-tun";
#[cfg(any(target_os = "windows", target_os = "linux"))]
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>> {
#[cfg(any(target_os = "windows", target_os = "linux"))]
let default_name: &str = if config.tap {
DEFAULT_TAP_NAME
} else {
DEFAULT_TUN_NAME
};
#[cfg(target_os = "linux")]
let device = {
let device_name = config
.device_name
.clone()
.unwrap_or(default_name.to_string());
if &device_name == default_name {
delete_device(default_name);
}
Arc::new(Device::new(Some(device_name), config.tap)?)
};
#[cfg(target_os = "macos")]
let device = Arc::new(Device::new(config.device_name.clone())?);
#[cfg(target_os = "windows")]
let device = Arc::new(Device::new(
config
.device_name
.clone()
.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)?;
Ok(device)
}
#[cfg(target_os = "linux")]
fn delete_device(name: &str) {
// 删除默认网卡,此操作有风险,后续可能去除
use std::process::Command;
let cmd = format!("ip link delete {}", name);
let delete_tun = Command::new("sh")
.arg("-c")
.arg(&cmd)
.output()
.expect("sh exec error!");
if !delete_tun.status.success() {
log::warn!("删除网卡失败:{:?}", delete_tun);
}
}
+5 -69
View File
@@ -1,70 +1,6 @@
use std::io;
use std::sync::Arc;
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
pub use create_device::create_device;
use tun::device::IFace;
use tun::Device;
use crate::core::Config;
#[cfg(any(target_os = "windows", target_os = "linux"))]
const DEFAULT_TUN_NAME: &str = "vnt-tun";
#[cfg(any(target_os = "windows", target_os = "linux"))]
const DEFAULT_TAP_NAME: &str = "vnt-tap";
pub fn create_device(config: &Config) -> io::Result<Arc<Device>> {
#[cfg(any(target_os = "windows", target_os = "linux"))]
let default_name: &str = if config.tap {
DEFAULT_TAP_NAME
} else {
DEFAULT_TUN_NAME
};
#[cfg(target_os = "linux")]
let device = {
let device_name = config
.device_name
.clone()
.unwrap_or(default_name.to_string());
if &device_name == default_name {
delete_device(default_name);
}
Arc::new(Device::new(Some(device_name), config.tap)?)
};
#[cfg(target_os = "macos")]
let device = Arc::new(Device::new(config.device_name.clone())?);
#[cfg(target_os = "windows")]
let device = Arc::new(Device::new(
config
.device_name
.clone()
.unwrap_or(default_name.to_string()),
config.tap,
)?);
#[cfg(target_os = "android")]
let device = Arc::new(Device::new(config.device_fd as _)?);
#[cfg(not(target_os = "android"))]
{
let mtu = config.mtu.unwrap_or_else(|| {
if config.password.is_none() {
1450
} else {
1410
}
});
device.set_mtu(mtu)?;
}
Ok(device)
}
#[cfg(target_os = "linux")]
fn delete_device(name: &str) {
// 删除默认网卡,此操作有风险,后续可能去除
use std::process::Command;
let cmd = format!("ip link delete {}", name);
let delete_tun = Command::new("sh")
.arg("-c")
.arg(&cmd)
.output()
.expect("sh exec error!");
if !delete_tun.status.success() {
log::warn!("删除网卡失败:{:?}", delete_tun);
}
}
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
mod create_device;
pub mod tun_create_helper;
+134
View File
@@ -0,0 +1,134 @@
use std::io;
use std::sync::Arc;
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::Mutex;
use tun::Device;
use crate::channel::context::Context;
use crate::cipher::Cipher;
use crate::external_route::ExternalRoute;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
use crate::ip_proxy::IpProxyMap;
use crate::util::{SingleU64Adder, StopManager};
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
#[repr(transparent)]
#[derive(Clone)]
pub struct DeviceAdapter {
tun: Arc<Device>,
}
impl DeviceAdapter {
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
pub fn new(tun: Arc<Device>) -> Self {
Self { tun }
}
#[cfg(target_os = "android")]
pub fn new(tun_device_helper: TunDeviceHelper) -> Self {
Self {
tun: Arc::new(Mutex::new(None)),
tun_device_helper,
}
}
}
#[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<Mutex<Option<Arc<Device>>>>,
tun_device_helper: TunDeviceHelper,
}
#[cfg(target_os = "android")]
impl DeviceAdapter {
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
if let Some(device) = self.tun.lock().as_ref() {
use tun::device::IFace;
device.write(buf)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not tun device"))
}
}
pub fn start(&self, device: Arc<Device>) -> io::Result<()> {
self.tun_device_helper.start(device.clone())?;
self.tun.lock().replace(device);
Ok(())
}
}
#[derive(Clone)]
pub struct TunDeviceHelper {
inner: Arc<AtomicCell<Option<TunDeviceHelperInner>>>,
}
struct TunDeviceHelperInner {
stop_manager: StopManager,
context: Context,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
#[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>)>>,
}
impl TunDeviceHelper {
pub fn new(
stop_manager: StopManager,
context: Context,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
ip_route: ExternalRoute,
#[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>)>>,
) -> Self {
Self {
inner: Arc::new(AtomicCell::new(Some(TunDeviceHelperInner {
stop_manager,
context,
current_device,
ip_route,
ip_proxy_map,
client_cipher,
server_cipher,
parallel,
up_counter,
device_list,
}))),
}
}
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,
)?;
Ok(())
} else {
Err(io::Error::new(io::ErrorKind::Other, "Repeated start"))
}
}
}