Compare commits

..
60 Commits
Author SHA1 Message Date
lubeilin 4f52d58d6e 调整错误输出 2024-04-23 14:04:32 +08:00
lubeilin 441e374563 jni设置dns 2024-04-23 13:56:25 +08:00
lubeilin 3272f3cdca 设置dns 2024-04-23 12:40:33 +08:00
lbl8603 5b40a9f147 支持指定dns 2024-04-23 08:21:01 +08:00
lubeilin 12d4fc8e98 dns解析 2024-04-22 19:00:05 +08:00
lbl8603 ca74827aaf 拒绝服务端密钥对变化 2024-04-21 22:14:56 +08:00
lbl8603 0b570130e8 处理tcp加密注册失败的问题 2024-04-21 18:48:18 +08:00
lbl8603 5bdc514606 增加转发日志 2024-04-21 18:30:33 +08:00
lbl8603 137efe20b8 增加密钥hash,方便客户端判断加密是否一致 2024-04-20 21:27:35 +08:00
lbl8603 0cbc3e0f63 双重探测NAT类型,用于检测某些对称网络 2024-04-20 16:15:45 +08:00
lbl8603 7fbcf0a832 Merge remote-tracking branch 'origin/2024-04-19' into 2024-04-19 2024-04-20 14:49:57 +08:00
lbl8603 7283863fe8 增加路由回调 2024-04-20 14:48:58 +08:00
lbl8603 198f82fb2c 修改ip转u32方式 2024-04-19 20:05:19 +08:00
lubeilin c219af4f4b 增加额外路由 2024-04-19 18:44:22 +08:00
lubeilin 0352982c14 回调增加网络路由 2024-04-19 18:35:37 +08:00
lubeilin cc6cd6dc37 去除多余代码 2024-04-19 18:07:41 +08:00
lubeilin 9155471c26 去除多余代码 2024-04-19 16:28:49 +08:00
lubeilin d916fd7573 去除多余字段 2024-04-19 16:17:39 +08:00
lubeilin 5528557964 去除多余字段 2024-04-19 16:16:49 +08:00
lbl8603 8dfc3b8c43 修改安卓端逻辑 2024-04-19 10:49:47 +08:00
lubeilin 84824731a7 优化nat探测 2024-04-16 23:20:24 +08:00
lubeilin 7131937d06 fmt 2024-04-13 17:45:46 +08:00
lubeilin a657eae599 优化加密状态下的重连 2024-04-13 11:13:37 +08:00
lubeilin e9ec6e8903 增加丢包日志 2024-04-13 10:24:29 +08:00
lubeilin c4a9e79dc2 修复域名转换ip的问题 2024-04-09 22:48:14 +08:00
lubeilin aeebf45390 去除proto生成代码 2024-04-08 23:34:36 +08:00
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
lubeilin b26c4b97b2 上报状态 2024-03-24 21:50:47 +08:00
lubeilin 5569c67ba4 增加日志 2024-03-24 21:50:39 +08:00
lubeilin 69da6de1ed 离线时才检测服务器地址 2024-03-24 09:18:12 +08:00
lubeilin ae983f014b 降低地址探测频率 2024-03-23 12:46:20 +08:00
lubeilin 499e3bbfdf 去除重复逻辑 2024-03-21 23:08:48 +08:00
lubeilin 01f6890fd3 减少离线时发包 2024-03-21 21:25:24 +08:00
lubeilin 9badbe180c 不转发来源和目的相同的数据 2024-03-20 12:21:19 +08:00
lubeilin 30b1e71aa1 fmt 2024-03-19 23:54:33 +08:00
lubeilin b36cc352d5 兼容纯ipv4 2024-03-19 23:53:16 +08:00
lubeilin 12d888cefc 忽略跃点设置失败的异常 2024-03-18 21:35:22 +08:00
lubeilin ad1df41029 调整打洞 2024-03-17 15:41:25 +08:00
lubeilin 67498dfc82 增加序列号 2024-03-17 14:28:03 +08:00
lubeilin cf52fdde57 修改线程名称 2024-03-17 14:27:49 +08:00
lubeilin a20082d40b 已支持ipv6 2024-03-14 23:31:40 +08:00
lubeilin 8e29b020e0 Merge branch 'main' into mio 2024-03-14 12:06:47 +08:00
lubeilin 20132861e9 完善日志,修复已知问题 2024-03-14 12:05:35 +08:00
lubeilin a1e9b3c133 增加参数说明 2024-03-13 23:24:36 +08:00
75 changed files with 2277 additions and 2538 deletions
+4
View File
@@ -0,0 +1,4 @@
target/*
vnt/src/proto/*
vnt-cli/src/generated_serial_number.rs
Cargo.lock
-1
View File
@@ -213,7 +213,6 @@ sudo pfctl -f /etc/pf.conf -e
### Todo
- 桌面UI(测试中)
- 支持Ipv6(1.2.2已支持客户端之间的ipv6,待支持客户端和服务端之间的ipv6通信)
### 常见问题
+2 -2
View File
@@ -68,10 +68,10 @@ pub fn out_ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32)>, String> {
pub fn to_ip(mask: &str) -> Result<u32, String> {
if let Ok(m) = mask.parse::<u32>() {
if m >= 32 {
if m > 32 {
return Err("not netmask".to_string());
}
let mut mask = 0 as u32;
let mut mask = 0u32;
for i in 0..m {
mask = mask | (1 << (31 - i));
}
+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")
+3 -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"
@@ -40,4 +39,6 @@ aes_gcm=["vnt/aes_gcm"]
server_encrypt=["vnt/server_encrypt"]
ip_proxy=["vnt/ip_proxy"]
[build-dependencies]
embed-manifest = "1.4.0"
embed-manifest = "1.4.0"
rand = "0.8.5"
chrono = "0.4.23"
+5
View File
@@ -118,6 +118,11 @@ ports:
cmd: false #关闭控制台输入
no_proxy: false #是否关闭内置代理,true为关闭
first_latency: false #是否优先低延迟通道,默认为false,表示优先使用p2p通道
device_name: vnt-tun #网卡名称
packet_loss: 0 #指定丢包率 取值0~1之间的数 用于模拟弱网
packet_delay: 0 #指定延迟 单位毫秒 用于模拟弱网
dns:
- 8.8.8.8:53
```
或者需要哪个配置就加哪个,当然token是必须的
+13 -7
View File
@@ -1,10 +1,16 @@
// use embed_manifest::{embed_manifest, new_manifest};
// use embed_manifest::manifest::ExecutionLevel;
use rand::Rng;
use std::fs::File;
use std::io::Write;
fn main() {
////强制用管理员运行貌似体验更差了
// if std::env::var_os("CARGO_CFG_WINDOWS").is_some() {
// embed_manifest(new_manifest("vnt")
// .requested_execution_level(ExecutionLevel::RequireAdministrator)).expect("unable to embed manifest file");
// }
let now_time = chrono::Local::now();
let serial_number = format!(
"{}-{}",
&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);
let dest_path = "src/generated_serial_number.rs";
let mut file = File::create(&dest_path).unwrap();
file.write_all(generated_code.as_bytes()).unwrap();
}
+1
View File
@@ -31,6 +31,7 @@ impl VntCallback for VntHandler {
}
fn error(&self, info: ErrorInfo) {
log::error!("error {:?}", info);
println!("{}", style(format!("error {}", info)).red());
match info.code {
ErrorType::TokenError
+2
View File
@@ -36,5 +36,7 @@ pub struct DeviceItem {
pub rt: String,
pub status: String,
pub client_secret: bool,
pub client_secret_hash: Vec<u8>,
pub current_client_secret: bool,
pub current_client_secret_hash: Vec<u8>,
}
+3
View File
@@ -85,6 +85,7 @@ pub fn command_list(vnt: &Vnt) -> Vec<DeviceItem> {
let device_list = vnt.device_list();
let mut list = Vec::new();
let current_client_secret = vnt.client_encrypt();
let client_encrypt_hash = vnt.client_encrypt_hash().unwrap_or(&[]);
for peer in device_list {
let name = peer.name;
let virtual_ip = peer.virtual_ip.to_string();
@@ -153,7 +154,9 @@ pub fn command_list(vnt: &Vnt) -> Vec<DeviceItem> {
rt,
status,
client_secret,
client_secret_hash: peer.client_secret_hash,
current_client_secret,
current_client_secret_hash: client_encrypt_hash.to_vec(),
};
list.push(item);
}
+5 -20
View File
@@ -1,5 +1,5 @@
use std::io;
use std::net::{Ipv4Addr, ToSocketAddrs};
use std::net::Ipv4Addr;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
@@ -19,6 +19,7 @@ pub struct FileConfig {
pub name: String,
pub server_address: String,
pub stun_server: Vec<String>,
pub dns: Vec<String>,
pub in_ips: Vec<String>,
pub out_ips: Vec<String>,
pub password: Option<String>,
@@ -55,6 +56,7 @@ impl Default for FileConfig {
"stun2.l.google.com:19302".to_string(),
"stun.qq.com:3478".to_string(),
],
dns: vec![],
in_ips: vec![],
out_ips: vec![],
password: None,
@@ -91,24 +93,7 @@ pub fn read_config(file_path: &str) -> io::Result<(Config, bool)> {
if file_conf.token.is_empty() {
return Err(io::Error::new(io::ErrorKind::Other, "token is_empty"));
}
let server_address = match file_conf.server_address.to_socket_addrs() {
Ok(mut addr) => {
if let Some(addr) = addr.next() {
addr
} else {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("server_address {:?} error", &file_conf.server_address),
));
}
}
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("server_address {:?} error:{}", &file_conf.server_address, e),
));
}
};
let in_ips = match common::args_parse::ips_parse(&file_conf.in_ips) {
Ok(in_ips) => in_ips,
Err(e) => {
@@ -150,8 +135,8 @@ pub fn read_config(file_path: &str) -> io::Result<(Config, bool)> {
file_conf.token,
file_conf.device_id,
file_conf.name,
server_address,
file_conf.server_address,
file_conf.dns,
file_conf.stun_server,
in_ips,
out_ips,
+7 -2
View File
@@ -21,6 +21,7 @@ pub fn console_info(status: Info) {
println!("Up: {}", style(convert(status.up)).green());
println!("Down: {}", style(convert(status.down)).green());
}
fn convert(num: u64) -> String {
let gigabytes = num / (1024 * 1024 * 1024);
let remaining_bytes = num % (1024 * 1024 * 1024);
@@ -90,13 +91,17 @@ pub fn console_device_list(mut list: Vec<DeviceItem>) {
]);
for item in list {
if &item.status == "Online" {
if item.client_secret != item.current_client_secret {
if item.client_secret != item.current_client_secret
|| (!item.current_client_secret_hash.is_empty()
&& !item.client_secret_hash.is_empty()
&& item.current_client_secret_hash != item.client_secret_hash)
{
//加密状态不一致,无法通信的
out_list.push(vec![
(item.name, Style::new().red()),
(item.virtual_ip, Style::new().red()),
(item.status, Style::new().red()),
("".to_string(), Style::new().red()),
("Mismatch".to_string(), Style::new().red()),
("".to_string(), Style::new().red()),
]);
} else {
+23 -24
View File
@@ -1,4 +1,4 @@
use std::net::{Ipv4Addr, ToSocketAddrs};
use std::net::Ipv4Addr;
use std::path::PathBuf;
use std::str::FromStr;
use std::{io, thread};
@@ -15,6 +15,7 @@ use vnt::core::{Config, Vnt};
mod command;
mod config;
mod console_out;
mod generated_serial_number;
mod root_check;
pub fn app_home() -> io::Result<PathBuf> {
@@ -71,6 +72,7 @@ fn main() {
opts.optopt("", "use-channel", "使用通道 relay/p2p", "<use-channel>");
opts.optopt("", "packet-loss", "丢包率", "<packet-loss>");
opts.optopt("", "packet-delay", "延迟", "<packet-delay>");
opts.optmulti("", "dns", "dns", "<dns>");
opts.optopt("f", "", "配置文件", "<conf>");
//"后台运行时,查看其他设备列表"
opts.optflag("", "list", "后台运行时,查看其他设备列表");
@@ -149,27 +151,14 @@ fn main() {
let server_address_str = matches
.opt_get_default("s", "nat1.wherewego.top:29872".to_string())
.unwrap();
let server_address = match server_address_str.to_socket_addrs() {
Ok(mut addr) => {
if let Some(addr) = addr.next() {
addr
} else {
println!("parameter '-s {}' error .", server_address_str);
return;
}
}
Err(e) => {
println!("parameter '-s {}' error {}.", server_address_str, e);
return;
}
};
let mut stun_server = matches.opt_strs("e");
if stun_server.is_empty() {
stun_server.push("stun1.l.google.com:19302".to_string());
stun_server.push("stun2.l.google.com:19302".to_string());
stun_server.push("stun.qq.com:3478".to_string());
}
let dns = matches.opt_strs("dns");
let in_ip = matches.opt_strs("i");
let in_ip = match ips_parse(&in_ip) {
Ok(in_ip) => in_ip,
@@ -304,8 +293,8 @@ fn main() {
token,
device_id,
name,
server_address,
server_address_str,
dns,
stun_server,
in_ip,
out_ip,
@@ -336,7 +325,12 @@ fn main() {
(config, cmd)
};
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);
}
@@ -346,11 +340,14 @@ mod callback;
fn main0(config: Config, show_cmd: bool) {
let vnt_util = Vnt::new(config, callback::VntHandler {}).unwrap();
let vnt_c = vnt_util.clone();
thread::spawn(move || {
if let Err(e) = command::server::CommandServer::new().start(vnt_c) {
log::warn!("cmd:{:?}", e);
}
});
thread::Builder::new()
.name("CommandServer".into())
.spawn(move || {
if let Err(e) = command::server::CommandServer::new().start(vnt_c) {
log::warn!("cmd:{:?}", e);
}
})
.expect("CommandServer");
if show_cmd {
let mut cmd = String::new();
loop {
@@ -406,6 +403,7 @@ fn command(cmd: &str, vnt: &Vnt) -> bool {
fn print_usage(program: &str, _opts: Options) {
println!("Usage: {} [options]", program);
println!("version:{}", vnt::VNT_VERSION);
println!("Serial:{}", generated_serial_number::SERIAL_NUMBER);
println!("Options:");
println!(
" -k <token> {}",
@@ -413,7 +411,7 @@ fn print_usage(program: &str, _opts: Options) {
);
println!(" -n <name> 给设备一个名字,便于区分不同设备,默认使用系统版本");
println!(" -d <id> 设备唯一标识符,不使用--ip参数时,服务端凭此参数分配虚拟ip,注意不能重复");
println!(" -s <server> 注册和中继服务器地址");
println!(" -s <server> 注册和中继服务器地址,以'TXT:'开头表示解析TXT记录");
println!(" -e <stun-server> stun服务器,用于探测NAT类型,可多次指定,如-e addr1 -e addr2");
println!(" -a 使用tap模式,默认使用tun模式");
println!(" -i <in-ip> 配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3表示允许接收网段192.168.0.0/24的数据");
@@ -476,6 +474,7 @@ fn print_usage(program: &str, _opts: Options) {
println!(
" --packet-delay <0> 模拟延迟,整数,单位毫秒(ms),程序会按设定的值延迟发包,可用于模拟弱网"
);
println!(" --dns <host:port> DNS服务器地址,可使用多个dns,默认使用114.114.114.114和8.8.8.8");
println!();
println!(
@@ -8,8 +8,14 @@ import top.wherewego.vnt.jni.param.*;
* @author https://github.com/lbl8603/vnt
*/
public interface CallBack {
/**
* 连接成功的回调
*/
void success();
/**
* 创建虚拟网卡成功的回调方法
* 仅在 windows/linux/macos上使用
*
* @param info 网卡信息
*/
@@ -38,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);
/**
* 异常回调
*
+42 -6
View File
@@ -50,6 +50,10 @@ public class Config {
* 服务端地址
*/
private String server;
/**
* dns地址
*/
private String[] dns;
/**
* stun服务地址
*/
@@ -87,9 +91,17 @@ public class Config {
*/
private String deviceName;
/**
* 虚拟网卡fd 仅在android上支持
* enum: relay/p2p/all
*/
private int deviceFd;
private String useChannel;
/**
* 模拟丢包率,取0~1之间的数,为null表示不丢包,1表示全部丢包
*/
private Double packetLossRate;
/**
* 模拟延迟 单位毫秒(ms)
*/
private Integer packetDelay;
public Config() {
}
@@ -182,6 +194,14 @@ public class Config {
this.server = server;
}
public String[] getDns() {
return dns;
}
public void setDns(String[] dns) {
this.dns = dns;
}
public String[] getStunServer() {
return stunServer;
}
@@ -254,11 +274,27 @@ public class Config {
this.deviceName = deviceName;
}
public int getDeviceFd() {
return deviceFd;
public String getUseChannel() {
return useChannel;
}
public void setDeviceFd(int deviceFd) {
this.deviceFd = deviceFd;
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,10 +1,17 @@
package top.wherewego.vnt.jni;
/**
* @author lubeilin
* @date: 2024/02/27 18:31
* ip转换
*
* @author https://github.com/lbl8603/vnt
*/
public class IpUtils {
/**
* 将整数的ip地址转成字符串,例如 0 转成 "0.0.0.0"
*
* @param ipAddress
* @return
*/
public static String intToIpAddress(int ipAddress) {
return ((ipAddress & 0xFF000000) >>> 24) + "." +
@@ -12,6 +19,13 @@ public class IpUtils {
((ipAddress & 0x0000FF00) >>> 8) + "." +
(ipAddress & 0x000000FF);
}
/**
* 返回掩码的长度
*
* @param subnetMask
* @return
*/
public static int subnetMaskToPrefixLength(int subnetMask) {
int prefixLength = 0;
int bit = 1 << 31;
@@ -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 -5
View File
@@ -11,9 +11,9 @@ 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){
if (this.raw == 0) {
throw new RuntimeException();
}
}
@@ -26,11 +26,11 @@ public class Vnt implements Closeable {
wait0(raw);
}
public PeerDeviceInfo[] list() {
public PeerRouteInfo[] list() {
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);
@@ -38,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,72 @@
package top.wherewego.vnt.jni.param;
import top.wherewego.vnt.jni.IpUtils;
import java.util.Arrays;
/**
* 创建网卡所需信息,仅在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 final String[] externalRoute;
public DeviceConfig(int virtualIp, int virtualNetmask, int virtualGateway, int virtualNetwork, String[] externalRoute) {
this.virtualIp = virtualIp;
this.virtualNetmask = virtualNetmask;
this.virtualGateway = virtualGateway;
this.virtualNetwork = virtualNetwork;
this.externalRoute = externalRoute;
}
public int getVirtualIp() {
return virtualIp;
}
public int getVirtualNetmask() {
return virtualNetmask;
}
public int getVirtualGateway() {
return virtualGateway;
}
public int getVirtualNetwork() {
return virtualNetwork;
}
public String[] getExternalRoute() {
return externalRoute;
}
@Override
public String toString() {
return "DeviceConfig{" +
"virtualIp=" + IpUtils.intToIpAddress(virtualIp) +
", virtualNetmask=" + IpUtils.intToIpAddress(virtualNetmask) +
", virtualGateway=" + IpUtils.intToIpAddress(virtualGateway) +
", virtualNetwork=" + IpUtils.intToIpAddress(virtualNetwork) +
", externalRoute=" + Arrays.toString(externalRoute) +
'}';
}
}
@@ -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) + '\'' +
'}';
}
}
+156 -21
View File
@@ -1,35 +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 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()),
@@ -45,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 _),
@@ -63,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)?,
@@ -80,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),
@@ -98,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(u32::from(info.virtual_ip) as _),
JValue::Int(u32::from(info.virtual_netmask) as _),
JValue::Int(u32::from(info.virtual_gateway) as _),
],
)?;
let rs = env.call_method(
@@ -116,16 +172,78 @@ 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 object_array = env.new_object_array(
info.external_route.len() as _,
"java/lang/String",
JObject::null(),
)?;
for (index, (network, mask)) in info.external_route.into_iter().enumerate() {
let param =
env.new_string(format!("{}/{}", network, u32::from(mask).leading_ones()))?;
env.set_object_array_element(&object_array, index as _, &param)?;
}
let param = env.new_object(
class,
"(IIII[Ljava/lang/String;)V",
&[
JValue::Int(u32::from(info.virtual_ip) as _),
JValue::Int(u32::from(info.virtual_netmask) as _),
JValue::Int(u32::from(info.virtual_gateway) as _),
JValue::Int(u32::from(info.virtual_network) as _),
JValue::Object(&object_array),
],
)?;
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(u32::from(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())],
)?;
@@ -138,15 +256,19 @@ impl CallBack {
Ok(())
}
fn stop0(&self) -> jni::errors::Result<()> {
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
env.call_method(&self.this, "error", "()V", &[])?;
let mut env = self.jvm.attach_current_thread_as_daemon()?;
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);
}
}
#[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);
@@ -172,6 +294,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) {
+9 -27
View File
@@ -1,4 +1,3 @@
use std::net::ToSocketAddrs;
use std::str::FromStr;
use jni::errors::Error;
@@ -21,6 +20,7 @@ pub fn new_config(env: &mut JNIEnv, config: JObject) -> Result<Config, Error> {
let password = to_string(env, &config, "password")?;
let server_address_str = to_string_not_null(env, &config, "server")?;
let stun_server = to_string_array_not_null(env, &config, "stunServer")?;
let dns = to_string_array(env, &config, "dns")?.unwrap_or_else(|| vec![]);
let cipher_model = to_string_not_null(env, &config, "cipherModel")?;
let punch_model = to_string(env, &config, "punchModel")?;
let mtu = to_integer(env, &config, "mtu")?.map(|v| v as u32);
@@ -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 =
@@ -73,25 +78,6 @@ pub fn new_config(env: &mut JNIEnv, config: JObject) -> Result<Config, Error> {
vec![]
};
let server_address = match server_address_str.to_socket_addrs() {
Ok(mut rs) => {
if let Some(addr) = rs.next() {
addr
} else {
env.throw_new("java/lang/RuntimeException", "server address err")
.expect("throw");
return Err(Error::JavaException);
}
}
Err(e) => {
env.throw_new(
"java/lang/RuntimeException",
format!("server address {}", e),
)
.expect("throw");
return Err(Error::JavaException);
}
};
let cipher_model = match CipherModel::from_str(&cipher_model) {
Ok(cipher_model) => cipher_model,
Err(e) => {
@@ -102,16 +88,14 @@ 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,
token,
device_id,
name,
server_address,
server_address_str,
dns,
stun_server,
in_ips,
out_ips,
@@ -129,11 +113,9 @@ 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(),
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 _,
));
}
+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),
+3
View File
@@ -31,6 +31,9 @@ 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"
anyhow = "1.0.82"
dns-parser = "0.8.0"
[target.'cfg(target_os = "windows")'.dependencies]
libloading = "0.8.0"
+68 -53
View File
@@ -1,66 +1,81 @@
syntax = "proto3";
message HandshakeRequest{
string version = 1;
bool secret = 2;
message HandshakeRequest {
string version = 1;
bool secret = 2;
string key_finger = 3;
}
message HandshakeResponse{
string version = 1;
bool secret = 2;
bytes public_key = 3;
string key_finger = 4;
message HandshakeResponse {
string version = 1;
bool secret = 2;
bytes public_key = 3;
string key_finger = 4;
}
message SecretHandshakeRequest{
string token = 1;
bytes key = 2;
message SecretHandshakeRequest {
string token = 1;
bytes key = 2;
}
message RegistrationRequest{
string token = 1;
string device_id = 2;
string name = 3;
bool is_fast = 4;
string version = 5;
fixed32 virtual_ip = 6;
bool allow_ip_change = 7;
bool client_secret = 8;
message RegistrationRequest {
string token = 1;
string device_id = 2;
string name = 3;
bool is_fast = 4;
string version = 5;
fixed32 virtual_ip = 6;
bool allow_ip_change = 7;
bool client_secret = 8;
bytes client_secret_hash = 9;
}
message RegistrationResponse{
fixed32 virtual_ip = 1;
fixed32 virtual_gateway = 2;
fixed32 virtual_netmask = 3;
uint32 epoch = 4;
repeated DeviceInfo device_info_list = 5;
fixed32 public_ip = 6;
uint32 public_port = 7;
bytes public_ipv6 = 8;
message RegistrationResponse {
fixed32 virtual_ip = 1;
fixed32 virtual_gateway = 2;
fixed32 virtual_netmask = 3;
uint32 epoch = 4;
repeated DeviceInfo device_info_list = 5;
fixed32 public_ip = 6;
uint32 public_port = 7;
bytes public_ipv6 = 8;
}
message DeviceInfo{
string name = 1;
fixed32 virtual_ip = 2;
uint32 device_status = 3;
bool client_secret = 4;
message DeviceInfo {
string name = 1;
fixed32 virtual_ip = 2;
uint32 device_status = 3;
bool client_secret = 4;
bytes client_secret_hash = 5;
}
message DeviceList{
uint32 epoch = 1;
repeated DeviceInfo device_info_list = 2;
message DeviceList {
uint32 epoch = 1;
repeated DeviceInfo device_info_list = 2;
}
message PunchInfo{
repeated fixed32 public_ip_list = 2;
uint32 public_port = 3;
uint32 public_port_range = 4;
PunchNatType nat_type = 5;
bool reply = 6;
fixed32 local_ip = 7;
uint32 local_port = 8;
bytes ipv6 = 9;
uint32 ipv6_port = 10;
uint32 tcp_port = 11;
repeated uint32 udp_ports = 12;
repeated uint32 public_ports = 13;
message PunchInfo {
repeated fixed32 public_ip_list = 2;
uint32 public_port = 3;
uint32 public_port_range = 4;
PunchNatType nat_type = 5;
bool reply = 6;
fixed32 local_ip = 7;
uint32 local_port = 8;
bytes ipv6 = 9;
uint32 ipv6_port = 10;
uint32 tcp_port = 11;
repeated uint32 udp_ports = 12;
repeated uint32 public_ports = 13;
}
enum PunchNatType{
Symmetric = 0;
Cone = 1;
enum PunchNatType {
Symmetric = 0;
Cone = 1;
}
/// 向服务器上报客户端状态信息
message ClientStatusInfo {
fixed32 source = 1;
repeated RouteItem p2p_list = 2;
uint64 up_stream = 3;
uint64 down_stream = 4;
PunchNatType nat_type = 5;
}
message RouteItem {
fixed32 next_ip = 1;
}
+36 -44
View File
@@ -28,6 +28,7 @@ impl Context {
is_tcp: bool,
packet_loss_rate: Option<f64>,
packet_delay: u32,
use_ipv6: bool,
) -> Self {
let channel_num = main_udp_socket.len();
assert_ne!(channel_num, 0, "not channel");
@@ -51,6 +52,7 @@ impl Context {
packet_loss_rate,
packet_delay,
main_index: AtomicUsize::new(0),
use_ipv6,
};
Self {
inner: Arc::new(inner),
@@ -70,8 +72,9 @@ impl Deref for Context {
}
/// 对称网络增加的udp socket数目,有助于增加打洞成功率
pub const SYMMETRIC_CHANNEL_NUM: usize = 64;
pub const SYMMETRIC_CHANNEL_NUM: usize = 100;
const PACKET_LOSS_RATE_DENOMINATOR: u32 = 100_0000;
pub struct ContextInner {
// 核心udp socket
pub(crate) main_udp_socket: Vec<UdpSocket>,
@@ -90,6 +93,7 @@ pub struct ContextInner {
//控制延迟
packet_delay: u32,
main_index: AtomicUsize,
use_ipv6: bool,
}
impl ContextInner {
@@ -172,15 +176,16 @@ impl ContextInner {
}
}
pub fn send_main_udp(&self, index: usize, buf: &[u8], mut addr: SocketAddr) -> io::Result<()> {
//核心udp socket都是ipv6模式,如果是v4地址则需要转换成v6
//只有服务器地址可能需要这样转换
if let SocketAddr::V4(ipv4) = addr {
addr = SocketAddr::V6(SocketAddrV6::new(
ipv4.ip().to_ipv6_mapped(),
ipv4.port(),
0,
0,
));
if self.use_ipv6 {
//如果是v4地址则需要转换成v6
if let SocketAddr::V4(ipv4) = addr {
addr = SocketAddr::V6(SocketAddrV6::new(
ipv4.ip().to_ipv6_mapped(),
ipv4.port(),
0,
0,
));
}
}
self.main_udp_socket[index].send_to(buf, addr)?;
Ok(())
@@ -194,6 +199,7 @@ impl ContextInner {
self.send_main_udp(self.main_index.load(Ordering::Relaxed), buf, addr)
}
}
pub fn change_main_index(&self) {
let index = (self.main_index.load(Ordering::Relaxed) + 1) % self.main_udp_socket.len();
self.main_index.store(index, Ordering::Relaxed);
@@ -208,17 +214,9 @@ impl ContextInner {
thread::sleep(Duration::from_millis(1));
}
}
pub fn try_send_all_main(&self, buf: &[u8], mut addr: SocketAddr) {
if let SocketAddr::V4(ipv4) = addr {
addr = SocketAddr::V6(SocketAddrV6::new(
ipv4.ip().to_ipv6_mapped(),
ipv4.port(),
0,
0,
));
}
for udp in &self.main_udp_socket {
if let Err(e) = udp.send_to(buf, addr) {
pub fn try_send_all_main(&self, buf: &[u8], addr: SocketAddr) {
for index in 0..self.channel_num() {
if let Err(e) = self.send_main_udp(index, buf, addr) {
log::warn!("{:?},add={:?}", e, addr);
}
}
@@ -229,6 +227,7 @@ impl ContextInner {
buf: &[u8],
id: &Ipv4Addr,
server_addr: SocketAddr,
send_default: bool,
) -> io::Result<()> {
if self.packet_loss_rate > 0 {
if rand::thread_rng().gen_ratio(self.packet_loss_rate, PACKET_LOSS_RATE_DENOMINATOR) {
@@ -243,7 +242,7 @@ impl ContextInner {
if e.kind() != io::ErrorKind::NotFound {
log::warn!("{}:{:?}", id, e);
}
if !self.route_table.use_channel_type.is_only_p2p() {
if !self.route_table.use_channel_type.is_only_p2p() && send_default {
//符合条件再发到服务器转发
self.send_default(buf, server_addr)?;
}
@@ -292,15 +291,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)
}
}
@@ -464,14 +455,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>)> {
@@ -485,9 +481,10 @@ impl RouteTable {
let table = self.route_table.read();
let mut list = Vec::with_capacity(8);
for (ip, (_, routes)) in table.iter() {
if let Some((route, _)) = routes.first() {
for (route, _) in routes.iter() {
if route.is_p2p() {
list.push((*ip, *route));
break;
}
}
}
@@ -503,18 +500,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;
}
}
/// 更新路由入栈包的时刻,长时间没有收到数据的路由将会被剔除
+42 -18
View File
@@ -154,16 +154,31 @@ pub fn init_context(
) -> io::Result<(Context, mio::net::TcpListener)> {
assert!(!ports.is_empty(), "not channel");
let mut udps = Vec::with_capacity(ports.len());
//检查系统是否支持ipv6
let use_ipv6 = match socket2::Socket::new(socket2::Domain::IPV6, socket2::Type::DGRAM, None) {
Ok(_) => true,
Err(e) => {
log::warn!("{:?}", e);
false
}
};
for port in &ports {
//监听v6+v4双栈
let address: SocketAddr = format!("[::]:{}", port).parse().unwrap();
let socket = socket2::Socket::new(socket2::Domain::IPV6, socket2::Type::DGRAM, None)?;
io_convert(socket.set_only_v6(false), |_| {
format!("set_only_v6 failed: {}", &address)
})?;
io_convert(socket.set_reuse_address(true), |_| {
format!("set_reuse_address failed: {}", &address)
})?;
let (socket, address) = if use_ipv6 {
let address: SocketAddr = format!("[::]:{}", port).parse().unwrap();
let socket = socket2::Socket::new(socket2::Domain::IPV6, socket2::Type::DGRAM, None)?;
io_convert(socket.set_only_v6(false), |_| {
format!("set_only_v6 failed: {}", &address)
})?;
(socket, address)
} else {
let address: SocketAddr = format!("0.0.0.0:{}", port).parse().unwrap();
(
socket2::Socket::new(socket2::Domain::IPV4, socket2::Type::DGRAM, None)?,
address,
)
};
io_convert(socket.set_send_buffer_size(2 * 1024 * 1024), |_| {
format!("set_send_buffer_size failed: {}", &address)
})?;
@@ -174,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(
@@ -184,23 +198,33 @@ pub fn init_context(
is_tcp,
packet_loss_rate,
packet_delay,
use_ipv6,
);
let port = context.main_local_udp_port()?[0];
//监听v6+v4双栈,tcp通道使用异步io
let address: SocketAddr = format!("[::]:{}", port).parse().unwrap();
let socket = socket2::Socket::new(socket2::Domain::IPV6, socket2::Type::STREAM, None)?;
io_convert(socket.set_only_v6(false), |_| {
format!("set_only_v6 failed: {}", &address)
})?;
io_convert(socket.set_reuse_address(true), |_| {
format!("set_reuse_address failed: {}", &address)
})?;
let (socket, address) = if use_ipv6 {
let address: SocketAddr = format!("[::]:{}", port).parse().unwrap();
let socket = socket2::Socket::new(socket2::Domain::IPV6, socket2::Type::STREAM, None)?;
io_convert(socket.set_only_v6(false), |_| {
format!("set_only_v6 failed: {}", &address)
})?;
(socket, address)
} else {
let address: SocketAddr = format!("0.0.0.0:{}", port).parse().unwrap();
let socket = socket2::Socket::new(socket2::Domain::IPV4, socket2::Type::STREAM, None)?;
(socket, address)
};
if let Err(e) = socket.bind(&address.into()) {
if ports[0] == 0 {
//端口可能冲突,则使用任意端口
log::warn!("监听tcp端口失败 {:?},重试一次", address);
let address: SocketAddr = format!("[::]:{}", 0).parse().unwrap();
let address: SocketAddr = if use_ipv6 {
format!("[::]:{}", 0).parse().unwrap()
} else {
format!("0.0.0.0:{}", port).parse().unwrap()
};
io_convert(socket.bind(&address.into()), |_| {
format!("bind failed: {}", &address)
})?;
+35 -24
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(());
}
}
}
@@ -301,25 +311,26 @@ impl Punch {
}
let start = *self.port_index.entry(id.clone()).or_insert(0);
let mut end = start + max_k2;
let mut index = end;
if end >= self.port_vec.len() {
if end > self.port_vec.len() {
end = self.port_vec.len();
}
let mut index = start
+ self.punch_symmetric(
&self.port_vec[start..end],
buf,
&nat_info.public_ips,
max_k2,
)?;
if index >= self.port_vec.len() {
index = 0
}
self.punch_symmetric(
&self.port_vec[start..end],
buf,
&nat_info.public_ips,
max_k2,
)?;
self.port_index.insert(id, index);
}
NatType::Cone => {
let is_cone = self.context.is_cone();
for index in 0..channel_num {
let len = nat_info.public_ports.len();
'a: for index in 0..nat_info.public_ports.len().min(channel_num) {
for ip in &nat_info.public_ips {
let port = nat_info.public_ports[index % len];
let port = nat_info.public_ports[index];
if port == 0 || ip.is_unspecified() {
continue;
}
@@ -334,7 +345,7 @@ impl Punch {
}
if !is_cone {
//对称网络数据只发一遍
break;
break 'a;
}
}
}
@@ -348,19 +359,19 @@ impl Punch {
buf: &[u8],
ips: &Vec<Ipv4Addr>,
max: usize,
) -> io::Result<()> {
) -> io::Result<usize> {
let mut count = 0;
for port in ports {
for (index, port) in ports.iter().enumerate() {
for pub_ip in ips {
count += 1;
if count == max {
return Ok(());
return Ok(index);
}
let addr = SocketAddr::V4(SocketAddrV4::new(*pub_ip, *port));
self.context.send_main_udp(0, buf, addr)?;
thread::sleep(Duration::from_millis(2));
}
}
Ok(())
Ok(ports.len())
}
}
+2 -2
View File
@@ -49,7 +49,7 @@ where
};
thread::Builder::new()
.name("tcp读事件处理线程".into())
.name("tcpRead".into())
.spawn(move || {
if let Err(e) = tcp_listen0(
poll,
@@ -173,7 +173,7 @@ fn init_writable_handler(
{
let writable_notify = writable_notify.clone();
thread::Builder::new()
.name("tcp-writeable-listen".into())
.name("tcpWriteableListen".into())
.spawn(move || {
if let Err(e) = tcp_writable_listen(receiver, poll, writable_notify, &context) {
log::error!("{:?}", e);
+78 -5
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;
@@ -49,7 +48,7 @@ where
};
let accept = AcceptSocketSender::new(waker.clone(), udp_sender);
thread::Builder::new()
.name("sub_udp读事件处理线程".into())
.name("subUdp".into())
.spawn(move || {
if let Err(e) = sub_udp_listen0(poll, recv_handler, context, waker, udp_receiver) {
log::error!("{:?}", e);
@@ -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();
@@ -153,7 +220,7 @@ where
}
})?;
thread::Builder::new()
.name("main_udp".into())
.name("mainUdp".into())
.spawn(move || {
if let Err(e) = main_udp_listen0(poll, recv_handler, context) {
log::error!("{:?}", e);
@@ -188,8 +255,14 @@ where
NOTIFY => return Ok(()),
Token(index) => index - 1,
};
let udp = if let Some(udp) = udps.get(index) {
udp
} else {
log::error!("{:?}", x);
continue;
};
loop {
match udps[index].recv_from(&mut buf) {
match udp.recv_from(&mut buf) {
Ok((len, addr)) => {
recv_handler.handle(
&mut buf[..len],
+13
View File
@@ -1,6 +1,7 @@
#[cfg(feature = "aes_ecb")]
#[cfg(not(any(feature = "openssl-vendored", feature = "openssl")))]
use crate::cipher::aes_ecb::AesEcbCipher;
use std::fmt::Display;
#[cfg(feature = "aes_cbc")]
use crate::cipher::aes_cbc::AesCbcCipher;
@@ -48,6 +49,18 @@ pub enum CipherModel {
None,
}
impl Display for CipherModel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let str = match self {
CipherModel::AesGcm => "aes_gcm".to_string(),
CipherModel::AesCbc => "aes_cbc".to_string(),
CipherModel::AesEcb => "aes_ecb".to_string(),
CipherModel::Sm4Cbc => "sm4_cbc".to_string(),
CipherModel::None => "none".to_string(),
};
write!(f, "{}", str)
}
}
impl FromStr for CipherModel {
type Err = String;
+25 -19
View File
@@ -1,5 +1,5 @@
use crate::protocol::NetPacket;
use std::io;
use {
crate::protocol::body::{RsaSecretBody, RSA_ENCRYPTION_RESERVED},
rand::Rng,
@@ -9,6 +9,8 @@ use {
spki::{DecodePublicKey, EncodePublicKey},
};
use crate::protocol::NetPacket;
#[derive(Clone)]
pub struct RsaCipher {
inner: Inner,
@@ -16,13 +18,15 @@ pub struct RsaCipher {
#[derive(Clone)]
struct Inner {
public_key: RsaPublicKey,
finger: String,
}
impl RsaCipher {
pub fn new(der: &[u8]) -> io::Result<Self> {
match RsaPublicKey::from_public_key_der(der) {
Ok(public_key) => {
let inner = Inner { public_key };
let finger = finger(&public_key)?;
let inner = Inner { public_key, finger };
Ok(Self { inner })
}
Err(e) => Err(io::Error::new(
@@ -31,30 +35,32 @@ impl RsaCipher {
)),
}
}
pub fn finger(&self) -> io::Result<String> {
match self.inner.public_key.to_public_key_der() {
Ok(der) => match rsa::pkcs8::SubjectPublicKeyInfoRef::from_der(der.as_bytes()) {
Ok(spki) => match spki.fingerprint_base64() {
Ok(finger) => Ok(finger),
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("fingerprint_base64 error {}", e),
)),
},
pub fn finger(&self) -> &String {
&self.inner.finger
}
pub fn public_key(&self) -> io::Result<&RsaPublicKey> {
return Ok(&self.inner.public_key);
}
}
pub fn finger(public_key: &RsaPublicKey) -> io::Result<String> {
match public_key.to_public_key_der() {
Ok(der) => match rsa::pkcs8::SubjectPublicKeyInfoRef::from_der(der.as_bytes()) {
Ok(spki) => match spki.fingerprint_base64() {
Ok(finger) => Ok(finger),
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("from_der error {}", e),
format!("fingerprint_base64 error {}", e),
)),
},
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("to_public_key_der error {}", e),
format!("from_der error {}", e),
)),
}
}
pub fn public_key(&self) -> io::Result<&RsaPublicKey> {
return Ok(&self.inner.public_key);
},
Err(e) => Err(io::Error::new(
io::ErrorKind::Other,
format!("to_public_key_der error {}", e),
)),
}
}
+70 -27
View File
@@ -7,7 +7,8 @@ use std::time::Duration;
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::{Mutex, RwLock};
use rand::Rng;
use rsa::signature::digest::Digest;
#[cfg(not(target_os = "android"))]
use tun::device::IFace;
use crate::channel::context::Context;
@@ -22,14 +23,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 {
@@ -42,6 +44,7 @@ pub struct Vnt {
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
down_count_watcher: WatchU64Adder,
up_count_watcher: WatchSingleU64Adder,
client_secret_hash: Option<[u8; 16]>,
}
impl Vnt {
@@ -78,9 +81,18 @@ impl Vnt {
config.name.clone(),
config.token.clone(),
config.ip,
config.password.is_some(),
config.password.as_ref().map(|v| {
let mut hasher = sha2::Sha256::new();
hasher.update(config.cipher_model.to_string().as_bytes());
hasher.update(v.as_bytes());
hasher.update(config.token.as_bytes());
let key: [u8; 32] = hasher.finalize().into();
key[16..].try_into().unwrap()
}),
config.server_encrypt,
config.device_id.clone(),
config.server_address_str.clone(),
config.name_servers.clone(),
);
let ports = config.ports.as_ref().map_or(vec![0, 0], |v| {
if v.is_empty() {
@@ -112,10 +124,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();
@@ -144,14 +160,34 @@ impl Vnt {
let down_counter =
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();
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(),
@@ -176,21 +212,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,
)?;
#[cfg(not(target_os = "android"))]
tun_helper.start(device)?;
maintain::idle_gateway(
&scheduler,
context.clone(),
@@ -205,6 +230,9 @@ impl Vnt {
let context = context.clone();
let nat_test = nat_test.clone();
let device_list = device_list.clone();
let down_count_watcher = down_count_watcher.clone();
let up_count_watcher = up_count_watcher.clone();
let config_info = config_info.clone();
let current_device = current_device.clone();
if !config.use_channel_type.is_only_relay() {
// 定时nat探测
@@ -229,6 +257,8 @@ impl Vnt {
config_info,
punch,
callback,
down_count_watcher,
up_count_watcher,
);
});
}
@@ -243,6 +273,7 @@ impl Vnt {
peer_nat_info_map,
down_count_watcher,
up_count_watcher,
client_secret_hash: config_info.client_secret_hash,
})
}
}
@@ -259,6 +290,8 @@ pub fn start<Call: VntCallback>(
config_info: BaseConfigInfo,
punch: Punch,
callback: Call,
down_count_watcher: WatchU64Adder,
up_count_watcher: WatchSingleU64Adder,
) {
// 定时心跳
maintain::heartbeat(
@@ -310,6 +343,13 @@ pub fn start<Call: VntCallback>(
punch,
);
}
maintain::up_status(
scheduler,
context.clone(),
current_device.clone(),
down_count_watcher,
up_count_watcher,
)
}
impl Vnt {
@@ -322,6 +362,9 @@ impl Vnt {
pub fn client_encrypt(&self) -> bool {
self.config.password.is_some()
}
pub fn client_encrypt_hash(&self) -> Option<&[u8]> {
self.client_secret_hash.as_ref().map(|v| v.as_ref())
}
pub fn current_device(&self) -> CurrentDeviceInfo {
self.current_device.load()
}
+24 -12
View File
@@ -1,11 +1,13 @@
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use anyhow::anyhow;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
use std::str::FromStr;
pub use conn::Vnt;
use crate::channel::punch::PunchModel;
use crate::channel::UseChannelType;
use crate::cipher::CipherModel;
use crate::util::{address_choose, dns_query_all};
mod conn;
@@ -18,6 +20,7 @@ pub struct Config {
pub name: String,
pub server_address: SocketAddr,
pub server_address_str: String,
pub name_servers: Vec<String>,
pub stun_server: Vec<String>,
pub in_ips: Vec<(u32, u32, Ipv4Addr)>,
pub out_ips: Vec<(u32, u32)>,
@@ -36,8 +39,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>,
@@ -50,8 +51,8 @@ impl Config {
token: String,
device_id: String,
name: String,
server_address: SocketAddr,
server_address_str: String,
mut name_servers: Vec<String>,
mut stun_server: Vec<String>,
in_ips: Vec<(u32, u32, Ipv4Addr)>,
out_ips: Vec<(u32, u32)>,
@@ -68,25 +69,37 @@ 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,
) -> io::Result<Self> {
) -> anyhow::Result<Self> {
for x in stun_server.iter_mut() {
if !x.contains(":") {
x.push_str(":3478");
}
}
for x in name_servers.iter_mut() {
if Ipv6Addr::from_str(x).is_ok() {
x.push_str(":53");
} else if !x.contains(":") {
x.push_str(":53");
}
}
if token.is_empty() || token.len() > 128 {
return Err(io::Error::new(io::ErrorKind::Other, "token too long"));
return Err(anyhow!("token too long"));
}
if device_id.is_empty() || device_id.len() > 128 {
return Err(io::Error::new(io::ErrorKind::Other, "device_id too long"));
return Err(anyhow!("device_id too long"));
}
if name.is_empty() || name.len() > 128 {
return Err(io::Error::new(io::ErrorKind::Other, "name too long"));
return Err(anyhow!("name too long"));
}
if name_servers.is_empty() {
name_servers.push("114.114.114.114:53".to_string());
name_servers.push("8.8.8.8:53".to_string());
}
let server_address =
address_choose(dns_query_all(&server_address_str, name_servers.clone())?)?;
Ok(Self {
#[cfg(any(target_os = "windows", target_os = "linux"))]
tap,
@@ -95,6 +108,7 @@ impl Config {
name,
server_address,
server_address_str,
name_servers,
stun_server,
in_ips,
out_ips,
@@ -113,8 +127,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) {}
/// 服务停止
+32 -27
View File
@@ -4,6 +4,7 @@ use std::sync::Arc;
use std::time::{Duration, Instant};
use crossbeam_utils::atomic::AtomicCell;
use parking_lot::Mutex;
use protobuf::Message;
use crate::channel::context::Context;
@@ -27,49 +28,53 @@ pub enum HandshakeEnum {
#[derive(Clone)]
pub struct Handshake {
time: Arc<AtomicCell<Instant>>,
rsa_cipher: Arc<Mutex<Option<RsaCipher>>>,
}
impl Handshake {
pub fn new() -> Self {
pub fn new(rsa_cipher: Arc<Mutex<Option<RsaCipher>>>) -> Self {
Handshake {
time: Arc::new(AtomicCell::new(Instant::now() - Duration::from_secs(60))),
rsa_cipher,
}
}
pub fn send(&self, context: &Context, secret: bool, addr: SocketAddr) -> io::Result<()> {
let last = self.time.load();
//短时间不重复发送
if last.elapsed() < Duration::from_secs(5) {
if last.elapsed() < Duration::from_secs(3) {
return Ok(());
}
let request_packet = handshake_request_packet(secret)?;
let request_packet = self.handshake_request_packet(secret)?;
log::info!("发送握手请求,secret={},{:?}", secret, addr);
context.send_default(request_packet.buffer(), addr)?;
self.time.store(Instant::now());
Ok(())
}
}
/// 第一次握手数据
pub fn handshake_request_packet(secret: bool) -> io::Result<NetPacket<Vec<u8>>> {
let mut request = HandshakeRequest::new();
request.secret = secret;
request.version = crate::VNT_VERSION.to_string();
let bytes = request.write_to_bytes().map_err(|e| {
io::Error::new(
io::ErrorKind::Other,
format!("handshake_request_packet {:?}", e),
)
})?;
let buf = vec![0u8; 12 + bytes.len()];
let mut net_packet = NetPacket::new(buf)?;
net_packet.set_version(Version::V1);
net_packet.set_gateway_flag(true);
net_packet.set_destination(GATEWAY_IP);
net_packet.set_source(SELF_IP);
net_packet.set_protocol(Protocol::Service);
net_packet.set_transport_protocol(service_packet::Protocol::HandshakeRequest.into());
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_payload(&bytes)?;
Ok(net_packet)
/// 第一次握手数据
pub fn handshake_request_packet(&self, secret: bool) -> io::Result<NetPacket<Vec<u8>>> {
let mut request = HandshakeRequest::new();
request.secret = secret;
request.version = crate::VNT_VERSION.to_string();
if let Some(finger) = self.rsa_cipher.lock().as_ref().map(|v| v.finger().clone()) {
request.key_finger = finger;
}
let bytes = request.write_to_bytes().map_err(|e| {
io::Error::new(
io::ErrorKind::Other,
format!("handshake_request_packet {:?}", e),
)
})?;
let buf = vec![0u8; 12 + bytes.len()];
let mut net_packet = NetPacket::new(buf)?;
net_packet.set_version(Version::V1);
net_packet.set_gateway_flag(true);
net_packet.set_destination(GATEWAY_IP);
net_packet.set_source(SELF_IP);
net_packet.set_protocol(Protocol::Service);
net_packet.set_transport_protocol(service_packet::Protocol::HandshakeRequest.into());
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_payload(&bytes)?;
Ok(net_packet)
}
}
/// 第二次加密握手
+18 -24
View File
@@ -1,4 +1,3 @@
use std::net::ToSocketAddrs;
use std::sync::Arc;
use std::time::Duration;
@@ -16,12 +15,25 @@ pub fn addr_request(
context: Context,
current_device_info: Arc<AtomicCell<CurrentDeviceInfo>>,
server_cipher: Cipher,
config: BaseConfigInfo,
_config: BaseConfigInfo,
) {
addr_request0(&context, &current_device_info, &server_cipher, &config);
pub_address_request(
scheduler,
context,
current_device_info.clone(),
server_cipher,
);
}
pub fn pub_address_request(
scheduler: &Scheduler,
context: Context,
current_device_info: Arc<AtomicCell<CurrentDeviceInfo>>,
server_cipher: Cipher,
) {
addr_request0(&context, &current_device_info, &server_cipher);
// 9秒发送一次
let rs = scheduler.timeout(Duration::from_secs(9), |s| {
addr_request(s, context, current_device_info, server_cipher, config)
pub_address_request(s, context, current_device_info, server_cipher)
});
if !rs {
log::info!("定时任务停止");
@@ -32,27 +44,9 @@ pub fn addr_request0(
context: &Context,
current_device: &AtomicCell<CurrentDeviceInfo>,
server_cipher: &Cipher,
config: &BaseConfigInfo,
) {
let mut current_dev = current_device.load();
// 探测服务端地址变化
if let Ok(mut addr) = config.server_addr.to_socket_addrs() {
if let Some(addr) = addr.next() {
if addr != current_dev.connect_server {
let mut tmp = current_dev.clone();
tmp.connect_server = addr;
let rs = current_device.compare_exchange(current_dev, tmp);
current_dev.connect_server = addr;
log::info!(
"服务端地址变化,旧地址:{},新地址:{},替换结果:{}",
current_dev.connect_server,
addr,
rs.is_ok()
);
}
}
}
if current_dev.connect_server.is_ipv4() {
let current_dev = current_device.load();
if current_dev.connect_server.is_ipv4() && current_dev.status.online() {
// 如果连接的是ipv4服务,则探测公网端口
let gateway_ip = current_dev.virtual_gateway;
let src_ip = current_dev.virtual_ip;
+2 -2
View File
@@ -12,7 +12,7 @@ use crate::cipher::Cipher;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
use crate::protocol::body::ENCRYPTION_RESERVED;
use crate::protocol::control_packet::PingPacket;
use crate::protocol::{control_packet, NetPacket, Protocol, Version, MAX_TTL};
use crate::protocol::{control_packet, NetPacket, Protocol, Version};
use crate::util::Scheduler;
/// 定时发送心跳包
@@ -216,7 +216,7 @@ fn heartbeat_packet(
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Control);
net_packet.set_transport_protocol(control_packet::Protocol::Ping.into());
net_packet.first_set_ttl(MAX_TTL);
net_packet.first_set_ttl(5);
net_packet.set_source(src);
net_packet.set_destination(dest);
let mut ping = PingPacket::new(net_packet.payload_mut())?;
+64 -13
View File
@@ -1,17 +1,19 @@
use std::io;
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Duration;
use crossbeam_utils::atomic::AtomicCell;
use mio::net::TcpStream;
use crate::channel::context::Context;
use crate::channel::idle::{Idle, IdleType};
use crate::channel::sender::AcceptSocketSender;
use crate::handle::callback::{ConnectInfo, ErrorType};
use crate::handle::handshaker::Handshake;
use crate::handle::{handshaker, BaseConfigInfo, ConnectStatus, CurrentDeviceInfo};
use crate::util::Scheduler;
use crate::handle::{BaseConfigInfo, ConnectStatus, CurrentDeviceInfo};
use crate::util::{address_choose, dns_query_all, Scheduler};
use crate::{ErrorInfo, VntCallback};
use crossbeam_utils::atomic::AtomicCell;
use mio::net::TcpStream;
use std::io;
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Duration;
pub fn idle_route<Call: VntCallback>(
scheduler: &Scheduler,
@@ -28,6 +30,7 @@ pub fn idle_route<Call: VntCallback>(
log::info!("定时任务停止");
}
}
pub fn idle_gateway<Call: VntCallback>(
scheduler: &Scheduler,
context: Context,
@@ -63,6 +66,7 @@ pub fn idle_gateway<Call: VntCallback>(
log::info!("定时任务停止");
}
}
fn idle_gateway0<Call: VntCallback>(
context: &Context,
current_device: &AtomicCell<CurrentDeviceInfo>,
@@ -86,9 +90,9 @@ fn idle_gateway0<Call: VntCallback>(
ErrorType::Disconnect,
format!("connect:{},error:{:?}", cur.connect_server, e),
));
log::warn!("{:?}", e);
}
}
fn idle_route0<Call: VntCallback>(
idle: &Idle,
context: &Context,
@@ -114,24 +118,26 @@ fn idle_route0<Call: VntCallback>(
fn check_gateway_channel<Call: VntCallback>(
context: &Context,
current_device: &AtomicCell<CurrentDeviceInfo>,
current_device_info: &AtomicCell<CurrentDeviceInfo>,
config: &BaseConfigInfo,
tcp_socket_sender: &AcceptSocketSender<(TcpStream, SocketAddr, Option<Vec<u8>>)>,
call: &Call,
count: &mut usize,
handshake: &Handshake,
) -> io::Result<()> {
let current_device = current_device.load();
let mut current_device = current_device_info.load();
if current_device.status.offline() {
*count += 1;
// 探测服务器地址
current_device = domain_request0(current_device_info, config);
//需要重连
call.connect(ConnectInfo::new(*count, current_device.connect_server));
log::info!("发送握手请求,{:?}", config);
if let Err(e) = handshake.send(context, config.client_secret, current_device.connect_server)
if let Err(e) = handshake.send(context, config.server_secret, current_device.connect_server)
{
log::warn!("{:?}", e);
if context.is_main_tcp() {
let request_packet = handshaker::handshake_request_packet(config.client_secret)?;
let request_packet = handshake.handshake_request_packet(config.server_secret)?;
//tcp需要重连
let tcp_stream = std::net::TcpStream::connect_timeout(
&current_device.connect_server,
@@ -150,3 +156,48 @@ fn check_gateway_channel<Call: VntCallback>(
}
Ok(())
}
pub fn domain_request0(
current_device: &AtomicCell<CurrentDeviceInfo>,
config: &BaseConfigInfo,
) -> CurrentDeviceInfo {
let mut current_dev = current_device.load();
// 探测服务端地址变化
match dns_query_all(&config.server_addr, config.name_servers.clone()) {
Ok(addrs) => {
log::info!(
"domain {} dns {:?} addr {:?}",
config.server_addr,
config.name_servers,
addrs
);
match address_choose(addrs) {
Ok(addr) => {
if addr != current_dev.connect_server {
let mut tmp = current_dev.clone();
tmp.connect_server = addr;
let rs = current_device.compare_exchange(current_dev, tmp);
log::info!(
"服务端地址变化,旧地址:{},新地址:{},替换结果:{}",
current_dev.connect_server,
addr,
rs.is_ok()
);
if rs.is_ok() {
current_dev.connect_server = addr;
}
}
}
Err(e) => {
log::error!("域名地址选择失败:{:?},domain={}", e, config.server_addr);
}
}
}
Err(e) => {
log::error!("域名解析失败:{:?},domain={}", e, config.server_addr);
}
}
current_dev
}
+3
View File
@@ -14,3 +14,6 @@ pub use punch::*;
mod idle;
pub use idle::idle_gateway;
pub use idle::idle_route;
mod up_status;
pub use up_status::*;
+141 -52
View File
@@ -1,4 +1,4 @@
use std::cmp::Ordering;
use std::collections::HashMap;
use std::net::Ipv4Addr;
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
use std::sync::Arc;
@@ -11,7 +11,7 @@ use protobuf::Message;
use rand::prelude::SliceRandom;
use crate::channel::context::Context;
use crate::channel::punch::{NatInfo, Punch};
use crate::channel::punch::{NatInfo, NatType, Punch};
use crate::cipher::Cipher;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
use crate::nat::NatTest;
@@ -24,31 +24,62 @@ use crate::util::Scheduler;
pub struct PunchSender {
sender_self: SyncSender<(Ipv4Addr, NatInfo)>,
sender_peer: SyncSender<(Ipv4Addr, NatInfo)>,
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 {
if src_peer {
self.sender_peer.send((ip, info)).is_ok()
} else {
self.sender_self.send((ip, info)).is_ok()
}
log::info!(
"发送打洞协商消息,是否对端发起:{},ip:{},info:{:?}",
src_peer,
ip,
info
);
let sender = match info.nat_type {
NatType::Symmetric => {
if src_peer {
&self.sender_peer
} else {
&self.sender_self
}
}
NatType::Cone => {
if src_peer {
&self.sender_cone_peer
} else {
&self.sender_cone_self
}
}
};
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_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,
sender_peer,
sender_cone_peer,
sender_cone_self,
},
PunchReceiver {
receiver_peer,
receiver_self,
receiver_cone_peer,
receiver_cone_self,
},
)
}
@@ -63,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,
@@ -71,20 +104,25 @@ pub fn punch(
current_device.clone(),
client_cipher.clone(),
0,
punch_record.clone(),
last_punch_record,
);
let receiver_peer = receiver.receiver_peer;
let receiver_self = receiver.receiver_self;
{
let f = |receiver: Receiver<(Ipv4Addr, NatInfo)>| {
let punch = punch.clone();
let current_device = current_device.clone();
let client_cipher = client_cipher.clone();
thread::spawn(move || {
punch_start(receiver_peer, punch, current_device, client_cipher);
});
}
thread::spawn(move || {
punch_start(receiver_self, punch, current_device, client_cipher);
});
let punch_record = punch_record.clone();
thread::Builder::new()
.name("punch".into())
.spawn(move || {
punch_start(receiver, punch, current_device, client_cipher, punch_record);
})
.expect("punch");
};
f(receiver.receiver_peer);
f(receiver.receiver_self);
f(receiver.receiver_cone_peer);
f(receiver.receiver_cone_self);
}
/// 接收打洞消息,配合对端打洞
@@ -93,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();
@@ -102,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)
}
}
@@ -122,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(
@@ -142,6 +203,8 @@ fn punch_request(
current_device,
client_cipher,
count + 1,
punch_record,
last_punch_record,
);
});
if !rs {
@@ -156,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()
@@ -167,38 +243,51 @@ fn punch0(
.cloned()
.collect();
list.shuffle(&mut rand::thread_rng());
let mut count = 0;
// 优先没打洞的
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,
)?;
context.send_default(packet.buffer(), current_device.connect_server)?;
}
Ok(())
}
+19 -16
View File
@@ -25,21 +25,24 @@ fn retrieve_nat_type0(
nat_test: NatTest,
udp_socket_sender: AcceptSocketSender<Option<Vec<mio::net::UdpSocket>>>,
) {
thread::spawn(move || {
if nat_test.can_update() {
let local_ipv4 = nat::local_ipv4();
let local_ipv6 = nat::local_ipv6();
match nat_test.re_test(local_ipv4, local_ipv6) {
Ok(nat_info) => {
log::info!("当前nat信息:{:?}", nat_info);
if let Err(e) = context.switch(nat_info.nat_type, &udp_socket_sender) {
log::warn!("{:?}", e);
thread::Builder::new()
.name("natTest".into())
.spawn(move || {
if nat_test.can_update() {
let local_ipv4 = nat::local_ipv4();
let local_ipv6 = nat::local_ipv6();
match nat_test.re_test(local_ipv4, local_ipv6) {
Ok(nat_info) => {
log::info!("当前nat信息:{:?}", nat_info);
if let Err(e) = context.switch(nat_info.nat_type, &udp_socket_sender) {
log::warn!("{:?}", e);
}
}
}
Err(e) => {
log::warn!("nat re_test {:?}", e);
}
};
}
});
Err(e) => {
log::warn!("nat re_test {:?}", e);
}
};
}
})
.expect("natTest");
}
+104
View File
@@ -0,0 +1,104 @@
use crate::channel::context::Context;
use crate::handle::CurrentDeviceInfo;
use crate::proto::message::{ClientStatusInfo, PunchNatType, RouteItem};
use crate::protocol::body::ENCRYPTION_RESERVED;
use crate::protocol::{service_packet, NetPacket, Protocol, Version, HEAD_LEN, MAX_TTL};
use crate::util::{Scheduler, WatchSingleU64Adder, WatchU64Adder};
use crossbeam_utils::atomic::AtomicCell;
use protobuf::Message;
use std::io;
use std::sync::Arc;
use std::time::Duration;
/// 上报状态给服务器
pub fn up_status(
scheduler: &Scheduler,
context: Context,
current_device_info: Arc<AtomicCell<CurrentDeviceInfo>>,
down_count_watcher: WatchU64Adder,
up_count_watcher: WatchSingleU64Adder,
) {
let _ = scheduler.timeout(Duration::from_secs(60), move |x| {
up_status0(
x,
context,
current_device_info,
down_count_watcher,
up_count_watcher,
)
});
}
fn up_status0(
scheduler: &Scheduler,
context: Context,
current_device_info: Arc<AtomicCell<CurrentDeviceInfo>>,
down_count_watcher: WatchU64Adder,
up_count_watcher: WatchSingleU64Adder,
) {
if let Err(e) = send_up_status_packet(
&context,
&current_device_info,
&down_count_watcher,
&up_count_watcher,
) {
log::warn!("{:?}", e)
}
let rs = scheduler.timeout(Duration::from_secs(10 * 60), move |x| {
up_status0(
x,
context,
current_device_info,
down_count_watcher,
up_count_watcher,
)
});
if !rs {
log::info!("定时任务停止");
}
}
fn send_up_status_packet(
context: &Context,
current_device_info: &AtomicCell<CurrentDeviceInfo>,
down_count_watcher: &WatchU64Adder,
up_count_watcher: &WatchSingleU64Adder,
) -> io::Result<()> {
let device_info = current_device_info.load();
if device_info.status.offline() {
return Ok(());
}
let routes = context.route_table.route_table_p2p();
if routes.is_empty() {
return Ok(());
}
let mut message = ClientStatusInfo::new();
message.source = device_info.virtual_ip.into();
for (ip, _) in routes {
let mut item = RouteItem::new();
item.next_ip = ip.into();
message.p2p_list.push(item);
}
message.up_stream = up_count_watcher.get();
message.down_stream = down_count_watcher.get();
message.nat_type = protobuf::EnumOrUnknown::new(if context.is_cone() {
PunchNatType::Cone
} else {
PunchNatType::Symmetric
});
let buf = message
.write_to_bytes()
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("up_status_packet {:?}", e)))?;
let mut net_packet =
NetPacket::new_encrypt(vec![0; HEAD_LEN + buf.len() + ENCRYPTION_RESERVED])?;
net_packet.set_version(Version::V1);
net_packet.set_gateway_flag(true);
net_packet.set_protocol(Protocol::Service);
net_packet.set_transport_protocol_into(service_packet::Protocol::ClientStatusInfo);
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_source(device_info.virtual_ip);
net_packet.set_destination(device_info.virtual_gateway);
net_packet.set_payload(&buf)?;
context.send_default(net_packet.buffer(), device_info.connect_server)?;
Ok(())
}
+18 -4
View File
@@ -32,15 +32,23 @@ pub struct PeerDeviceInfo {
pub name: String,
pub status: PeerDeviceStatus,
pub client_secret: bool,
pub client_secret_hash: Vec<u8>,
}
impl PeerDeviceInfo {
pub fn new(virtual_ip: Ipv4Addr, name: String, status: u8, client_secret: bool) -> Self {
pub fn new(
virtual_ip: Ipv4Addr,
name: String,
status: u8,
client_secret: bool,
client_secret_hash: Vec<u8>,
) -> Self {
Self {
virtual_ip,
name,
status: PeerDeviceStatus::from(status),
client_secret,
client_secret_hash,
}
}
}
@@ -50,9 +58,11 @@ pub struct BaseConfigInfo {
pub name: String,
pub token: String,
pub ip: Option<Ipv4Addr>,
pub client_secret: bool,
pub client_secret_hash: Option<[u8; 16]>,
pub server_secret: bool,
pub device_id: String,
pub server_addr: String,
pub name_servers: Vec<String>,
}
impl BaseConfigInfo {
@@ -60,17 +70,21 @@ impl BaseConfigInfo {
name: String,
token: String,
ip: Option<Ipv4Addr>,
client_secret: bool,
client_secret_hash: Option<[u8; 16]>,
server_secret: bool,
device_id: String,
server_addr: String,
name_servers: Vec<String>,
) -> Self {
Self {
name,
token,
ip,
client_secret,
client_secret_hash,
server_secret,
device_id,
server_addr,
name_servers,
}
}
}
+10 -13
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>>>,
@@ -176,8 +175,8 @@ impl ClientPacketHandler {
net_packet.first_set_ttl(MAX_TTL);
self.client_cipher.encrypt_ipv4(&mut net_packet)?;
context.send_by_key(net_packet.buffer(), route_key)?;
// let route = Route::from_default_rt(route_key, metric);
// context.route_table.add_route_if_absent(source, route);
let route = Route::from_default_rt(route_key, metric);
context.route_table.add_route_if_absent(source, route);
}
ControlPacket::PongPacket(pong_packet) => {
let current_time = crate::handle::now_time() as u16;
@@ -320,13 +319,11 @@ impl ClientPacketHandler {
punch_packet.set_source(current_device.virtual_ip());
punch_packet.set_destination(source);
punch_packet.set_payload(&bytes)?;
log::info!("接收打洞请求={:?}", peer_nat_info);
self.client_cipher.encrypt_ipv4(&mut punch_packet)?;
if self.punch_sender.send(true, source, peer_nat_info) {
self.client_cipher.encrypt_ipv4(&mut punch_packet)?;
context.send_by_key(punch_packet.buffer(), route_key)?;
}
} else {
log::info!("接收打洞请求回复={:?}", peer_nat_info);
self.punch_sender.send(false, source, peer_nat_info);
}
}
+3 -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,
@@ -111,6 +110,7 @@ impl<Call: VntCallback> RecvDataHandler<Call> {
self.counter.add(buf.len() as _);
let net_packet = NetPacket::new(buf)?;
if net_packet.ttl() == 0 || net_packet.source_ttl() < net_packet.ttl() {
log::warn!("丢弃过时包:{:?}", net_packet.head());
return Ok(());
}
let current_device = self.current_device.load();
+151 -71
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,
@@ -136,13 +139,45 @@ impl<Call: VntCallback> PacketHandler for ServerPacketHandler<Call> {
HandshakeResponse::parse_from_bytes(net_packet.payload()).map_err(|e| {
io::Error::new(io::ErrorKind::Other, format!("HandshakeResponse {:?}", e))
})?;
log::info!("握手响应:{:?},{}", route_key, response);
//如果开启了加密,则发送加密握手请求
#[cfg(feature = "server_encrypt")]
if let Some(key) = self.server_cipher.key() {
{
let guard = self.rsa_cipher.lock();
if let Some(rsa_cipher) = guard.as_ref() {
if rsa_cipher.finger() == &response.key_finger {
let packet = handshaker::secret_handshake_request_packet(
rsa_cipher,
self.config_info.token.clone(),
key,
)?;
drop(guard);
context.send_by_key(packet.buffer(), route_key)?;
return Ok(());
}
log::warn!(
"拒绝服务端密钥对变化,原指纹:{:?},新指纹:{:?}addr:{:?}",
rsa_cipher.finger(),
response.key_finger,
route_key
);
return Ok(());
}
drop(guard);
}
let rsa_cipher = RsaCipher::new(&response.public_key)?;
if rsa_cipher.finger() != &response.key_finger {
log::info!(
"服务端密钥和指纹不匹 配拒绝握手,指纹1:{:?},指纹2:{:?}",
rsa_cipher.finger(),
response.key_finger
);
return Ok(());
}
let handshake_info = HandshakeInfo::new(
rsa_cipher.public_key()?.clone(),
rsa_cipher.finger()?,
response.key_finger,
response.version,
);
log::info!("加密握手请求:{:?}", handshake_info);
@@ -158,7 +193,9 @@ impl<Call: VntCallback> PacketHandler for ServerPacketHandler<Call> {
}
return Ok(());
}
if let Ok(rsa_cipher) = RsaCipher::new(&response.public_key) {
self.rsa_cipher.lock().replace(rsa_cipher);
}
let handshake_info = HandshakeInfo::new_no_secret(response.version);
if self.callback.handshake(handshake_info) {
//没有加密,则发送注册请求
@@ -237,6 +274,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 +286,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 +297,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,78 +304,107 @@ 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) {
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);
#[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),
));
}
}
}
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::RegistrationRequest => {
//不处理注册包
}
service_packet::Protocol::PollDeviceList => {}
service_packet::Protocol::PushDeviceList => {
let response = DeviceList::parse_from_bytes(net_packet.payload()).map_err(|e| {
io::Error::new(io::ErrorKind::Other, format!("PushDeviceList {:?}", e))
})?;
self.set_device_info_list(response.device_info_list, response.epoch as _);
}
service_packet::Protocol::HandshakeRequest => {}
service_packet::Protocol::HandshakeResponse => {}
service_packet::Protocol::SecretHandshakeRequest => {}
service_packet::Protocol::SecretHandshakeResponse => {
log::info!("SecretHandshakeResponse");
//加密握手结束,发送注册数据
self.register(current_device, context)?;
}
service_packet::Protocol::Unknown(e) => {
log::warn!("service_packet::Protocol::Unknown = {}", e);
_ => {
log::warn!(
"service_packet::Protocol::Unknown = {:?}",
net_packet.head()
);
}
}
Ok(())
@@ -352,24 +418,40 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
info.name,
info.device_status as u8,
info.client_secret,
info.client_secret_hash,
)
})
.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() {
//已连接的不需要注册
log::info!("已连接的不需要注册,{:?}", self.config_info);
return Ok(());
}
let token = self.config_info.token.clone();
let device_id = self.config_info.device_id.clone();
let name = self.config_info.name.clone();
let client_secret = self.config_info.client_secret;
let ip = self.config_info.ip;
let client_secret = self
.config_info
.client_secret_hash
.as_ref()
.map(|v| v.as_ref());
let mut ip = self.config_info.ip;
if ip.is_none() {
ip = Some(current_device.virtual_ip)
}
let response = registrar::registration_request_packet(
&self.server_cipher,
token,
@@ -408,7 +490,7 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
drop(dev);
}
self.handshake
.send(context, self.config_info.client_secret, route_key.addr)?;
.send(context, self.config_info.server_secret, route_key.addr)?;
// self.register(current_device, context, route_key)?;
}
InErrorPacket::AddressExhausted => {
@@ -421,12 +503,10 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
self.callback.error(err);
}
InErrorPacket::IpAlreadyExists => {
log::error!("IpAlreadyExists");
let err = ErrorInfo::new(ErrorType::IpAlreadyExists);
self.callback.error(err);
}
InErrorPacket::InvalidIp => {
log::error!("InvalidIp");
let err = ErrorInfo::new(ErrorType::InvalidIp);
self.callback.error(err);
}
@@ -464,7 +544,7 @@ impl<Call: VntCallback> ServerPacketHandler<Call> {
poll_device.first_set_ttl(MAX_TTL);
poll_device.set_protocol(Protocol::Service);
poll_device
.set_transport_protocol(service_packet::Protocol::PollDeviceList.into());
.set_transport_protocol(service_packet::Protocol::PullDeviceList.into());
self.server_cipher.encrypt_ipv4(&mut poll_device)?;
//发送到默认服务端即可
context.send_default(poll_device.buffer(), current_device.connect_server)?;
+8 -3
View File
@@ -18,7 +18,7 @@ impl PacketHandler for TurnPacketHandler {
fn handle(
&self,
mut net_packet: NetPacket<&mut [u8]>,
_route_key: RouteKey,
route_key: RouteKey,
context: &Context,
_current_device: &CurrentDeviceInfo,
) -> std::io::Result<()> {
@@ -27,13 +27,18 @@ impl PacketHandler for TurnPacketHandler {
if ttl > 0 {
let destination = net_packet.destination();
if let Some(route) = context.route_table.route_one(&destination) {
if route.addr == route_key.addr {
//防止环路
log::warn!("来源和目标相同 {:?},{:?}", route_key, net_packet.head());
return Ok(());
}
if route.metric <= ttl {
context.send_by_key(net_packet.buffer(), route.route_key())?;
return context.send_by_key(net_packet.buffer(), route.route_key());
}
}
//其他没有路由的不转发
}
log::info!("没有路由 {:?},{:?}", route_key, net_packet.head());
Ok(())
}
}
+7 -2
View File
@@ -18,7 +18,7 @@ pub fn registration_request_packet(
ip: Option<Ipv4Addr>,
is_fast: bool,
allow_ip_change: bool,
client_secret: bool,
client_secret_hash: Option<&[u8]>,
) -> io::Result<NetPacket<Vec<u8>>> {
let mut request = RegistrationRequest::new();
request.token = token;
@@ -30,7 +30,12 @@ pub fn registration_request_packet(
request.allow_ip_change = allow_ip_change;
request.is_fast = is_fast;
request.version = crate::VNT_VERSION.to_string();
request.client_secret = client_secret;
if let Some(client_secret_hash) = client_secret_hash {
request.client_secret = true;
request
.client_secret_hash
.extend_from_slice(client_secret_hash);
}
let bytes = request.write_to_bytes().map_err(|e| {
io::Error::new(io::ErrorKind::Other, format!("RegistrationRequest {:?}", e))
})?;
+83 -43
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,56 +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 {
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() && peer_ips.len() != MAX_COUNT {
//不需要转发
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)
}
/// 实现一个原地发送,必须保证是如下结构
@@ -88,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();
@@ -97,7 +126,7 @@ pub fn base_handle(
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(3);
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 {
@@ -117,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(
@@ -143,5 +178,10 @@ pub fn base_handle(
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)
context.send_ipv4_by_id(
net_packet.buffer(),
&dest_ip,
current_device.connect_server,
current_device.status.online(),
)
}
+15 -6
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,16 +84,17 @@ 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")]
#[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") {
@@ -110,8 +114,9 @@ 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!("tun_handler_{}", index))
.name(format!("tunHandler-{}", index))
.spawn(move || {
while let Ok((mut buf, len)) = receiver.recv() {
#[cfg(not(target_os = "macos"))]
@@ -129,6 +134,7 @@ pub fn start(
&ip_proxy_map,
&client_cipher,
&server_cipher,
&device_list,
) {
Ok(_) => {}
Err(e) => {
@@ -139,7 +145,7 @@ pub fn start(
})?;
}
thread::Builder::new()
.name("tun_handler".into())
.name("tunHandlerM".into())
.spawn(move || {
if let Err(e) = start_multi(stop_manager, device, sender, &mut up_counter) {
log::warn!("stop:{}", e);
@@ -148,7 +154,7 @@ pub fn start(
})?;
} else {
thread::Builder::new()
.name("tun_handler".into())
.name("tunHandlerS".into())
.spawn(move || {
if let Err(e) = start_simple(
stop_manager,
@@ -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) => {
+16 -12
View File
@@ -47,18 +47,21 @@ impl IcmpProxy {
Arc::new(Mutex::new(HashMap::with_capacity(16)));
{
let nat_map = nat_map.clone();
thread::spawn(move || {
if let Err(e) = icmp_proxy(
mio_icmp_socket,
nat_map,
context,
stop_manager,
current_device,
client_cipher,
) {
log::warn!("icmp_proxy:{:?}", e);
}
});
thread::Builder::new()
.name("icmpProxy".into())
.spawn(move || {
if let Err(e) = icmp_proxy(
mio_icmp_socket,
nat_map,
context,
stop_manager,
current_device,
client_cipher,
) {
log::warn!("icmp_proxy:{:?}", e);
}
})
.expect("icmpProxy");
}
Ok(Self {
icmp_socket: Arc::new(std_socket),
@@ -185,6 +188,7 @@ fn recv_handle(
net_packet.buffer(),
&dest_ip,
current_device.connect_server,
current_device.status.online(),
) {
log::warn!("发送到目标失败:{}", e);
}
+8 -5
View File
@@ -38,11 +38,14 @@ impl TcpProxy {
let port = tcp_listener.local_addr()?.port();
{
let nat_map = nat_map.clone();
thread::spawn(move || {
if let Err(e) = tcp_proxy(tcp_listener, nat_map, stop_manager) {
log::warn!("tcp_proxy:{:?}", e);
}
});
thread::Builder::new()
.name("tcpProxy".into())
.spawn(move || {
if let Err(e) = tcp_proxy(tcp_listener, nat_map, stop_manager) {
log::warn!("tcp_proxy:{:?}", e);
}
})
.expect("tcpProxy");
}
Ok(Self { port, nat_map })
}
+8 -5
View File
@@ -40,11 +40,14 @@ impl UdpProxy {
let port = udp.local_addr()?.port();
{
let nat_map = nat_map.clone();
thread::spawn(move || {
if let Err(e) = udp_proxy(udp, nat_map, scheduler, stop_manager) {
log::warn!("udp_proxy:{:?}", e);
}
});
thread::Builder::new()
.name("udpProxy".into())
.spawn(move || {
if let Err(e) = udp_proxy(udp, nat_map, scheduler, stop_manager) {
log::warn!("udp_proxy:{:?}", e);
}
})
.expect("udpProxy");
}
Ok(Self { port, nat_map })
}
+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::*;
+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,
+80 -32
View File
@@ -1,24 +1,24 @@
use std::collections::HashSet;
use std::io;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::time::Duration;
use std::{io, thread};
use crate::channel::punch::NatType;
use std::net::UdpSocket;
use stun_format::Attr;
pub fn stun_test_nat(stun_servers: Vec<String>) -> io::Result<(NatType, Vec<Ipv4Addr>, u16)> {
let mut h = Vec::new();
for x in stun_servers {
let handle = thread::spawn(move || test_nat(x));
h.push(handle);
let mut th = Vec::new();
for _ in 0..2 {
let stun_servers = stun_servers.clone();
let handle = std::thread::spawn(move || stun_test_nat0(stun_servers));
th.push(handle);
}
let mut nat_type = NatType::Cone;
let mut port_range = 0;
let mut hash_set = HashSet::new();
for x in h {
if let Ok(rs) = x.join() {
if let Ok((nat_type_t, ip_list_t, port_range_t)) = rs {
for x in th {
match x.join().unwrap() {
Ok((nat_type_t, ip_list_t, port_range_t)) => {
if nat_type_t == NatType::Symmetric {
nat_type = NatType::Symmetric;
}
@@ -29,44 +29,91 @@ pub fn stun_test_nat(stun_servers: Vec<String>) -> io::Result<(NatType, Vec<Ipv4
port_range = port_range_t;
}
}
Err(e) => {
log::warn!("{:?}", e);
}
}
}
Ok((nat_type, hash_set.into_iter().collect(), port_range))
}
fn test_nat(stun_server: String) -> io::Result<(NatType, Vec<Ipv4Addr>, u16)> {
pub fn stun_test_nat0(stun_servers: Vec<String>) -> io::Result<(NatType, Vec<Ipv4Addr>, u16)> {
let udp = UdpSocket::bind("0.0.0.0:0")?;
udp.set_read_timeout(Some(Duration::from_millis(300)))?;
let mut nat_type = NatType::Cone;
let mut port_range = 0;
let mut hash_set = HashSet::new();
let mut pub_addrs = HashSet::new();
for x in &stun_servers {
match test_nat(&udp, x) {
Ok((addr, nat_type_t, ip_list_t, port_range_t)) => {
if nat_type_t == NatType::Symmetric {
nat_type = NatType::Symmetric;
}
for x in ip_list_t {
hash_set.insert(x);
}
if port_range < port_range_t {
port_range = port_range_t;
}
pub_addrs.insert(addr);
}
Err(e) => {
log::warn!("stun {} error {:?} ", x, e);
}
}
}
if pub_addrs.len() > 1 {
nat_type = NatType::Symmetric;
}
Ok((nat_type, hash_set.into_iter().collect(), port_range))
}
fn test_nat(
udp: &UdpSocket,
stun_server: &String,
) -> io::Result<(SocketAddr, NatType, Vec<Ipv4Addr>, u16)> {
udp.connect(stun_server)?;
let mut port_range = 0;
let mut hash_set = HashSet::new();
let mut nat_type = NatType::Cone;
match test_nat_(&udp, true, true) {
Ok((mapped_addr1, changed_addr1)) => {
match mapped_addr1.ip() {
IpAddr::V4(ip) => {
hash_set.insert(ip);
}
IpAddr::V6(_) => {}
}
if udp.connect(changed_addr1).is_ok() {
if let Ok((mapped_addr2, _)) = test_nat_(&udp, false, false) {
match mapped_addr2.ip() {
IpAddr::V4(ip) => {
hash_set.insert(ip);
if mapped_addr1 != mapped_addr2 {
nat_type = NatType::Symmetric;
}
let (mapped_addr1, changed_addr1) = test_nat_(&udp, true, true)?;
match mapped_addr1.ip() {
IpAddr::V4(ip) => {
hash_set.insert(ip);
}
IpAddr::V6(_) => {}
}
if udp.connect(changed_addr1).is_ok() {
match test_nat_(&udp, false, false) {
Ok((mapped_addr2, _)) => {
match mapped_addr2.ip() {
IpAddr::V4(ip) => {
hash_set.insert(ip);
if mapped_addr1 != mapped_addr2 {
nat_type = NatType::Symmetric;
}
IpAddr::V6(_) => {}
}
port_range = mapped_addr2.port().abs_diff(mapped_addr1.port());
IpAddr::V6(_) => {}
}
port_range = mapped_addr2.port().abs_diff(mapped_addr1.port());
}
Err(e) => {
log::warn!("stun {} error {:?} ", stun_server, e);
}
}
Err(_) => {}
}
Ok((nat_type, hash_set.into_iter().collect(), port_range))
log::warn!(
"stun {} mapped_addr {:?} nat_type {:?}",
stun_server,
mapped_addr1,
nat_type
);
Ok((
mapped_addr1,
nat_type,
hash_set.into_iter().collect(),
port_range,
))
}
fn test_nat_(
@@ -88,7 +135,8 @@ fn test_nat_(
let mut buf = [0; 10240];
let (len, _addr) = match udp.recv_from(&mut buf) {
Ok(rs) => rs,
Err(_) => {
Err(e) => {
log::warn!("stun error {:?}", e);
continue;
}
};
-1755
View File
@@ -1,1755 +0,0 @@
// This file is generated by rust-protobuf 3.2.0. Do not edit
// .proto file is parsed by pure
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy::all)]
#![allow(unused_attributes)]
#![cfg_attr(rustfmt, rustfmt::skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unused_results)]
#![allow(unused_mut)]
//! Generated file from `message.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_2_0;
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:HandshakeRequest)
pub struct HandshakeRequest {
// message fields
// @@protoc_insertion_point(field:HandshakeRequest.version)
pub version: ::std::string::String,
// @@protoc_insertion_point(field:HandshakeRequest.secret)
pub secret: bool,
// special fields
// @@protoc_insertion_point(special_field:HandshakeRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a HandshakeRequest {
fn default() -> &'a HandshakeRequest {
<HandshakeRequest as ::protobuf::Message>::default_instance()
}
}
impl HandshakeRequest {
pub fn new() -> HandshakeRequest {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(2);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"version",
|m: &HandshakeRequest| { &m.version },
|m: &mut HandshakeRequest| { &mut m.version },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"secret",
|m: &HandshakeRequest| { &m.secret },
|m: &mut HandshakeRequest| { &mut m.secret },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HandshakeRequest>(
"HandshakeRequest",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for HandshakeRequest {
const NAME: &'static str = "HandshakeRequest";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.version = is.read_string()?;
},
16 => {
self.secret = is.read_bool()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.version.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.version);
}
if self.secret != false {
my_size += 1 + 1;
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.version.is_empty() {
os.write_string(1, &self.version)?;
}
if self.secret != false {
os.write_bool(2, self.secret)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> HandshakeRequest {
HandshakeRequest::new()
}
fn clear(&mut self) {
self.version.clear();
self.secret = false;
self.special_fields.clear();
}
fn default_instance() -> &'static HandshakeRequest {
static instance: HandshakeRequest = HandshakeRequest {
version: ::std::string::String::new(),
secret: false,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for HandshakeRequest {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeRequest").unwrap()).clone()
}
}
impl ::std::fmt::Display for HandshakeRequest {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for HandshakeRequest {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:HandshakeResponse)
pub struct HandshakeResponse {
// message fields
// @@protoc_insertion_point(field:HandshakeResponse.version)
pub version: ::std::string::String,
// @@protoc_insertion_point(field:HandshakeResponse.secret)
pub secret: bool,
// @@protoc_insertion_point(field:HandshakeResponse.public_key)
pub public_key: ::std::vec::Vec<u8>,
// @@protoc_insertion_point(field:HandshakeResponse.key_finger)
pub key_finger: ::std::string::String,
// special fields
// @@protoc_insertion_point(special_field:HandshakeResponse.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a HandshakeResponse {
fn default() -> &'a HandshakeResponse {
<HandshakeResponse as ::protobuf::Message>::default_instance()
}
}
impl HandshakeResponse {
pub fn new() -> HandshakeResponse {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(4);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"version",
|m: &HandshakeResponse| { &m.version },
|m: &mut HandshakeResponse| { &mut m.version },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"secret",
|m: &HandshakeResponse| { &m.secret },
|m: &mut HandshakeResponse| { &mut m.secret },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_key",
|m: &HandshakeResponse| { &m.public_key },
|m: &mut HandshakeResponse| { &mut m.public_key },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"key_finger",
|m: &HandshakeResponse| { &m.key_finger },
|m: &mut HandshakeResponse| { &mut m.key_finger },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<HandshakeResponse>(
"HandshakeResponse",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for HandshakeResponse {
const NAME: &'static str = "HandshakeResponse";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.version = is.read_string()?;
},
16 => {
self.secret = is.read_bool()?;
},
26 => {
self.public_key = is.read_bytes()?;
},
34 => {
self.key_finger = is.read_string()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.version.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.version);
}
if self.secret != false {
my_size += 1 + 1;
}
if !self.public_key.is_empty() {
my_size += ::protobuf::rt::bytes_size(3, &self.public_key);
}
if !self.key_finger.is_empty() {
my_size += ::protobuf::rt::string_size(4, &self.key_finger);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.version.is_empty() {
os.write_string(1, &self.version)?;
}
if self.secret != false {
os.write_bool(2, self.secret)?;
}
if !self.public_key.is_empty() {
os.write_bytes(3, &self.public_key)?;
}
if !self.key_finger.is_empty() {
os.write_string(4, &self.key_finger)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> HandshakeResponse {
HandshakeResponse::new()
}
fn clear(&mut self) {
self.version.clear();
self.secret = false;
self.public_key.clear();
self.key_finger.clear();
self.special_fields.clear();
}
fn default_instance() -> &'static HandshakeResponse {
static instance: HandshakeResponse = HandshakeResponse {
version: ::std::string::String::new(),
secret: false,
public_key: ::std::vec::Vec::new(),
key_finger: ::std::string::String::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for HandshakeResponse {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("HandshakeResponse").unwrap()).clone()
}
}
impl ::std::fmt::Display for HandshakeResponse {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for HandshakeResponse {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:SecretHandshakeRequest)
pub struct SecretHandshakeRequest {
// message fields
// @@protoc_insertion_point(field:SecretHandshakeRequest.token)
pub token: ::std::string::String,
// @@protoc_insertion_point(field:SecretHandshakeRequest.key)
pub key: ::std::vec::Vec<u8>,
// special fields
// @@protoc_insertion_point(special_field:SecretHandshakeRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a SecretHandshakeRequest {
fn default() -> &'a SecretHandshakeRequest {
<SecretHandshakeRequest as ::protobuf::Message>::default_instance()
}
}
impl SecretHandshakeRequest {
pub fn new() -> SecretHandshakeRequest {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(2);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"token",
|m: &SecretHandshakeRequest| { &m.token },
|m: &mut SecretHandshakeRequest| { &mut m.token },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"key",
|m: &SecretHandshakeRequest| { &m.key },
|m: &mut SecretHandshakeRequest| { &mut m.key },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<SecretHandshakeRequest>(
"SecretHandshakeRequest",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for SecretHandshakeRequest {
const NAME: &'static str = "SecretHandshakeRequest";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.token = is.read_string()?;
},
18 => {
self.key = is.read_bytes()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.token.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.token);
}
if !self.key.is_empty() {
my_size += ::protobuf::rt::bytes_size(2, &self.key);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.token.is_empty() {
os.write_string(1, &self.token)?;
}
if !self.key.is_empty() {
os.write_bytes(2, &self.key)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> SecretHandshakeRequest {
SecretHandshakeRequest::new()
}
fn clear(&mut self) {
self.token.clear();
self.key.clear();
self.special_fields.clear();
}
fn default_instance() -> &'static SecretHandshakeRequest {
static instance: SecretHandshakeRequest = SecretHandshakeRequest {
token: ::std::string::String::new(),
key: ::std::vec::Vec::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for SecretHandshakeRequest {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("SecretHandshakeRequest").unwrap()).clone()
}
}
impl ::std::fmt::Display for SecretHandshakeRequest {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for SecretHandshakeRequest {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:RegistrationRequest)
pub struct RegistrationRequest {
// message fields
// @@protoc_insertion_point(field:RegistrationRequest.token)
pub token: ::std::string::String,
// @@protoc_insertion_point(field:RegistrationRequest.device_id)
pub device_id: ::std::string::String,
// @@protoc_insertion_point(field:RegistrationRequest.name)
pub name: ::std::string::String,
// @@protoc_insertion_point(field:RegistrationRequest.is_fast)
pub is_fast: bool,
// @@protoc_insertion_point(field:RegistrationRequest.version)
pub version: ::std::string::String,
// @@protoc_insertion_point(field:RegistrationRequest.virtual_ip)
pub virtual_ip: u32,
// @@protoc_insertion_point(field:RegistrationRequest.allow_ip_change)
pub allow_ip_change: bool,
// @@protoc_insertion_point(field:RegistrationRequest.client_secret)
pub client_secret: bool,
// special fields
// @@protoc_insertion_point(special_field:RegistrationRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a RegistrationRequest {
fn default() -> &'a RegistrationRequest {
<RegistrationRequest as ::protobuf::Message>::default_instance()
}
}
impl RegistrationRequest {
pub fn new() -> RegistrationRequest {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(8);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"token",
|m: &RegistrationRequest| { &m.token },
|m: &mut RegistrationRequest| { &mut m.token },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"device_id",
|m: &RegistrationRequest| { &m.device_id },
|m: &mut RegistrationRequest| { &mut m.device_id },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"name",
|m: &RegistrationRequest| { &m.name },
|m: &mut RegistrationRequest| { &mut m.name },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"is_fast",
|m: &RegistrationRequest| { &m.is_fast },
|m: &mut RegistrationRequest| { &mut m.is_fast },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"version",
|m: &RegistrationRequest| { &m.version },
|m: &mut RegistrationRequest| { &mut m.version },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_ip",
|m: &RegistrationRequest| { &m.virtual_ip },
|m: &mut RegistrationRequest| { &mut m.virtual_ip },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"allow_ip_change",
|m: &RegistrationRequest| { &m.allow_ip_change },
|m: &mut RegistrationRequest| { &mut m.allow_ip_change },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"client_secret",
|m: &RegistrationRequest| { &m.client_secret },
|m: &mut RegistrationRequest| { &mut m.client_secret },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RegistrationRequest>(
"RegistrationRequest",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for RegistrationRequest {
const NAME: &'static str = "RegistrationRequest";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.token = is.read_string()?;
},
18 => {
self.device_id = is.read_string()?;
},
26 => {
self.name = is.read_string()?;
},
32 => {
self.is_fast = is.read_bool()?;
},
42 => {
self.version = is.read_string()?;
},
53 => {
self.virtual_ip = is.read_fixed32()?;
},
56 => {
self.allow_ip_change = is.read_bool()?;
},
64 => {
self.client_secret = is.read_bool()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.token.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.token);
}
if !self.device_id.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.device_id);
}
if !self.name.is_empty() {
my_size += ::protobuf::rt::string_size(3, &self.name);
}
if self.is_fast != false {
my_size += 1 + 1;
}
if !self.version.is_empty() {
my_size += ::protobuf::rt::string_size(5, &self.version);
}
if self.virtual_ip != 0 {
my_size += 1 + 4;
}
if self.allow_ip_change != false {
my_size += 1 + 1;
}
if self.client_secret != false {
my_size += 1 + 1;
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.token.is_empty() {
os.write_string(1, &self.token)?;
}
if !self.device_id.is_empty() {
os.write_string(2, &self.device_id)?;
}
if !self.name.is_empty() {
os.write_string(3, &self.name)?;
}
if self.is_fast != false {
os.write_bool(4, self.is_fast)?;
}
if !self.version.is_empty() {
os.write_string(5, &self.version)?;
}
if self.virtual_ip != 0 {
os.write_fixed32(6, self.virtual_ip)?;
}
if self.allow_ip_change != false {
os.write_bool(7, self.allow_ip_change)?;
}
if self.client_secret != false {
os.write_bool(8, self.client_secret)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> RegistrationRequest {
RegistrationRequest::new()
}
fn clear(&mut self) {
self.token.clear();
self.device_id.clear();
self.name.clear();
self.is_fast = false;
self.version.clear();
self.virtual_ip = 0;
self.allow_ip_change = false;
self.client_secret = false;
self.special_fields.clear();
}
fn default_instance() -> &'static RegistrationRequest {
static instance: RegistrationRequest = RegistrationRequest {
token: ::std::string::String::new(),
device_id: ::std::string::String::new(),
name: ::std::string::String::new(),
is_fast: false,
version: ::std::string::String::new(),
virtual_ip: 0,
allow_ip_change: false,
client_secret: false,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for RegistrationRequest {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("RegistrationRequest").unwrap()).clone()
}
}
impl ::std::fmt::Display for RegistrationRequest {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for RegistrationRequest {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:RegistrationResponse)
pub struct RegistrationResponse {
// message fields
// @@protoc_insertion_point(field:RegistrationResponse.virtual_ip)
pub virtual_ip: u32,
// @@protoc_insertion_point(field:RegistrationResponse.virtual_gateway)
pub virtual_gateway: u32,
// @@protoc_insertion_point(field:RegistrationResponse.virtual_netmask)
pub virtual_netmask: u32,
// @@protoc_insertion_point(field:RegistrationResponse.epoch)
pub epoch: u32,
// @@protoc_insertion_point(field:RegistrationResponse.device_info_list)
pub device_info_list: ::std::vec::Vec<DeviceInfo>,
// @@protoc_insertion_point(field:RegistrationResponse.public_ip)
pub public_ip: u32,
// @@protoc_insertion_point(field:RegistrationResponse.public_port)
pub public_port: u32,
// @@protoc_insertion_point(field:RegistrationResponse.public_ipv6)
pub public_ipv6: ::std::vec::Vec<u8>,
// special fields
// @@protoc_insertion_point(special_field:RegistrationResponse.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a RegistrationResponse {
fn default() -> &'a RegistrationResponse {
<RegistrationResponse as ::protobuf::Message>::default_instance()
}
}
impl RegistrationResponse {
pub fn new() -> RegistrationResponse {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(8);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_ip",
|m: &RegistrationResponse| { &m.virtual_ip },
|m: &mut RegistrationResponse| { &mut m.virtual_ip },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_gateway",
|m: &RegistrationResponse| { &m.virtual_gateway },
|m: &mut RegistrationResponse| { &mut m.virtual_gateway },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_netmask",
|m: &RegistrationResponse| { &m.virtual_netmask },
|m: &mut RegistrationResponse| { &mut m.virtual_netmask },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"epoch",
|m: &RegistrationResponse| { &m.epoch },
|m: &mut RegistrationResponse| { &mut m.epoch },
));
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"device_info_list",
|m: &RegistrationResponse| { &m.device_info_list },
|m: &mut RegistrationResponse| { &mut m.device_info_list },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_ip",
|m: &RegistrationResponse| { &m.public_ip },
|m: &mut RegistrationResponse| { &mut m.public_ip },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_port",
|m: &RegistrationResponse| { &m.public_port },
|m: &mut RegistrationResponse| { &mut m.public_port },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_ipv6",
|m: &RegistrationResponse| { &m.public_ipv6 },
|m: &mut RegistrationResponse| { &mut m.public_ipv6 },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RegistrationResponse>(
"RegistrationResponse",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for RegistrationResponse {
const NAME: &'static str = "RegistrationResponse";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
13 => {
self.virtual_ip = is.read_fixed32()?;
},
21 => {
self.virtual_gateway = is.read_fixed32()?;
},
29 => {
self.virtual_netmask = is.read_fixed32()?;
},
32 => {
self.epoch = is.read_uint32()?;
},
42 => {
self.device_info_list.push(is.read_message()?);
},
53 => {
self.public_ip = is.read_fixed32()?;
},
56 => {
self.public_port = is.read_uint32()?;
},
66 => {
self.public_ipv6 = is.read_bytes()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if self.virtual_ip != 0 {
my_size += 1 + 4;
}
if self.virtual_gateway != 0 {
my_size += 1 + 4;
}
if self.virtual_netmask != 0 {
my_size += 1 + 4;
}
if self.epoch != 0 {
my_size += ::protobuf::rt::uint32_size(4, self.epoch);
}
for value in &self.device_info_list {
let len = value.compute_size();
my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len;
};
if self.public_ip != 0 {
my_size += 1 + 4;
}
if self.public_port != 0 {
my_size += ::protobuf::rt::uint32_size(7, self.public_port);
}
if !self.public_ipv6.is_empty() {
my_size += ::protobuf::rt::bytes_size(8, &self.public_ipv6);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if self.virtual_ip != 0 {
os.write_fixed32(1, self.virtual_ip)?;
}
if self.virtual_gateway != 0 {
os.write_fixed32(2, self.virtual_gateway)?;
}
if self.virtual_netmask != 0 {
os.write_fixed32(3, self.virtual_netmask)?;
}
if self.epoch != 0 {
os.write_uint32(4, self.epoch)?;
}
for v in &self.device_info_list {
::protobuf::rt::write_message_field_with_cached_size(5, v, os)?;
};
if self.public_ip != 0 {
os.write_fixed32(6, self.public_ip)?;
}
if self.public_port != 0 {
os.write_uint32(7, self.public_port)?;
}
if !self.public_ipv6.is_empty() {
os.write_bytes(8, &self.public_ipv6)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> RegistrationResponse {
RegistrationResponse::new()
}
fn clear(&mut self) {
self.virtual_ip = 0;
self.virtual_gateway = 0;
self.virtual_netmask = 0;
self.epoch = 0;
self.device_info_list.clear();
self.public_ip = 0;
self.public_port = 0;
self.public_ipv6.clear();
self.special_fields.clear();
}
fn default_instance() -> &'static RegistrationResponse {
static instance: RegistrationResponse = RegistrationResponse {
virtual_ip: 0,
virtual_gateway: 0,
virtual_netmask: 0,
epoch: 0,
device_info_list: ::std::vec::Vec::new(),
public_ip: 0,
public_port: 0,
public_ipv6: ::std::vec::Vec::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for RegistrationResponse {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("RegistrationResponse").unwrap()).clone()
}
}
impl ::std::fmt::Display for RegistrationResponse {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for RegistrationResponse {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:DeviceInfo)
pub struct DeviceInfo {
// message fields
// @@protoc_insertion_point(field:DeviceInfo.name)
pub name: ::std::string::String,
// @@protoc_insertion_point(field:DeviceInfo.virtual_ip)
pub virtual_ip: u32,
// @@protoc_insertion_point(field:DeviceInfo.device_status)
pub device_status: u32,
// @@protoc_insertion_point(field:DeviceInfo.client_secret)
pub client_secret: bool,
// special fields
// @@protoc_insertion_point(special_field:DeviceInfo.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a DeviceInfo {
fn default() -> &'a DeviceInfo {
<DeviceInfo as ::protobuf::Message>::default_instance()
}
}
impl DeviceInfo {
pub fn new() -> DeviceInfo {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(4);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"name",
|m: &DeviceInfo| { &m.name },
|m: &mut DeviceInfo| { &mut m.name },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_ip",
|m: &DeviceInfo| { &m.virtual_ip },
|m: &mut DeviceInfo| { &mut m.virtual_ip },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"device_status",
|m: &DeviceInfo| { &m.device_status },
|m: &mut DeviceInfo| { &mut m.device_status },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"client_secret",
|m: &DeviceInfo| { &m.client_secret },
|m: &mut DeviceInfo| { &mut m.client_secret },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<DeviceInfo>(
"DeviceInfo",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for DeviceInfo {
const NAME: &'static str = "DeviceInfo";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.name = is.read_string()?;
},
21 => {
self.virtual_ip = is.read_fixed32()?;
},
24 => {
self.device_status = is.read_uint32()?;
},
32 => {
self.client_secret = is.read_bool()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.name.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.name);
}
if self.virtual_ip != 0 {
my_size += 1 + 4;
}
if self.device_status != 0 {
my_size += ::protobuf::rt::uint32_size(3, self.device_status);
}
if self.client_secret != false {
my_size += 1 + 1;
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.name.is_empty() {
os.write_string(1, &self.name)?;
}
if self.virtual_ip != 0 {
os.write_fixed32(2, self.virtual_ip)?;
}
if self.device_status != 0 {
os.write_uint32(3, self.device_status)?;
}
if self.client_secret != false {
os.write_bool(4, self.client_secret)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> DeviceInfo {
DeviceInfo::new()
}
fn clear(&mut self) {
self.name.clear();
self.virtual_ip = 0;
self.device_status = 0;
self.client_secret = false;
self.special_fields.clear();
}
fn default_instance() -> &'static DeviceInfo {
static instance: DeviceInfo = DeviceInfo {
name: ::std::string::String::new(),
virtual_ip: 0,
device_status: 0,
client_secret: false,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for DeviceInfo {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("DeviceInfo").unwrap()).clone()
}
}
impl ::std::fmt::Display for DeviceInfo {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for DeviceInfo {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:DeviceList)
pub struct DeviceList {
// message fields
// @@protoc_insertion_point(field:DeviceList.epoch)
pub epoch: u32,
// @@protoc_insertion_point(field:DeviceList.device_info_list)
pub device_info_list: ::std::vec::Vec<DeviceInfo>,
// special fields
// @@protoc_insertion_point(special_field:DeviceList.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a DeviceList {
fn default() -> &'a DeviceList {
<DeviceList as ::protobuf::Message>::default_instance()
}
}
impl DeviceList {
pub fn new() -> DeviceList {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(2);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"epoch",
|m: &DeviceList| { &m.epoch },
|m: &mut DeviceList| { &mut m.epoch },
));
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"device_info_list",
|m: &DeviceList| { &m.device_info_list },
|m: &mut DeviceList| { &mut m.device_info_list },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<DeviceList>(
"DeviceList",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for DeviceList {
const NAME: &'static str = "DeviceList";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
8 => {
self.epoch = is.read_uint32()?;
},
18 => {
self.device_info_list.push(is.read_message()?);
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if self.epoch != 0 {
my_size += ::protobuf::rt::uint32_size(1, self.epoch);
}
for value in &self.device_info_list {
let len = value.compute_size();
my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len;
};
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if self.epoch != 0 {
os.write_uint32(1, self.epoch)?;
}
for v in &self.device_info_list {
::protobuf::rt::write_message_field_with_cached_size(2, v, os)?;
};
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> DeviceList {
DeviceList::new()
}
fn clear(&mut self) {
self.epoch = 0;
self.device_info_list.clear();
self.special_fields.clear();
}
fn default_instance() -> &'static DeviceList {
static instance: DeviceList = DeviceList {
epoch: 0,
device_info_list: ::std::vec::Vec::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for DeviceList {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("DeviceList").unwrap()).clone()
}
}
impl ::std::fmt::Display for DeviceList {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for DeviceList {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:PunchInfo)
pub struct PunchInfo {
// message fields
// @@protoc_insertion_point(field:PunchInfo.public_ip_list)
pub public_ip_list: ::std::vec::Vec<u32>,
// @@protoc_insertion_point(field:PunchInfo.public_port)
pub public_port: u32,
// @@protoc_insertion_point(field:PunchInfo.public_port_range)
pub public_port_range: u32,
// @@protoc_insertion_point(field:PunchInfo.nat_type)
pub nat_type: ::protobuf::EnumOrUnknown<PunchNatType>,
// @@protoc_insertion_point(field:PunchInfo.reply)
pub reply: bool,
// @@protoc_insertion_point(field:PunchInfo.local_ip)
pub local_ip: u32,
// @@protoc_insertion_point(field:PunchInfo.local_port)
pub local_port: u32,
// @@protoc_insertion_point(field:PunchInfo.ipv6)
pub ipv6: ::std::vec::Vec<u8>,
// @@protoc_insertion_point(field:PunchInfo.ipv6_port)
pub ipv6_port: u32,
// @@protoc_insertion_point(field:PunchInfo.tcp_port)
pub tcp_port: u32,
// @@protoc_insertion_point(field:PunchInfo.udp_ports)
pub udp_ports: ::std::vec::Vec<u32>,
// @@protoc_insertion_point(field:PunchInfo.public_ports)
pub public_ports: ::std::vec::Vec<u32>,
// special fields
// @@protoc_insertion_point(special_field:PunchInfo.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a PunchInfo {
fn default() -> &'a PunchInfo {
<PunchInfo as ::protobuf::Message>::default_instance()
}
}
impl PunchInfo {
pub fn new() -> PunchInfo {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(12);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"public_ip_list",
|m: &PunchInfo| { &m.public_ip_list },
|m: &mut PunchInfo| { &mut m.public_ip_list },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_port",
|m: &PunchInfo| { &m.public_port },
|m: &mut PunchInfo| { &mut m.public_port },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_port_range",
|m: &PunchInfo| { &m.public_port_range },
|m: &mut PunchInfo| { &mut m.public_port_range },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"nat_type",
|m: &PunchInfo| { &m.nat_type },
|m: &mut PunchInfo| { &mut m.nat_type },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"reply",
|m: &PunchInfo| { &m.reply },
|m: &mut PunchInfo| { &mut m.reply },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"local_ip",
|m: &PunchInfo| { &m.local_ip },
|m: &mut PunchInfo| { &mut m.local_ip },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"local_port",
|m: &PunchInfo| { &m.local_port },
|m: &mut PunchInfo| { &mut m.local_port },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"ipv6",
|m: &PunchInfo| { &m.ipv6 },
|m: &mut PunchInfo| { &mut m.ipv6 },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"ipv6_port",
|m: &PunchInfo| { &m.ipv6_port },
|m: &mut PunchInfo| { &mut m.ipv6_port },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"tcp_port",
|m: &PunchInfo| { &m.tcp_port },
|m: &mut PunchInfo| { &mut m.tcp_port },
));
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"udp_ports",
|m: &PunchInfo| { &m.udp_ports },
|m: &mut PunchInfo| { &mut m.udp_ports },
));
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"public_ports",
|m: &PunchInfo| { &m.public_ports },
|m: &mut PunchInfo| { &mut m.public_ports },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<PunchInfo>(
"PunchInfo",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for PunchInfo {
const NAME: &'static str = "PunchInfo";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
18 => {
is.read_repeated_packed_fixed32_into(&mut self.public_ip_list)?;
},
21 => {
self.public_ip_list.push(is.read_fixed32()?);
},
24 => {
self.public_port = is.read_uint32()?;
},
32 => {
self.public_port_range = is.read_uint32()?;
},
40 => {
self.nat_type = is.read_enum_or_unknown()?;
},
48 => {
self.reply = is.read_bool()?;
},
61 => {
self.local_ip = is.read_fixed32()?;
},
64 => {
self.local_port = is.read_uint32()?;
},
74 => {
self.ipv6 = is.read_bytes()?;
},
80 => {
self.ipv6_port = is.read_uint32()?;
},
88 => {
self.tcp_port = is.read_uint32()?;
},
98 => {
is.read_repeated_packed_uint32_into(&mut self.udp_ports)?;
},
96 => {
self.udp_ports.push(is.read_uint32()?);
},
106 => {
is.read_repeated_packed_uint32_into(&mut self.public_ports)?;
},
104 => {
self.public_ports.push(is.read_uint32()?);
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
my_size += 5 * self.public_ip_list.len() as u64;
if self.public_port != 0 {
my_size += ::protobuf::rt::uint32_size(3, self.public_port);
}
if self.public_port_range != 0 {
my_size += ::protobuf::rt::uint32_size(4, self.public_port_range);
}
if self.nat_type != ::protobuf::EnumOrUnknown::new(PunchNatType::Symmetric) {
my_size += ::protobuf::rt::int32_size(5, self.nat_type.value());
}
if self.reply != false {
my_size += 1 + 1;
}
if self.local_ip != 0 {
my_size += 1 + 4;
}
if self.local_port != 0 {
my_size += ::protobuf::rt::uint32_size(8, self.local_port);
}
if !self.ipv6.is_empty() {
my_size += ::protobuf::rt::bytes_size(9, &self.ipv6);
}
if self.ipv6_port != 0 {
my_size += ::protobuf::rt::uint32_size(10, self.ipv6_port);
}
if self.tcp_port != 0 {
my_size += ::protobuf::rt::uint32_size(11, self.tcp_port);
}
for value in &self.udp_ports {
my_size += ::protobuf::rt::uint32_size(12, *value);
};
for value in &self.public_ports {
my_size += ::protobuf::rt::uint32_size(13, *value);
};
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
for v in &self.public_ip_list {
os.write_fixed32(2, *v)?;
};
if self.public_port != 0 {
os.write_uint32(3, self.public_port)?;
}
if self.public_port_range != 0 {
os.write_uint32(4, self.public_port_range)?;
}
if self.nat_type != ::protobuf::EnumOrUnknown::new(PunchNatType::Symmetric) {
os.write_enum(5, ::protobuf::EnumOrUnknown::value(&self.nat_type))?;
}
if self.reply != false {
os.write_bool(6, self.reply)?;
}
if self.local_ip != 0 {
os.write_fixed32(7, self.local_ip)?;
}
if self.local_port != 0 {
os.write_uint32(8, self.local_port)?;
}
if !self.ipv6.is_empty() {
os.write_bytes(9, &self.ipv6)?;
}
if self.ipv6_port != 0 {
os.write_uint32(10, self.ipv6_port)?;
}
if self.tcp_port != 0 {
os.write_uint32(11, self.tcp_port)?;
}
for v in &self.udp_ports {
os.write_uint32(12, *v)?;
};
for v in &self.public_ports {
os.write_uint32(13, *v)?;
};
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> PunchInfo {
PunchInfo::new()
}
fn clear(&mut self) {
self.public_ip_list.clear();
self.public_port = 0;
self.public_port_range = 0;
self.nat_type = ::protobuf::EnumOrUnknown::new(PunchNatType::Symmetric);
self.reply = false;
self.local_ip = 0;
self.local_port = 0;
self.ipv6.clear();
self.ipv6_port = 0;
self.tcp_port = 0;
self.udp_ports.clear();
self.public_ports.clear();
self.special_fields.clear();
}
fn default_instance() -> &'static PunchInfo {
static instance: PunchInfo = PunchInfo {
public_ip_list: ::std::vec::Vec::new(),
public_port: 0,
public_port_range: 0,
nat_type: ::protobuf::EnumOrUnknown::from_i32(0),
reply: false,
local_ip: 0,
local_port: 0,
ipv6: ::std::vec::Vec::new(),
ipv6_port: 0,
tcp_port: 0,
udp_ports: ::std::vec::Vec::new(),
public_ports: ::std::vec::Vec::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for PunchInfo {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("PunchInfo").unwrap()).clone()
}
}
impl ::std::fmt::Display for PunchInfo {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for PunchInfo {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:PunchNatType)
pub enum PunchNatType {
// @@protoc_insertion_point(enum_value:PunchNatType.Symmetric)
Symmetric = 0,
// @@protoc_insertion_point(enum_value:PunchNatType.Cone)
Cone = 1,
}
impl ::protobuf::Enum for PunchNatType {
const NAME: &'static str = "PunchNatType";
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<PunchNatType> {
match value {
0 => ::std::option::Option::Some(PunchNatType::Symmetric),
1 => ::std::option::Option::Some(PunchNatType::Cone),
_ => ::std::option::Option::None
}
}
const VALUES: &'static [PunchNatType] = &[
PunchNatType::Symmetric,
PunchNatType::Cone,
];
}
impl ::protobuf::EnumFull for PunchNatType {
fn enum_descriptor() -> ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().enum_by_package_relative_name("PunchNatType").unwrap()).clone()
}
fn descriptor(&self) -> ::protobuf::reflect::EnumValueDescriptor {
let index = *self as usize;
Self::enum_descriptor().value_by_index(index)
}
}
impl ::std::default::Default for PunchNatType {
fn default() -> Self {
PunchNatType::Symmetric
}
}
impl PunchNatType {
fn generated_enum_descriptor_data() -> ::protobuf::reflect::GeneratedEnumDescriptorData {
::protobuf::reflect::GeneratedEnumDescriptorData::new::<PunchNatType>("PunchNatType")
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\rmessage.proto\"D\n\x10HandshakeRequest\x12\x18\n\x07version\x18\x01\
\x20\x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06sec\
ret\"\x83\x01\n\x11HandshakeResponse\x12\x18\n\x07version\x18\x01\x20\
\x01(\tR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x08R\x06secret\
\x12\x1d\n\npublic_key\x18\x03\x20\x01(\x0cR\tpublicKey\x12\x1d\n\nkey_f\
inger\x18\x04\x20\x01(\tR\tkeyFinger\"@\n\x16SecretHandshakeRequest\x12\
\x14\n\x05token\x18\x01\x20\x01(\tR\x05token\x12\x10\n\x03key\x18\x02\
\x20\x01(\x0cR\x03key\"\xfb\x01\n\x13RegistrationRequest\x12\x14\n\x05to\
ken\x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\t\
R\x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\
\x07is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\
\x20\x01(\tR\x07version\x12\x1d\n\nvirtual_ip\x18\x06\x20\x01(\x07R\tvir\
tualIp\x12&\n\x0fallow_ip_change\x18\x07\x20\x01(\x08R\rallowIpChange\
\x12#\n\rclient_secret\x18\x08\x20\x01(\x08R\x0cclientSecret\"\xb3\x02\n\
\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvi\
rtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07R\x0evirtualGatewa\
y\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0evirtualNetmask\x12\
\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\
\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\n\tpubl\
ic_ip\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\
\x20\x01(\rR\npublicPort\x12\x1f\n\x0bpublic_ipv6\x18\x08\x20\x01(\x0cR\
\npublicIpv6\"\x89\x01\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\x01(\
\tR\x04name\x12\x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\x12#\
\n\rdevice_status\x18\x03\x20\x01(\rR\x0cdeviceStatus\x12#\n\rclient_sec\
ret\x18\x04\x20\x01(\x08R\x0cclientSecret\"Y\n\nDeviceList\x12\x14\n\x05\
epoch\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x02\
\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\x84\x03\n\tPunchInfo\
\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\
\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11public_port_\
range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_type\x18\x05\
\x20\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\
\x01(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\x07R\x07local\
Ip\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort\x12\x12\n\x04ipv\
6\x18\t\x20\x01(\x0cR\x04ipv6\x12\x1b\n\tipv6_port\x18\n\x20\x01(\rR\x08\
ipv6Port\x12\x19\n\x08tcp_port\x18\x0b\x20\x01(\rR\x07tcpPort\x12\x1b\n\
\tudp_ports\x18\x0c\x20\x03(\rR\x08udpPorts\x12!\n\x0cpublic_ports\x18\r\
\x20\x03(\rR\x0bpublicPorts*'\n\x0cPunchNatType\x12\r\n\tSymmetric\x10\0\
\x12\x08\n\x04Cone\x10\x01b\x06proto3\
";
/// `FileDescriptorProto` object which was a source for this generated file
fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
static file_descriptor_proto_lazy: ::protobuf::rt::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::Lazy::new();
file_descriptor_proto_lazy.get(|| {
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
})
}
/// `FileDescriptor` object which allows dynamic access to files
pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
static generated_file_descriptor_lazy: ::protobuf::rt::Lazy<::protobuf::reflect::GeneratedFileDescriptor> = ::protobuf::rt::Lazy::new();
static file_descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::FileDescriptor> = ::protobuf::rt::Lazy::new();
file_descriptor.get(|| {
let generated_file_descriptor = generated_file_descriptor_lazy.get(|| {
let mut deps = ::std::vec::Vec::with_capacity(0);
let mut messages = ::std::vec::Vec::with_capacity(8);
messages.push(HandshakeRequest::generated_message_descriptor_data());
messages.push(HandshakeResponse::generated_message_descriptor_data());
messages.push(SecretHandshakeRequest::generated_message_descriptor_data());
messages.push(RegistrationRequest::generated_message_descriptor_data());
messages.push(RegistrationResponse::generated_message_descriptor_data());
messages.push(DeviceInfo::generated_message_descriptor_data());
messages.push(DeviceList::generated_message_descriptor_data());
messages.push(PunchInfo::generated_message_descriptor_data());
let mut enums = ::std::vec::Vec::with_capacity(1);
enums.push(PunchNatType::generated_enum_descriptor_data());
::protobuf::reflect::GeneratedFileDescriptor::new_generated(
file_descriptor_proto(),
deps,
messages,
enums,
)
});
::protobuf::reflect::FileDescriptor::new_generated_2(generated_file_descriptor)
})
}
-3
View File
@@ -1,3 +0,0 @@
// @generated
pub mod message;
+16 -10
View File
@@ -5,14 +5,20 @@ use std::{fmt, io};
pub enum Protocol {
/// ping请求
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time | echo |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time | echo |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
Ping,
/// 维持连接,内容同ping
/*
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time | echo |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
Pong,
/// 打洞请求
PunchRequest,
@@ -85,8 +91,8 @@ pub type PongPacket<B> = PingPacket<B>;
impl<B: AsRef<[u8]>> PingPacket<B> {
pub fn new(buffer: B) -> io::Result<PingPacket<B>> {
let len = buffer.as_ref().len();
if len != 4 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "len != 4"));
if len < 4 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "len < 4"));
}
Ok(PingPacket { buffer })
}
@@ -126,8 +132,8 @@ pub struct AddrPacket<B> {
impl<B: AsRef<[u8]>> AddrPacket<B> {
pub fn new(buffer: B) -> io::Result<AddrPacket<B>> {
let len = buffer.as_ref().len();
if len != 6 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "len != 6"));
if len < 6 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "len < 6"));
}
Ok(AddrPacket { buffer })
}
+6
View File
@@ -183,6 +183,9 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
pub fn payload(&self) -> &[u8] {
&self.buffer.as_ref()[12..self.data_len]
}
pub fn head(&self) -> &[u8] {
&self.buffer.as_ref()[..12]
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
@@ -214,6 +217,9 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
pub fn set_transport_protocol(&mut self, transport_protocol: u8) {
self.buffer.as_mut()[2] = transport_protocol;
}
pub fn set_transport_protocol_into<P: Into<u8>>(&mut self, transport_protocol: P) {
self.buffer.as_mut()[2] = transport_protocol.into();
}
pub fn first_set_ttl(&mut self, ttl: u8) {
self.buffer.as_mut()[3] = ttl << 4 | ttl;
}
+7 -3
View File
@@ -5,7 +5,7 @@ pub enum Protocol {
/// 注册响应
RegistrationResponse,
/// 拉取设备列表
PollDeviceList,
PullDeviceList,
/// 推送设备列表
PushDeviceList,
/// 和服务端握手
@@ -13,6 +13,8 @@ pub enum Protocol {
HandshakeResponse,
SecretHandshakeRequest,
SecretHandshakeResponse,
/// 客户端上报状态
ClientStatusInfo,
Unknown(u8),
}
@@ -21,12 +23,13 @@ impl From<u8> for Protocol {
match value {
1 => Self::RegistrationRequest,
2 => Self::RegistrationResponse,
3 => Self::PollDeviceList,
3 => Self::PullDeviceList,
4 => Self::PushDeviceList,
5 => Self::HandshakeRequest,
6 => Self::HandshakeResponse,
7 => Self::SecretHandshakeRequest,
8 => Self::SecretHandshakeResponse,
9 => Self::ClientStatusInfo,
val => Self::Unknown(val),
}
}
@@ -37,12 +40,13 @@ impl Into<u8> for Protocol {
match self {
Self::RegistrationRequest => 1,
Self::RegistrationResponse => 2,
Self::PollDeviceList => 3,
Self::PullDeviceList => 3,
Self::PushDeviceList => 4,
Self::HandshakeRequest => 5,
Self::HandshakeResponse => 6,
Self::SecretHandshakeRequest => 7,
Self::SecretHandshakeResponse => 8,
Self::ClientStatusInfo => 9,
Self::Unknown(val) => val,
}
}
+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"))
}
}
}
+225
View File
@@ -0,0 +1,225 @@
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, UdpSocket};
use std::str::FromStr;
use std::time::Duration;
use std::{io, thread};
use anyhow::Context;
use dns_parser::{Builder, Packet, QueryClass, QueryType, RData, ResponseCode};
/// 后续实现选择延迟最低的可用地址,需要服务端配合
/// 现在是选择第一个地址,优先ipv6
pub fn address_choose(addrs: Vec<SocketAddr>) -> anyhow::Result<SocketAddr> {
let v4: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv4()).map(|v| *v).collect();
let v6: Vec<SocketAddr> = addrs.iter().filter(|v| v.is_ipv6()).map(|v| *v).collect();
let check_addr = |addrs: &Vec<SocketAddr>| -> anyhow::Result<SocketAddr> {
if !addrs.is_empty() {
let udp = if addrs[0].is_ipv6() {
UdpSocket::bind("[::]:0")?
} else {
UdpSocket::bind("0.0.0.0:0")?
};
for addr in addrs {
if udp.connect(addr).is_ok() {
return Ok(*addr);
}
}
}
Err(anyhow::anyhow!("Unable to connect to address {:?}", addrs))
};
if v6.is_empty() {
return check_addr(&v4);
}
if v4.is_empty() {
return check_addr(&v6);
}
match check_addr(&v6) {
Ok(addr) => Ok(addr),
Err(e1) => match check_addr(&v4) {
Ok(addr) => Ok(addr),
Err(e2) => Err(anyhow::anyhow!("{} , {}", e1, e2)),
},
}
}
pub fn dns_query_all(domain: &str, name_servers: Vec<String>) -> anyhow::Result<Vec<SocketAddr>> {
match SocketAddr::from_str(domain) {
Ok(addr) => {
return Ok(vec![addr]);
}
Err(_) => {
if name_servers.is_empty() {
Err(anyhow::anyhow!("name server is none"))?
}
let mut err: Option<anyhow::Error> = None;
for name_server in name_servers {
if let Some(domain) = domain.to_lowercase().strip_prefix("txt:") {
return txt_dns(domain, name_server);
}
let end_index = domain
.rfind(":")
.with_context(|| format!("{:?} not port", domain))?;
let host = &domain[..end_index];
let port = u16::from_str(&domain[end_index + 1..])
.with_context(|| format!("{:?} not port", domain))?;
let th1 = {
let host = host.to_string();
let name_server = name_server.clone();
thread::spawn(move || a_dns(host, name_server))
};
let th2 = {
let host = host.to_string();
let name_server = name_server.clone();
thread::spawn(move || aaaa_dns(host, name_server))
};
let mut addr = Vec::new();
match th1.join().unwrap() {
Ok(rs) => {
for ip in rs {
addr.push(SocketAddr::new(ip.into(), port));
}
}
Err(e) => {
err.replace(anyhow::anyhow!("{}", e));
}
}
match th2.join().unwrap() {
Ok(rs) => {
for ip in rs {
addr.push(SocketAddr::new(ip.into(), port));
}
}
Err(e) => {
if addr.is_empty() {
if let Some(err) = &mut err {
*err = anyhow::anyhow!("{},{}", err, e);
} else {
err.replace(anyhow::anyhow!("{}", e));
}
continue;
}
}
}
if addr.is_empty() {
continue;
}
return Ok(addr);
}
if let Some(e) = err {
Err(e)
} else {
Err(anyhow::anyhow!("DNS query failed"))
}
}
}
}
fn query<'a>(
udp: &UdpSocket,
domain: &str,
name_server: SocketAddr,
record_type: QueryType,
buf: &'a mut [u8],
) -> anyhow::Result<Packet<'a>> {
let mut builder = Builder::new_query(1, true);
builder.add_question(domain, false, record_type, QueryClass::IN);
let packet = builder.build().unwrap();
udp.connect(name_server)
.with_context(|| format!("DNS {:?} error ", name_server))?;
let mut count = 0;
let len = loop {
udp.send(&packet)?;
match udp.recv(buf) {
Ok(len) => {
break len;
}
Err(e) => {
if e.kind() == io::ErrorKind::TimedOut || e.kind() == io::ErrorKind::WouldBlock {
count += 1;
if count < 3 {
continue;
}
}
Err(e).with_context(|| format!("DNS {:?} recv error ", name_server))?
}
};
};
let pkt = Packet::parse(&buf[..len])
.with_context(|| format!("domain {:?} DNS {:?} data error ", domain, name_server))?;
if pkt.header.response_code != ResponseCode::NoError {
return Err(anyhow::anyhow!(
"response_code {} DNS {:?} domain {:?}",
pkt.header.response_code,
name_server,
domain
));
}
if pkt.answers.len() == 0 {
return Err(anyhow::anyhow!(
"No records received DNS {:?} domain {:?}",
name_server,
domain
));
}
Ok(pkt)
}
pub fn txt_dns(domain: &str, name_server: String) -> anyhow::Result<Vec<SocketAddr>> {
let name_server: SocketAddr = name_server.parse()?;
let udp = bind_udp(name_server)?;
let mut buf = [0; 65536];
let message = query(&udp, domain, name_server, QueryType::TXT, &mut buf)?;
let mut rs = Vec::new();
for record in message.answers {
if let RData::TXT(txt) = record.data {
for x in txt.iter() {
let txt = std::str::from_utf8(x).context("record type txt is not string")?;
let addr = SocketAddr::from_str(&txt.to_string())
.context("record type txt is not SocketAddr")?;
rs.push(addr);
}
}
}
Ok(rs)
}
fn bind_udp(name_server: SocketAddr) -> anyhow::Result<UdpSocket> {
let udp = if name_server.is_ipv4() {
UdpSocket::bind("0.0.0.0:0")?
} else {
UdpSocket::bind("[::]:0")?
};
udp.set_read_timeout(Some(Duration::from_millis(800)))?;
Ok(udp)
}
pub fn a_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv4Addr>> {
let name_server: SocketAddr = name_server.parse()?;
let udp = bind_udp(name_server)?;
let mut buf = [0; 65536];
let message = query(&udp, &domain, name_server, QueryType::A, &mut buf)?;
let mut rs = Vec::new();
for record in message.answers {
if let RData::A(a) = record.data {
rs.push(a.0);
}
}
Ok(rs)
}
pub fn aaaa_dns(domain: String, name_server: String) -> anyhow::Result<Vec<Ipv6Addr>> {
let name_server: SocketAddr = name_server.parse()?;
let udp = bind_udp(name_server)?;
let mut buf = [0; 65536];
let message = query(&udp, &domain, name_server, QueryType::AAAA, &mut buf)?;
let mut rs = Vec::new();
for record in message.answers {
if let RData::AAAA(a) = record.data {
rs.push(a.0);
}
}
Ok(rs)
}
+3
View File
@@ -7,3 +7,6 @@ pub use scheduler::Scheduler;
mod counter;
pub use counter::*;
mod dns_query;
pub use dns_query::*;
+1 -1
View File
@@ -52,7 +52,7 @@ impl Scheduler {
run(receiver, s_inner);
worker.stop_all();
})
.unwrap();
.expect("Scheduler");
Ok(s)
}
pub fn timeout<F>(&self, time: Duration, f: F) -> bool
+3 -1
View File
@@ -96,7 +96,9 @@ impl Device {
.map_err(|e| io::Error::new(e.kind(), format!("TAP_WIN_IOCTL_GET_MAC,err={:?}", e)))?;
let index = ffi::luid_to_index(&luid).map(|index| index as u32)?;
// 设置网卡跃点
netsh::set_interface_metric(index, 0)?;
if let Err(e) = netsh::set_interface_metric(index, 0) {
log::warn!("{:?}",e);
}
let device = Self {
handle,
index,
+3 -1
View File
@@ -117,7 +117,9 @@ impl Device {
win_tun.WintunGetAdapterLUID(adapter, &mut luid as *mut wintun_raw::NET_LUID);
let index = ffi::luid_to_index(&std::mem::transmute(luid)).map(|index| index as u32)?;
// 设置网卡跃点
netsh::set_interface_metric(index, 0)?;
if let Err(e) = netsh::set_interface_metric(index, 0) {
log::warn!("{:?}",e);
}
Ok(Self {
luid: std::mem::transmute(luid),
index,