Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b818851b38 | ||
|
|
f47db0ab1b | ||
|
|
256a2adc3e | ||
|
|
28522f2f07 |
+1
-1
@@ -40,5 +40,5 @@ server_encrypt=["vnt/server_encrypt"]
|
||||
ip_proxy=["vnt/ip_proxy"]
|
||||
[build-dependencies]
|
||||
embed-manifest = "1.4.0"
|
||||
rand = "0.9.0-alpha.0"
|
||||
rand = "0.8.5"
|
||||
chrono = "0.4.23"
|
||||
@@ -8,6 +8,10 @@ import top.wherewego.vnt.jni.param.*;
|
||||
* @author https://github.com/lbl8603/vnt
|
||||
*/
|
||||
public interface CallBack {
|
||||
/**
|
||||
* 连接成功的回调
|
||||
*/
|
||||
void success();
|
||||
/**
|
||||
* 创建虚拟网卡成功的回调方法
|
||||
*
|
||||
|
||||
@@ -90,6 +90,18 @@ public class Config {
|
||||
* 虚拟网卡fd 仅在android上支持
|
||||
*/
|
||||
private int deviceFd;
|
||||
/**
|
||||
* enum: relay/p2p/all
|
||||
*/
|
||||
private String useChannel;
|
||||
/**
|
||||
* 模拟丢包率,取0~1之间的数,为null表示不丢包,1表示全部丢包
|
||||
*/
|
||||
private Double packetLossRate;
|
||||
/**
|
||||
* 模拟延迟 单位毫秒(ms)
|
||||
*/
|
||||
private Integer packetDelay;
|
||||
|
||||
public Config() {
|
||||
}
|
||||
@@ -261,4 +273,28 @@ public class Config {
|
||||
public void setDeviceFd(int deviceFd) {
|
||||
this.deviceFd = deviceFd;
|
||||
}
|
||||
|
||||
public String getUseChannel() {
|
||||
return useChannel;
|
||||
}
|
||||
|
||||
public void setUseChannel(String useChannel) {
|
||||
this.useChannel = useChannel;
|
||||
}
|
||||
|
||||
public Double getPacketLossRate() {
|
||||
return packetLossRate;
|
||||
}
|
||||
|
||||
public void setPacketLossRate(Double packetLossRate) {
|
||||
this.packetLossRate = packetLossRate;
|
||||
}
|
||||
|
||||
public Integer getPacketDelay() {
|
||||
return packetDelay;
|
||||
}
|
||||
|
||||
public void setPacketDelay(Integer packetDelay) {
|
||||
this.packetDelay = packetDelay;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package top.wherewego.vnt.jni;
|
||||
|
||||
/**
|
||||
* @author lubeilin
|
||||
* @date: 2024/02/27 18:31
|
||||
* ip转换
|
||||
*
|
||||
* @author https://github.com/lbl8603/vnt
|
||||
*/
|
||||
public class IpUtils {
|
||||
public static String intToIpAddress(int ipAddress) {
|
||||
|
||||
@@ -11,11 +11,8 @@ import java.io.IOException;
|
||||
public class Vnt implements Closeable {
|
||||
private final long raw;
|
||||
|
||||
public Vnt(Config config, CallBack callBack) {
|
||||
public Vnt(Config config, CallBack callBack) throws Exception{
|
||||
this.raw = new0(config, callBack);
|
||||
if(this.raw == 0){
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
@@ -30,7 +27,7 @@ public class Vnt implements Closeable {
|
||||
return list0(raw);
|
||||
}
|
||||
|
||||
private native long new0(Config config, CallBack callBack);
|
||||
private native long new0(Config config, CallBack callBack) throws Exception;
|
||||
|
||||
private native void stop0(long raw);
|
||||
|
||||
|
||||
@@ -26,6 +26,11 @@ impl CallBack {
|
||||
}
|
||||
|
||||
impl CallBack {
|
||||
fn success0(&self) -> jni::errors::Result<()> {
|
||||
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
|
||||
env.call_method(&self.this, "success", "()V", &[])?;
|
||||
Ok(())
|
||||
}
|
||||
fn create_tun0(&self, info: DeviceInfo) -> jni::errors::Result<()> {
|
||||
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
|
||||
let param = env.new_object(
|
||||
@@ -139,13 +144,16 @@ impl CallBack {
|
||||
}
|
||||
fn stop0(&self) -> jni::errors::Result<()> {
|
||||
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
|
||||
env.call_method(&self.this, "error", "()V", &[])?;
|
||||
env.call_method(&self.this, "stop", "()V", &[])?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl VntCallback for CallBack {
|
||||
fn success(&self) {
|
||||
if let Err(e) = self.success0() {
|
||||
log::warn!("success {:?}", e);
|
||||
}
|
||||
}
|
||||
fn create_tun(&self, info: DeviceInfo) {
|
||||
if let Err(e) = self.create_tun0(info) {
|
||||
|
||||
@@ -29,6 +29,11 @@ pub fn new_config(env: &mut JNIEnv, config: JObject) -> Result<Config, Error> {
|
||||
let use_channel = to_string(env, &config, "useChannel")?;
|
||||
let finger = env.get_field(&config, "finger", "Z")?.z()?;
|
||||
let first_latency = env.get_field(&config, "firstLatency", "Z")?.z()?;
|
||||
let packet_delay = to_integer(env, &config, "packetDelay")?
|
||||
.map(|v| v as u32)
|
||||
.unwrap_or_default();
|
||||
let packet_loss_rate = to_double(env, &config, "packetLossRate")?;
|
||||
|
||||
let in_ips = to_string_array(env, &config, "inIps")?;
|
||||
let out_ips = to_string_array(env, &config, "outIps")?;
|
||||
let ports =
|
||||
@@ -132,8 +137,8 @@ pub fn new_config(env: &mut JNIEnv, config: JObject) -> Result<Config, Error> {
|
||||
#[cfg(target_os = "android")]
|
||||
device_fd,
|
||||
UseChannelType::from_str(&use_channel.unwrap_or_default()).unwrap_or_default(),
|
||||
None,
|
||||
0,
|
||||
packet_loss_rate,
|
||||
packet_delay,
|
||||
) {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
|
||||
@@ -119,3 +119,13 @@ pub fn to_integer(env: &mut JNIEnv, config: &JObject, name: &str) -> Result<Opti
|
||||
env.call_method(value, "intValue", "()I", &[])?.i()? as _
|
||||
));
|
||||
}
|
||||
pub fn to_double(env: &mut JNIEnv, config: &JObject, name: &str) -> Result<Option<f64>, Error> {
|
||||
let value = env.get_field(config, name, "Ljava/lang/Double;")?.l()?;
|
||||
if value.is_null() {
|
||||
return Ok(None);
|
||||
}
|
||||
// 调用 intValue
|
||||
return Ok(Some(
|
||||
env.call_method(value, "doubleValue", "()D", &[])?.d()? as _,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -453,14 +453,19 @@ impl RouteTable {
|
||||
}
|
||||
None
|
||||
}
|
||||
pub fn need_punch(&self, id: &Ipv4Addr) -> bool {
|
||||
pub fn no_need_punch(&self, id: &Ipv4Addr) -> bool {
|
||||
if let Some((_, v)) = self.route_table.read().get(id) {
|
||||
//存在p2p的通道则不再打洞
|
||||
if v.iter().filter(|(k, _)| k.is_p2p()).count() >= 1 {
|
||||
return false;
|
||||
}
|
||||
//p2p的通道数符合要求
|
||||
return v.iter().filter(|(k, _)| k.is_p2p()).count() >= self.channel_num;
|
||||
}
|
||||
false
|
||||
}
|
||||
pub fn p2p_num(&self, id: &Ipv4Addr) -> usize {
|
||||
if let Some((_, v)) = self.route_table.read().get(id) {
|
||||
v.iter().filter(|(k, _)| k.is_p2p()).count()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
true
|
||||
}
|
||||
/// 返回所有路由
|
||||
pub fn route_table(&self) -> Vec<(Ipv4Addr, Vec<Route>)> {
|
||||
|
||||
@@ -235,7 +235,7 @@ impl Punch {
|
||||
nat_info: NatInfo,
|
||||
punch_tcp: bool,
|
||||
) -> io::Result<()> {
|
||||
if !self.context.route_table.need_punch(&id) {
|
||||
if self.context.route_table.no_need_punch(&id) {
|
||||
log::info!("已打洞成功,无需打洞:{:?}", id);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -227,7 +227,9 @@ fn punch0(
|
||||
if total_count < 10
|
||||
&& (nat_info.public_ips.is_empty()
|
||||
|| nat_info.public_ports.is_empty()
|
||||
|| nat_info.public_ports[0] == 0)
|
||||
|| nat_info.public_ports[0] == 0
|
||||
|| nat_info.public_ports.iter().filter(|&&v| v == 0).count()
|
||||
> nat_info.public_ports.len() / 2)
|
||||
{
|
||||
log::info!("公网地址为空,暂时放弃打洞,第{}轮", total_count);
|
||||
return Ok(());
|
||||
@@ -242,22 +244,33 @@ fn punch0(
|
||||
.collect();
|
||||
list.shuffle(&mut rand::thread_rng());
|
||||
for info in list {
|
||||
if !context.route_table.need_punch(&info.virtual_ip) {
|
||||
punch_record.lock().remove(&info.virtual_ip);
|
||||
continue;
|
||||
}
|
||||
// 能发起打洞的前提是自己空闲,这里会间隔5秒以上发起一次打洞,所以假定上一轮打洞已结束
|
||||
let punch_count = punch_record
|
||||
.lock()
|
||||
.get(&info.virtual_ip)
|
||||
.cloned()
|
||||
.unwrap_or(0);
|
||||
let p2p_num = context.route_table.p2p_num(&info.virtual_ip);
|
||||
let mut max_punch_interval = 70;
|
||||
if p2p_num > 0 {
|
||||
if punch_count == 0 {
|
||||
continue;
|
||||
}
|
||||
if p2p_num >= context.channel_num() {
|
||||
//通道数满足要求,不再打洞
|
||||
punch_record.lock().remove(&info.virtual_ip);
|
||||
continue;
|
||||
}
|
||||
//有p2p通道,但是通道数量不够,则继续打洞
|
||||
// 提高等待上限
|
||||
max_punch_interval = 300;
|
||||
}
|
||||
// 能发起打洞的前提是自己空闲,这里会间隔5秒以上发起一次打洞,所以假定上一轮打洞已结束
|
||||
let last_punch = last_punch_record
|
||||
.get(&info.virtual_ip)
|
||||
.cloned()
|
||||
.unwrap_or(0);
|
||||
// 梯度减少打洞频率
|
||||
if total_count > last_punch + punch_count.min(35) {
|
||||
// 梯度增加打洞时间间隔
|
||||
if total_count > last_punch + punch_count.min(max_punch_interval) {
|
||||
last_punch_record.insert(info.virtual_ip, total_count);
|
||||
let packet = punch_packet(
|
||||
client_cipher,
|
||||
|
||||
@@ -267,57 +267,64 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
|
||||
if old.virtual_ip != Ipv4Addr::UNSPECIFIED {
|
||||
log::info!("ip发生变化,old:{:?},response={:?}", old, response);
|
||||
}
|
||||
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)
|
||||
#[cfg(not(target_os = "android"))]
|
||||
{
|
||||
log::warn!("添加广播路由失败 ={:?}", e);
|
||||
} else {
|
||||
guard.push((Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST));
|
||||
}
|
||||
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((
|
||||
if let Err(e) = self.device.add_route(
|
||||
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);
|
||||
1,
|
||||
) {
|
||||
log::warn!("添加组播路由失败 ={:?}", e);
|
||||
} else {
|
||||
guard.push((dest, mask));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
self.callback.success();
|
||||
}
|
||||
self.set_device_info_list(response.device_info_list, response.epoch as _);
|
||||
if old.status.offline() {
|
||||
self.callback.success();
|
||||
}
|
||||
}
|
||||
}
|
||||
service_packet::Protocol::PushDeviceList => {
|
||||
|
||||
Reference in New Issue
Block a user