Compare commits

...
17 Commits
Author SHA1 Message Date
lubeilin b818851b38 修改rand版本 2024-04-07 22:47:50 +08:00
lubeilin f47db0ab1b 处理通道空置的问题 2024-04-07 21:40:31 +08:00
lubeilin 256a2adc3e 安卓不设置路由 2024-04-07 21:38:09 +08:00
lubeilin 28522f2f07 完善jni调用 2024-04-07 20:57:10 +08:00
lubeilin a33ffd96fd 通道设置为0 2024-04-06 17:30:32 +08:00
lubeilin 61f7352312 测试阻塞udp的性能 2024-04-06 17:30:12 +08:00
lubeilin def33382e3 日志输出版本信息 2024-04-06 11:23:09 +08:00
lubeilin 1d0d64bd30 Merge remote-tracking branch 'origin/main' 2024-04-05 23:21:21 +08:00
lubeilin e7e8f6b771 调整tcp模式打洞 2024-04-05 23:14:45 +08:00
lubeilin 4317b06428 公网端口默认设置为0 2024-04-05 23:14:12 +08:00
lubeilin e9c695f4ac 注册成功后先更新地址 2024-04-05 23:13:36 +08:00
lubeilin da714e97e8 修改公网地址探测频率 2024-04-05 23:10:07 +08:00
lubeilin ee2186aba5 解决tcp掉线问题 2024-04-05 23:01:34 +08:00
lubeilin ca91f97c27 调整序列号 2024-04-05 23:00:34 +08:00
lubeilin 284cf38f0b 优化广播 2024-03-30 00:24:19 +08:00
lbl8603 dc3e4c8253 Merge pull request #32 from ziyouwa/main
优化从linux或wsl系统获取id
2024-03-25 15:46:01 +08:00
ziyouwa c7b9f61bd2 1、优化从linux或wsl系统获取id
2、增加.gitignore文件
2024-03-25 15:36:18 +08:00
23 changed files with 434 additions and 191 deletions
+4
View File
@@ -0,0 +1,4 @@
target/*
vnt/src/proto/message.rs
vnt-cli/src/generated_serial_number.rs
Cargo.lock
+7
View File
@@ -51,6 +51,13 @@ pub fn get_unique_identifier() -> Option<String> {
#[cfg(target_os = "linux")]
pub fn get_unique_identifier() -> Option<String> {
use std::process::Command;
// 对 linux 或 wsl 来说,读取 /etc/machine-id 即可获取当前操作系统的
// 唯一标识,而且某些环境没有预装`dmidecode`命令
if let Ok(identifier) = std::fs::read_to_string("/etc/machine-id") {
return Some(identifier);
}
let output = match Command::new("dmidecode")
.arg("-s")
.arg("system-uuid")
+2 -2
View File
@@ -12,7 +12,6 @@ getopts = "0.2.21"
console = "0.15.2"
os_info = "3.7.0"
serde = "1.0"
#serde_json = "1.0.94"
serde_yaml = "0.9.32"
log = "0.4.17"
log4rs = "1.2.0"
@@ -41,4 +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"
+3 -4
View File
@@ -3,11 +3,10 @@ use std::fs::File;
use std::io::Write;
fn main() {
// 生成随机序列号
let now_time = chrono::Local::now();
let serial_number = format!(
"{}-{}-{}",
rand::thread_rng().gen_range(100..1000),
rand::thread_rng().gen_range(100..1000),
"{}-{}",
&now_time.format("%y%m%d%H%M").to_string(),
rand::thread_rng().gen_range(100..1000)
);
let generated_code = format!(r#"pub const SERIAL_NUMBER: &str = "{}";"#, serial_number);
+5
View File
@@ -338,6 +338,11 @@ fn main() {
};
println!("version {}", vnt::VNT_VERSION);
println!("Serial:{}", generated_serial_number::SERIAL_NUMBER);
log::info!(
"version:{},Serial:{}",
vnt::VNT_VERSION,
generated_serial_number::SERIAL_NUMBER
);
main0(config, cmd);
std::process::exit(0);
}
@@ -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) {
+2 -5
View File
@@ -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);
+9 -1
View File
@@ -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) {
+7 -2
View File
@@ -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) => {
+10
View File
@@ -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 _,
));
}
+13 -21
View File
@@ -289,15 +289,7 @@ impl ContextInner {
}
}
pub fn remove_route(&self, ip: &Ipv4Addr, route_key: RouteKey) {
if self.route_table.remove_route(ip, route_key) {
if route_key.is_tcp {
if let Some(tcp) = self.tcp_map.write().remove(&route_key.addr) {
if let Err(e) = tcp.shutdown() {
log::warn!("{:?}", e);
}
}
}
}
self.route_table.remove_route(ip, route_key)
}
}
@@ -461,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>)> {
@@ -501,18 +498,13 @@ impl RouteTable {
}
list
}
pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) -> bool {
pub fn remove_route(&self, id: &Ipv4Addr, route_key: RouteKey) {
let mut write_guard = self.route_table.write();
if let Some((_, routes)) = write_guard.get_mut(id) {
routes.retain(|(x, _)| x.route_key() != route_key);
if routes.is_empty() {
write_guard.remove(id);
true
} else {
false
}
} else {
return true;
}
}
/// 更新路由入栈包的时刻,长时间没有收到数据的路由将会被剔除
-7
View File
@@ -179,9 +179,6 @@ pub fn init_context(
)
};
io_convert(socket.set_reuse_address(true), |_| {
format!("set_reuse_address failed: {}", &address)
})?;
io_convert(socket.set_send_buffer_size(2 * 1024 * 1024), |_| {
format!("set_send_buffer_size failed: {}", &address)
})?;
@@ -192,7 +189,6 @@ pub fn init_context(
format!("bind failed: {}", &address)
})?;
let main_channel: UdpSocket = socket.into();
main_channel.set_nonblocking(true)?;
udps.push(main_channel);
}
let context = Context::new(
@@ -220,9 +216,6 @@ pub fn init_context(
(socket, address)
};
io_convert(socket.set_reuse_address(true), |_| {
format!("set_reuse_address failed: {}", &address)
})?;
if let Err(e) = socket.bind(&address.into()) {
if ports[0] == 0 {
//端口可能冲突,则使用任意端口
+17 -7
View File
@@ -100,6 +100,9 @@ impl NatInfo {
pub fn update_addr(&mut self, index: usize, ip: Ipv4Addr, port: u16) {
if port != 0 {
if let Some(public_port) = self.public_ports.get_mut(index) {
if *public_port != port {
log::info!("端口变化={}:{}", ip, port)
}
*public_port = port;
}
}
@@ -111,6 +114,7 @@ impl NatInfo {
{
if !self.public_ips.contains(&ip) {
self.public_ips.push(ip);
log::info!("ip变化={},{:?}", ip, self.public_ips)
}
}
}
@@ -208,7 +212,7 @@ impl Punch {
impl Punch {
fn connect_tcp(&self, buf: &[u8], addr: SocketAddr) -> bool {
// mio是非阻塞的,不能立马判断是否能连接成功,所以用标准库的tcp
match std::net::TcpStream::connect_timeout(&addr, Duration::from_secs(3)) {
match std::net::TcpStream::connect_timeout(&addr, Duration::from_millis(100)) {
Ok(tcp_stream) => {
if tcp_stream.set_nonblocking(true).is_err() {
return false;
@@ -224,29 +228,35 @@ impl Punch {
}
false
}
pub fn punch(&mut self, buf: &[u8], id: Ipv4Addr, nat_info: NatInfo) -> io::Result<()> {
if !self.context.route_table.need_punch(&id) {
pub fn punch(
&mut self,
buf: &[u8],
id: Ipv4Addr,
nat_info: NatInfo,
punch_tcp: bool,
) -> io::Result<()> {
if self.context.route_table.no_need_punch(&id) {
log::info!("已打洞成功,无需打洞:{:?}", id);
return Ok(());
}
if self.is_tcp && nat_info.tcp_port != 0 {
if punch_tcp && self.is_tcp && nat_info.tcp_port != 0 {
//向tcp发起连接
if let Some(ipv6_addr) = nat_info.local_tcp_ipv6addr() {
if self.connect_tcp(buf, ipv6_addr) {
return Ok(());
// return Ok(());
}
}
//向tcp发起连接
if let Some(ipv4_addr) = nat_info.local_tcp_ipv4addr() {
if self.connect_tcp(buf, ipv4_addr) {
return Ok(());
// return Ok(());
}
}
if nat_info.nat_type == NatType::Cone && nat_info.public_ips.len() == 1 {
let addr =
SocketAddr::V4(SocketAddrV4::new(nat_info.public_ips[0], nat_info.tcp_port));
if self.connect_tcp(buf, addr) {
return Ok(());
// return Ok(());
}
}
}
+69 -2
View File
@@ -1,6 +1,5 @@
use std::collections::HashMap;
use std::sync::mpsc::{sync_channel, Receiver};
use std::sync::Arc;
use std::{io, thread};
use mio::event::Source;
@@ -135,7 +134,74 @@ where
}
}
/// 阻塞监听
// /// 阻塞
// fn main_udp_listen<H>(
// stop_manager: StopManager,
// recv_handler: H,
// context: Context,
// ) -> io::Result<()>
// where
// H: RecvChannelHandler,
// {
// for index in 0..context.main_udp_socket.len() {
// let stop_manager = stop_manager.clone();
// let context = context.clone();
// let recv_handler = recv_handler.clone();
// thread::Builder::new()
// .name(format!("mainUdp{}", index))
// .spawn(move || {
// if let Err(e) = main_udp_listen0(stop_manager, index, recv_handler, context) {
// log::error!("{:?}", e);
// }
// })?;
// }
// Ok(())
// }
//
// pub fn main_udp_listen0<H>(
// stop_manager: StopManager,
// index: usize,
// mut recv_handler: H,
// context: Context,
// ) -> io::Result<()>
// where
// H: RecvChannelHandler,
// {
// use std::time::Duration;
// let udp_socket = &context.main_udp_socket[index];
// udp_socket.set_read_timeout(Some(Duration::from_secs(5)))?;
// udp_socket.set_write_timeout(Some(Duration::from_secs(1)))?;
// let local_addr = udp_socket.local_addr()?;
// let worker = stop_manager.add_listener(format!("main_udp_{}", index), move || {
// if let Ok(udp) = std::net::UdpSocket::bind("0.0.0.0:0") {
// let _ = udp.send_to(b"stop", format!("127.0.0.1:{}", local_addr.port()));
// }
// })?;
//
// let mut buf = [0; BUFFER_SIZE];
// loop {
// match udp_socket.recv_from(&mut buf) {
// Ok((len, addr)) => {
// if &buf[..len] == b"stop" {
// if stop_manager.is_stop() {
// break;
// }
// }
// recv_handler.handle(&mut buf[..len], RouteKey::new(false, index, addr), &context);
// }
// Err(e) => {
// if stop_manager.is_stop() {
// break;
// }
// log::error!("index={},{:?},{}", index, udp_socket.local_addr(), e)
// }
// }
// }
// worker.stop_all();
// Ok(())
// }
/// 非阻塞
fn main_udp_listen<H>(
stop_manager: StopManager,
recv_handler: H,
@@ -144,6 +210,7 @@ fn main_udp_listen<H>(
where
H: RecvChannelHandler,
{
use std::sync::Arc;
let poll = Poll::new()?;
let waker = Arc::new(Waker::new(poll.registry(), NOTIFY)?);
let _waker = waker.clone();
+1
View File
@@ -190,6 +190,7 @@ impl Vnt {
server_cipher.clone(),
config.parallel,
up_counter,
device_list.clone(),
)?;
maintain::idle_gateway(
&scheduler,
+2 -2
View File
@@ -31,8 +31,8 @@ pub fn pub_address_request(
server_cipher: Cipher,
) {
addr_request0(&context, &current_device_info, &server_cipher);
// 17秒发送一次
let rs = scheduler.timeout(Duration::from_secs(17), |s| {
// 9秒发送一次
let rs = scheduler.timeout(Duration::from_secs(9), |s| {
pub_address_request(s, context, current_device_info, server_cipher)
});
if !rs {
+98 -43
View File
@@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::net::Ipv4Addr;
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
use std::sync::Arc;
@@ -26,6 +27,7 @@ pub struct PunchSender {
sender_cone_self: SyncSender<(Ipv4Addr, NatInfo)>,
sender_cone_peer: SyncSender<(Ipv4Addr, NatInfo)>,
}
impl PunchSender {
pub fn send(&self, src_peer: bool, ip: Ipv4Addr, info: NatInfo) -> bool {
log::info!(
@@ -53,17 +55,19 @@ impl PunchSender {
sender.try_send((ip, info)).is_ok()
}
}
pub struct PunchReceiver {
receiver_peer: Receiver<(Ipv4Addr, NatInfo)>,
receiver_self: Receiver<(Ipv4Addr, NatInfo)>,
receiver_cone_peer: Receiver<(Ipv4Addr, NatInfo)>,
receiver_cone_self: Receiver<(Ipv4Addr, NatInfo)>,
}
pub fn punch_channel() -> (PunchSender, PunchReceiver) {
let (sender_self, receiver_self) = sync_channel(1);
let (sender_peer, receiver_peer) = sync_channel(1);
let (sender_cone_peer, receiver_cone_peer) = sync_channel(1);
let (sender_cone_self, receiver_cone_self) = sync_channel(1);
let (sender_self, receiver_self) = sync_channel(0);
let (sender_peer, receiver_peer) = sync_channel(0);
let (sender_cone_peer, receiver_cone_peer) = sync_channel(0);
let (sender_cone_self, receiver_cone_self) = sync_channel(0);
(
PunchSender {
sender_self,
@@ -90,6 +94,8 @@ pub fn punch(
receiver: PunchReceiver,
punch: Punch,
) {
let punch_record = Arc::new(Mutex::new(HashMap::new()));
let last_punch_record = HashMap::new();
punch_request(
scheduler,
context,
@@ -98,15 +104,18 @@ pub fn punch(
current_device.clone(),
client_cipher.clone(),
0,
punch_record.clone(),
last_punch_record,
);
let f = |receiver: Receiver<(Ipv4Addr, NatInfo)>| {
let punch = punch.clone();
let current_device = current_device.clone();
let client_cipher = client_cipher.clone();
let punch_record = punch_record.clone();
thread::Builder::new()
.name("punch".into())
.spawn(move || {
punch_start(receiver, punch, current_device, client_cipher);
punch_start(receiver, punch, current_device, client_cipher, punch_record);
})
.expect("punch");
};
@@ -122,6 +131,7 @@ fn punch_start(
mut punch: Punch,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher,
punch_record: Arc<Mutex<HashMap<Ipv4Addr, usize>>>,
) {
while let Ok((peer_ip, nat_info)) = receiver.recv() {
let mut packet = NetPacket::new_encrypt([0u8; 12 + ENCRYPTION_RESERVED]).unwrap();
@@ -131,12 +141,23 @@ fn punch_start(
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
packet.set_source(current_device.load().virtual_ip());
packet.set_destination(peer_ip);
log::info!("发起打洞,目标:{:?},{:?}", peer_ip, nat_info);
let count = {
let mut guard = punch_record.lock();
if let Some(v) = guard.get_mut(&peer_ip) {
*v += 1;
*v
} else {
guard.insert(peer_ip, 1);
0
}
};
log::info!("第{}次发起打洞,目标:{:?},{:?} ", count, peer_ip, nat_info);
if let Err(e) = client_cipher.encrypt_ipv4(&mut packet) {
log::error!("{:?}", e);
continue;
}
if let Err(e) = punch.punch(packet.buffer(), peer_ip, nat_info) {
if let Err(e) = punch.punch(packet.buffer(), peer_ip, nat_info, count < 2) {
log::warn!("{:?}", e)
}
}
@@ -151,16 +172,27 @@ fn punch_request(
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
client_cipher: Cipher,
count: usize,
punch_record: Arc<Mutex<HashMap<Ipv4Addr, usize>>>,
mut last_punch_record: HashMap<Ipv4Addr, usize>,
) {
let curr = current_device.load();
let secs = if curr.status.online() {
if let Err(e) = punch0(&context, &nat_test, &device_list, curr, &client_cipher) {
if let Err(e) = punch0(
&context,
&nat_test,
&device_list,
curr,
&client_cipher,
&punch_record,
&mut last_punch_record,
count,
) {
log::warn!("{:?}", e)
}
let sleep_time = [3, 5, 7, 11, 13, 17, 19, 23, 29];
let sleep_time = [5, 6, 7];
Duration::from_secs(sleep_time[count % sleep_time.len()])
} else {
Duration::from_secs(3)
Duration::from_secs(5)
};
let rs = scheduler.timeout(secs, move |s| {
punch_request(
@@ -171,6 +203,8 @@ fn punch_request(
current_device,
client_cipher,
count + 1,
punch_record,
last_punch_record,
);
});
if !rs {
@@ -185,8 +219,21 @@ fn punch0(
device_list: &Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
current_device: CurrentDeviceInfo,
client_cipher: &Cipher,
punch_record: &Mutex<HashMap<Ipv4Addr, usize>>,
last_punch_record: &mut HashMap<Ipv4Addr, usize>,
total_count: usize,
) -> io::Result<()> {
let nat_info = nat_test.nat_info();
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.iter().filter(|&&v| v == 0).count()
> nat_info.public_ports.len() / 2)
{
log::info!("公网地址为空,暂时放弃打洞,第{}轮", total_count);
return Ok(());
}
let current_ip = current_device.virtual_ip;
let mut list: Vec<PeerDeviceInfo> = device_list
.lock()
@@ -196,43 +243,51 @@ fn punch0(
.cloned()
.collect();
list.shuffle(&mut rand::thread_rng());
let mut count = 0;
// // 优先没打洞的 need_punch会过滤掉已经打洞成功的
// list.sort_by(|v1, v2| {
// if context.route_table.route_one_p2p(&v1.virtual_ip).is_none() {
// Ordering::Less
// } else if context.route_table.route_one_p2p(&v2.virtual_ip).is_none() {
// Ordering::Greater
// } else {
// Ordering::Equal
// }
// });
for info in list {
if !info.status.is_online() {
continue;
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;
}
if info.virtual_ip <= current_device.virtual_ip {
continue;
}
if !context.route_table.need_punch(&info.virtual_ip) {
continue;
}
count += 1;
if count > 2 {
// 能发起打洞的前提是自己空闲,这里会间隔5秒以上发起一次打洞,所以假定上一轮打洞已结束
let last_punch = last_punch_record
.get(&info.virtual_ip)
.cloned()
.unwrap_or(0);
// 梯度增加打洞时间间隔
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,
current_device.virtual_ip(),
&nat_info,
info.virtual_ip,
)?;
log::info!(
"目标:{:?},当前nat:{:?} 第{}次发起打洞协商请求, 第:{}轮",
info.virtual_ip,
nat_info,
punch_count,
total_count,
);
context.send_default(packet.buffer(), current_device.connect_server)?;
break;
}
let packet = punch_packet(
client_cipher,
current_device.virtual_ip(),
&nat_info,
info.virtual_ip,
)?;
log::info!(
"发起打洞协商请求,目标:{:?},{:?}",
info.virtual_ip,
nat_info
);
context.send_default(packet.buffer(), current_device.connect_server)?;
}
Ok(())
}
+54 -47
View File
@@ -237,6 +237,10 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
context
.route_table
.add_route_if_absent(virtual_gateway, route);
let public_ip = response.public_ip.into();
let public_port = response.public_port as u16;
self.nat_test
.update_addr(route_key.index(), public_ip, public_port);
let old = current_device;
let mut cur = *current_device;
loop {
@@ -245,7 +249,7 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
new_current_device.virtual_ip = virtual_ip;
new_current_device.virtual_netmask = virtual_netmask;
new_current_device.virtual_gateway = virtual_gateway;
new_current_device.status = crate::handle::ConnectStatus::Connected;
new_current_device.status = ConnectStatus::Connected;
if let Err(c) = self
.current_device
.compare_exchange(cur, new_current_device)
@@ -256,10 +260,6 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
}
}
let public_ip = response.public_ip.into();
let public_port = response.public_port as u16;
self.nat_test
.update_addr(route_key.index(), public_ip, public_port);
if old.virtual_ip != virtual_ip
|| old.virtual_gateway != virtual_gateway
|| old.virtual_netmask != virtual_netmask
@@ -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 => {
+76 -42
View File
@@ -1,13 +1,15 @@
use std::io;
use std::net::Ipv4Addr;
use crate::channel::context::Context;
use parking_lot::Mutex;
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};
use crate::handle::{check_dest, CurrentDeviceInfo, PeerDeviceInfo};
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::{IpProxyMap, ProxyHandler};
use crate::protocol;
@@ -23,57 +25,82 @@ fn broadcast(
sender: &Context,
net_packet: &mut NetPacket<&mut [u8]>,
current_device: &CurrentDeviceInfo,
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
) -> io::Result<()> {
let mut peer_ips = Vec::with_capacity(8);
let vec = sender.route_table.route_table_one();
let mut relay_count = 0;
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;
for (peer_ip, route) in vec {
if peer_ip == current_device.virtual_gateway {
continue;
}
if peer_ips.len() == MAX_COUNT {
relay_count += 1;
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 route.is_p2p()
&& sender
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()
{
peer_ips.push(peer_ip);
} else {
relay_count += 1;
{
p2p_ips.push(peer_ip);
continue;
}
}
relay_ips.push(peer_ip);
}
if (relay_count == 0 && !peer_ips.is_empty()) || current_device.status.offline() {
//不需要转发
if !overflow && relay_ips.is_empty() {
//全部p2p,不需要服务器中转
return Ok(());
}
//转发到服务端的可选择广播,还要进行服务端加密
if peer_ips.is_empty() {
sender.send_default(net_packet.buffer(), current_device.connect_server)?;
} else {
let buf =
vec![0u8; 12 + 1 + peer_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(&peer_ips)?;
broadcast.set_data(net_packet.buffer())?;
server_cipher.encrypt_ipv4(&mut server_packet)?;
sender.send_default(server_packet.buffer(), current_device.connect_server)?;
if p2p_ips.is_empty() {
//都没有p2p则直接由服务器转发
if current_device.status.online() {
sender.send_default(net_packet.buffer(), current_device.connect_server)?;
}
return Ok(());
}
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)
}
/// 实现一个原地发送,必须保证是如下结构
@@ -89,6 +116,7 @@ pub fn base_handle(
#[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();
@@ -118,7 +146,13 @@ pub fn base_handle(
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)?;
broadcast(
server_cipher,
context,
&mut net_packet,
&current_device,
device_list,
)?;
return Ok(());
}
if !check_dest(
+10 -1
View File
@@ -2,6 +2,7 @@ use std::sync::Arc;
use std::{io, thread};
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::Mutex;
use packet::icmp::icmp::IcmpPacket;
use packet::icmp::Kind;
@@ -14,7 +15,7 @@ use crate::channel::context::Context;
use crate::cipher::Cipher;
use crate::external_route::ExternalRoute;
use crate::handle::tun_tap::channel_group::{channel_group, GroupSyncSender};
use crate::handle::CurrentDeviceInfo;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
#[cfg(feature = "ip_proxy")]
use crate::ip_proxy::IpProxyMap;
use crate::util::{SingleU64Adder, StopManager};
@@ -46,6 +47,7 @@ fn handle(
#[cfg(feature = "ip_proxy")] proxy_map: &Option<IpProxyMap>,
client_cipher: &Cipher,
server_cipher: &Cipher,
device_list: &Mutex<(u16, Vec<PeerDeviceInfo>)>,
) -> io::Result<()> {
//忽略掉结构不对的情况(ipv6数据、win tap会读到空数据),不然日志打印太多了
let ipv4_packet = match IpV4Packet::new(&mut data[12..len]) {
@@ -67,6 +69,7 @@ fn handle(
proxy_map,
client_cipher,
server_cipher,
device_list,
);
}
@@ -81,6 +84,7 @@ pub fn start(
server_cipher: Cipher,
parallel: usize,
mut up_counter: SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
) -> io::Result<()> {
let worker = {
#[cfg(target_os = "macos")]
@@ -110,6 +114,7 @@ pub fn start(
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 || {
@@ -129,6 +134,7 @@ pub fn start(
&ip_proxy_map,
&client_cipher,
&server_cipher,
&device_list,
) {
Ok(_) => {}
Err(e) => {
@@ -161,6 +167,7 @@ pub fn start(
client_cipher,
server_cipher,
&mut up_counter,
device_list,
) {
log::warn!("stop:{}", e);
}
@@ -180,6 +187,7 @@ fn start_simple(
client_cipher: Cipher,
server_cipher: Cipher,
up_counter: &mut SingleU64Adder,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
) -> io::Result<()> {
let mut buf = [0; 1024 * 16];
loop {
@@ -204,6 +212,7 @@ fn start_simple(
&ip_proxy_map,
&client_cipher,
&server_cipher,
&device_list,
) {
Ok(_) => {}
Err(e) => {
+2 -3
View File
@@ -78,7 +78,7 @@ impl Into<NatType> for PunchNatType {
impl NatTest {
pub fn new(
channel_num: usize,
_channel_num: usize,
mut stun_server: Vec<String>,
local_ipv4: Option<Ipv4Addr>,
ipv6: Option<Ipv6Addr>,
@@ -87,8 +87,7 @@ impl NatTest {
) -> NatTest {
let server = stun_server[0].clone();
stun_server.resize(3, server);
let mut ports = udp_ports.clone();
ports.resize(channel_num, 0);
let ports = vec![0; udp_ports.len()];
let nat_info = NatInfo::new(
Vec::new(),
ports,