This commit is contained in:
lubeilin
2023-03-10 23:01:57 +08:00
parent ebf84db204
commit 5b2c2435d5
39 changed files with 2493 additions and 2552 deletions
+3
View File
@@ -0,0 +1,3 @@
[submodule "switch/p2p_channel"]
path = switch/p2p_channel
url = [email protected]:lbl8603/p2p_channel.git
+4 -2
View File
@@ -13,17 +13,19 @@ console = "0.15.2"
dirs = "4.0.0" dirs = "4.0.0"
log = "0.4.17" log = "0.4.17"
log4rs = "1.2.0" log4rs = "1.2.0"
tokio = { version = "1.24.1", features = ["full"] } #tokio = { version = "1.24.1", features = ["full"] }
chrono = "0.4.23" chrono = "0.4.23"
serde = "1.0" serde = "1.0"
serde_yaml = "0.9" serde_yaml = "0.9"
serde_json = "1.0.94"
crossbeam = "0.8.2" crossbeam = "0.8.2"
lazy_static = "1.4.0" lazy_static = "1.4.0"
parking_lot = "0.12.1" parking_lot = "0.12.1"
#parity-tokio-ipc = "0.9.0" #parity-tokio-ipc = "0.9.0"
futures = "0.3" #futures = "0.3"
os_info = "3.5.1"
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies] [target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
sudo = "0.6.0" sudo = "0.6.0"
+43 -5
View File
@@ -2,15 +2,17 @@ use std::io;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket}; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
use std::time::Duration; use std::time::Duration;
use crate::command::entity::{DeviceItem, RouteItem, Status};
pub struct CommandClient { pub struct CommandClient {
udp: UdpSocket, udp: UdpSocket,
} }
impl CommandClient { impl CommandClient {
pub fn new() -> io::Result<Self> { pub fn new() -> io::Result<Self> {
let port = crate::config::read_command_port().unwrap(); let port = crate::config::read_command_port()?;
let udp = UdpSocket::bind("127.0.0.1:0")?; let udp = UdpSocket::bind("127.0.0.1:0")?;
udp.set_read_timeout(Some(Duration::from_secs(5)))?; udp.set_read_timeout(Some(Duration::from_secs(2)))?;
udp.connect(SocketAddr::V4(SocketAddrV4::new( udp.connect(SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::new(127, 0, 0, 1), Ipv4Addr::new(127, 0, 0, 1),
port, port,
@@ -20,16 +22,52 @@ impl CommandClient {
} }
impl CommandClient { impl CommandClient {
pub fn list(&self) -> io::Result<String> { pub fn list(&self) -> io::Result<Vec<DeviceItem>> {
self.udp.send(b"list")?; self.udp.send(b"list")?;
let mut buf = [0; 10240]; let mut buf = [0; 10240];
let len = self.udp.recv(&mut buf)?; let len = self.udp.recv(&mut buf)?;
Ok(String::from_utf8(buf[..len].to_vec()).unwrap()) match serde_json::from_slice::<Vec<DeviceItem>>(&buf[..len]) {
Ok(val) => {
Ok(val)
}
Err(e) => {
log::error!("{:?}",e);
Err(io::Error::new(io::ErrorKind::Other, "data error"))
}
}
} }
pub fn status(&self) -> io::Result<String> { pub fn route(&self) -> io::Result<Vec<RouteItem>> {
self.udp.send(b"route")?;
let mut buf = [0; 10240];
let len = self.udp.recv(&mut buf)?;
match serde_json::from_slice::<Vec<RouteItem>>(&buf[..len]) {
Ok(val) => {
Ok(val)
}
Err(e) => {
log::error!("{:?}",e);
Err(io::Error::new(io::ErrorKind::Other, "data error"))
}
}
}
pub fn status(&self) -> io::Result<Status> {
self.udp.send(b"status")?; self.udp.send(b"status")?;
let mut buf = [0; 10240]; let mut buf = [0; 10240];
let len = self.udp.recv(&mut buf)?; let len = self.udp.recv(&mut buf)?;
match serde_json::from_slice::<Status>(&buf[..len]) {
Ok(val) => {
Ok(val)
}
Err(e) => {
log::error!("{:?},{:?}",&buf[..len],e);
Err(io::Error::new(io::ErrorKind::Other, "data error"))
}
}
}
pub fn stop(&self) -> io::Result<String> {
self.udp.send(b"stop")?;
let mut buf = [0; 10240];
let len = self.udp.recv(&mut buf)?;
Ok(String::from_utf8(buf[..len].to_vec()).unwrap()) Ok(String::from_utf8(buf[..len].to_vec()).unwrap())
} }
} }
+34
View File
@@ -0,0 +1,34 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct Status {
pub name: String,
pub virtual_ip: String,
pub virtual_gateway: String,
pub virtual_netmask: String,
pub connect_status: String,
pub relay_server: String,
pub nat_type: String,
pub public_ips: String,
pub local_ip: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct RouteItem {
pub destination: String,
pub next_hop: String,
pub metric: String,
pub rt: String,
pub interface: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct DeviceItem {
pub name: String,
pub virtual_ip: String,
pub nat_type: String,
pub public_ips: String,
pub local_ip: String,
pub nat_traversal_type: String,
pub rt: String,
pub status: String,
}
+1
View File
@@ -1,2 +1,3 @@
pub mod client; pub mod client;
pub mod server; pub mod server;
pub mod entity;
+124 -98
View File
@@ -3,9 +3,9 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
use std::sync::Arc; use std::sync::Arc;
use console::style; use console::style;
use switch::core::Switch;
use crate::command::entity::{DeviceItem, RouteItem, Status};
use switch::handle::{PeerDeviceStatus, RouteType};
use switch::Switch;
pub struct CommandServer {} pub struct CommandServer {}
@@ -54,111 +54,137 @@ impl CommandServer {
} }
} }
pub fn command_route(switch: &Switch) -> Vec<RouteItem> {
let route_table = switch.route_table();
let mut route_list = Vec::with_capacity(route_table.len());
for (destination, route) in route_table {
let next_hop = switch.route_key(&route.route_key()).map_or(String::new(), |v| v.to_string());
let metric = route.metric.to_string();
let rt = if route.rt < 0 {
"".to_string()
} else {
route.rt.to_string()
};
let interface = route.addr.to_string();
let item = RouteItem {
destination: destination.to_string(),
next_hop,
metric,
rt,
interface,
};
route_list.push(item);
}
route_list
}
pub fn command_list(switch: &Switch) -> Vec<DeviceItem> {
let device_list = switch.device_list();
let mut list = Vec::new();
for peer in device_list {
let name = peer.name;
let virtual_ip = peer.virtual_ip.to_string();
let (nat_type, public_ips, local_ip) = if let Some(nat_info) = switch.peer_nat_info(&peer.virtual_ip) {
let nat_type = format!("{:?}", nat_info.nat_type);
let public_ips: Vec<String> = nat_info.public_ips.iter().map(|v| v.to_string()).collect();
let public_ips = public_ips.join(",");
let local_ip = nat_info.local_ip.to_string();
(nat_type, public_ips, local_ip)
} else {
("".to_string(), "".to_string(), "".to_string())
};
let (nat_traversal_type, rt) = if let Some(route) = switch.route(&peer.virtual_ip) {
let nat_traversal_type = if route.metric == 1 { "p2p" } else { "relay" }.to_string();
let rt = if route.rt < 0 {
"".to_string()
} else {
route.rt.to_string()
};
(nat_traversal_type, rt)
} else {
("relay".to_string(), "".to_string())
};
let status = format!("{:?}", peer.status);
let item = DeviceItem {
name,
virtual_ip,
nat_type,
public_ips,
local_ip,
nat_traversal_type,
rt,
status,
};
list.push(item);
}
list
}
pub fn command_status(switch: &Switch) -> Status {
let current_device = switch.current_device();
let nat_info = switch.nat_info();
let name = switch.name().to_string();
let virtual_ip = current_device.virtual_ip().to_string();
let virtual_gateway = current_device.virtual_gateway().to_string();
let virtual_netmask = current_device.virtual_netmask.to_string();
let connect_status = format!("{:?}", switch.connection_status());
let relay_server = current_device.connect_server.to_string();
let nat_type = format!("{:?}", nat_info.nat_type);
let public_ips: Vec<String> = nat_info.public_ips.iter().map(|v| v.to_string()).collect();
let public_ips = public_ips.join(",");
let local_ip = nat_info.local_ip.to_string();
Status {
name,
virtual_ip,
virtual_gateway,
virtual_netmask,
connect_status,
relay_server,
nat_type,
public_ips,
local_ip,
}
}
fn command(cmd: &str, switch: &Switch) -> io::Result<String> { fn command(cmd: &str, switch: &Switch) -> io::Result<String> {
let mut out_str = String::new(); let out_str = match cmd {
match cmd { "route" => {
"list" => { match serde_json::to_string(&command_route(switch)) {
let server_rt = switch.server_rt(); Ok(str) => {
let device_list = switch.device_list(); str
if device_list.is_empty() { }
return Ok("No other devices found\n".to_string()); Err(e) => {
format!("{:?}", e)
}
} }
for peer_device_info in device_list { }
let route = switch.route(&peer_device_info.virtual_ip); "list" => {
let str = if peer_device_info.status == PeerDeviceStatus::Online { match serde_json::to_string(&command_list(switch)) {
if route.route_type == RouteType::P2P { Ok(str) => {
let str = if route.rt >= 0 { str
format!( }
"[{}] {}(p2p delay:{}ms)\n", Err(e) => {
peer_device_info.name, peer_device_info.virtual_ip, route.rt format!("{:?}", e)
) }
} else {
format!(
"[{}] {}(p2p)",
peer_device_info.name, peer_device_info.virtual_ip
)
};
style(str).green().to_string()
} else {
let str = if server_rt >= 0 {
format!(
"[{}] {}(relay delay:{}ms)\n",
peer_device_info.name,
peer_device_info.virtual_ip,
server_rt * 2
)
} else {
format!(
"[{}] {}(relay)\n",
peer_device_info.name, peer_device_info.virtual_ip
)
};
style(str).blue().to_string()
}
} else {
let str = format!(
"[{}] {}(Offline)\n",
peer_device_info.name, peer_device_info.virtual_ip
);
style(str).red().to_string()
};
out_str.push_str(&str);
} }
} }
"status" => { "status" => {
let server_rt = switch.server_rt(); match serde_json::to_string(&command_status(switch)) {
let current_device = switch.current_device(); Ok(str) => {
let str = format!("Virtual ip:{}\n", style(current_device.virtual_ip).green()); str
out_str.push_str(&str); }
let str = format!( Err(e) => {
"Virtual gateway:{}\n", format!("{:?}", e)
style(current_device.virtual_gateway).green() }
);
out_str.push_str(&str);
let str = format!(
"Connection status :{}\n",
style(format!("{:?}", switch.connection_status())).green()
);
out_str.push_str(&str);
let str = format!(
"Relay server :{}\n",
style(current_device.connect_server).green()
);
out_str.push_str(&str);
if server_rt >= 0 {
let str = format!("Delay of relay server :{}ms\n", style(server_rt).green());
out_str.push_str(&str);
}
if let Some(nat_info) = switch.nat_info() {
let str = format!(
"NAT type :{}",
style(format!("{:?}", nat_info.nat_type)).green()
);
out_str.push_str(&str);
} }
} }
"help" | "h" => { "stop" => {
let str = format!("Options: \n"); switch.stop()?;
out_str.push_str(&str); "stopping".to_string()
let str = format!(
"{} , Query the virtual IP of other devices\n",
style("list").green()
);
out_str.push_str(&str);
let str = format!("{} , View current device status\n", style("status").green());
out_str.push_str(&str);
let str = format!("{} , Exit the program\n", style("exit").green());
out_str.push_str(&str);
}
"exit" => {
switch.stop_async();
} }
_ => { _ => {
let str = format!("command '{}' not fount. \n", style(cmd).red()); format!("command '{}' not fount. \n Try to enter: 'help'\n", cmd)
out_str.push_str(&str);
let str = format!("Try to enter: '{}'\n", style("help").green());
out_str.push_str(&str);
} }
} };
Ok(out_str) Ok(out_str)
} }
+64
View File
@@ -0,0 +1,64 @@
use std::io;
use std::path::PathBuf;
pub fn log_init_service(home: PathBuf) -> io::Result<()> {
if !home.exists() {
std::fs::create_dir(&home)?;
}
let logfile = log4rs::append::file::FileAppender::builder()
// Pattern: https://docs.rs/log4rs/*/log4rs/encode/pattern/index.html
.encoder(Box::new(log4rs::encode::pattern::PatternEncoder::new(
"{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}\n",
)))
.build(home.join("switch-service.log"))?;
match log4rs::Config::builder()
.appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile)))
.build(
log4rs::config::Root::builder()
.appender("logfile")
.build(log::LevelFilter::Info),
) {
Ok(config) => {
let _ = log4rs::init_config(config);
}
Err(_) => {}
}
Ok(())
}
pub fn log_init() -> io::Result<()> {
let home = dirs::home_dir().unwrap().join(".switch");
if !home.exists() {
std::fs::create_dir(&home)?;
}
let stderr = log4rs::append::console::ConsoleAppender::builder()
.target(log4rs::append::console::Target::Stderr)
.build();
let logfile = log4rs::append::file::FileAppender::builder()
// Pattern: https://docs.rs/log4rs/*/log4rs/encode/pattern/index.html
.encoder(Box::new(log4rs::encode::pattern::PatternEncoder::new(
"{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}\n",
)))
.build(home.join("switch.log"))?;
match log4rs::Config::builder()
.appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile)))
.appender(
log4rs::config::Appender::builder()
.filter(Box::new(log4rs::filter::threshold::ThresholdFilter::new(
log::LevelFilter::Error,
)))
.build("stderr", Box::new(stderr)),
)
.build(
log4rs::config::Root::builder()
.appender("logfile")
.appender("stderr")
.build(log::LevelFilter::Info),
) {
Ok(config) => {
let _ = log4rs::init_config(config);
}
Err(_) => {}
}
Ok(())
}
+123 -4
View File
@@ -1,11 +1,104 @@
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::net::{SocketAddr, ToSocketAddrs};
use std::path::PathBuf; use std::path::PathBuf;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use parking_lot::Mutex; use parking_lot::Mutex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{BaseArgs, StartArgs};
pub mod log_config;
pub struct BaseConfig {
pub name: String,
pub token: String,
pub server: SocketAddr,
pub nat_test_server: Vec<SocketAddr>,
pub device_id: String,
}
pub fn default_config(start_args: StartArgs) -> Result<BaseConfig, String> {
let args_config = read_config();
if args_config.is_none() && start_args.token.is_none() {
return Err("找不到token(Token not found)".to_string());
}
let token = start_args.token.unwrap_or_else(|| args_config.as_ref().unwrap().token.clone()).trim().to_string();
if token.is_empty() {
return Err("token不能为空(Token cannot be empty)".to_string());
}
if token.len() > 64 {
return Err("token不能超过64字符(Token cannot exceed 64 characters)".to_string());
}
let name = start_args.name.unwrap_or_else(|| {
if let Some(c) = &args_config {
c.name.clone()
} else {
os_info::get().to_string()
}
});
let name = name.trim();
let name = if name.len() > 64 {
name[..64].to_string()
} else {
name.to_string()
};
let device_id = start_args.device_id.unwrap_or_else(|| {
if let Some(c) = &args_config {
if !c.device_id.is_empty() {
return c.device_id.clone();
}
}
if let Ok(Some(mac_address)) = mac_address::get_mac_address() {
mac_address.to_string()
} else {
"".to_string()
}
});
if device_id.is_empty() || device_id.len() > 64 {
return Err("设备id不能为空并且长度不能大于64字符(The device id cannot be empty and the length cannot be greater than 64 characters)".to_string());
}
let server = match start_args.server.unwrap_or_else(|| {
if let Some(c) = &args_config {
if !c.server.is_empty() {
return c.server.clone();
}
}
"nat1.wherewego.top:29875".to_string()
}).to_socket_addrs() {
Ok(mut server) => {
if let Some(addr) = server.next() {
addr
} else {
return Err("中继服务器地址错误( Relay server address error)".to_string());
}
}
Err(e) => {
return Err(format!("中继服务器地址错误( Relay server address error) :{:?}", e));
}
};
let nat_test_server = start_args.nat_test_server.unwrap_or_else(|| {
if let Some(c) = &args_config {
if !c.nat_test_server.is_empty() {
return c.nat_test_server.join(",");
}
}
"nat1.wherewego.top:35061,nat1.wherewego.top:35062,nat2.wherewego.top:35061,nat2.wherewego.top:35062".to_string()
}).split(",").flat_map(|a| a.to_socket_addrs()).flatten()
.collect::<Vec<_>>();
if nat_test_server.is_empty() {
return Err("NAT检测服务地址错误(NAT detection service address error)".to_string());
}
let base_config = BaseConfig {
name,
token,
server,
nat_test_server,
device_id,
};
Ok(base_config)
}
lazy_static! { lazy_static! {
static ref CONFIG: Mutex<Option<ArgsConfig>> = Mutex::new(None); static ref CONFIG: Mutex<Option<ArgsConfig>> = Mutex::new(None);
@@ -14,17 +107,43 @@ lazy_static! {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ArgsConfig { pub struct ArgsConfig {
#[serde(default = "default_version")]
pub version: String,
#[serde(default = "default_str")]
pub token: String, pub token: String,
pub name: Option<String>, #[serde(default = "default_str")]
pub name: String,
pub command_port: Option<u16>, pub command_port: Option<u16>,
#[serde(default = "default_str")]
pub server: String,
#[serde(default = "default_resource_vec")]
pub nat_test_server: Vec<String>,
#[serde(default = "default_str")]
pub device_id: String,
}
fn default_version() -> String {
"1.0".to_string()
}
fn default_str() -> String {
"".to_string()
}
fn default_resource_vec() -> Vec<String> {
vec![]
} }
impl ArgsConfig { impl ArgsConfig {
pub fn new(token: String, name: Option<String>) -> Self { pub fn new(token: String, name: String, server: String, nat_test_server: Vec<String>, device_id: String) -> Self {
Self { Self {
version: "1.0".to_string(),
token, token,
name, name,
command_port: None, command_port: None,
server,
nat_test_server,
device_id,
} }
} }
} }
@@ -66,13 +185,13 @@ pub fn read_config() -> Option<ArgsConfig> {
return c; return c;
} }
if let Some(home) = SWITCH_HOME_PATH.lock().clone() { if let Some(home) = SWITCH_HOME_PATH.lock().clone() {
match read_config_(home) { match read_config_(home.to_path_buf()) {
Ok(config) => { Ok(config) => {
lock.replace(config.clone()); lock.replace(config.clone());
Some(config) Some(config)
} }
Err(e) => { Err(e) => {
log::error!("{:?}", e); log::error!("{:?},path:{:?}", e,home);
None None
} }
} }
+69
View File
@@ -0,0 +1,69 @@
use std::net::Ipv4Addr;
use console::style;
use switch::Route;
use crate::command::entity::{DeviceItem, RouteItem, Status};
pub mod table;
pub fn console_status(status: Status) {
println!("Name: {}", style(status.name).green());
println!("Virtual ip: {}", style(status.virtual_ip).green());
println!("Virtual gateway: {}", style(status.virtual_gateway).green());
println!("Virtual netmask: {}", style(status.virtual_netmask).green());
println!("Connection status: {}", style(status.connect_status).green());
println!("NAT type: {}", style(status.nat_type).green());
println!("Relay server: {}", style(status.relay_server).green());
println!("Public ips: {}", style(status.public_ips).green());
println!("Local ip: {}", style(status.local_ip).green());
}
pub fn console_route_table(list: Vec<RouteItem>) {
if list.is_empty() {
println!("No route found");
return;
}
let mut out_list = Vec::with_capacity(list.len());
//表头
out_list.push(vec!["Destination".to_string(), "Next Hop".to_string(), "Metric".to_string(),
"Rt".to_string(), "Interface".to_string()]);
for item in list {
out_list.push(vec![item.destination, item.next_hop, item.metric,
item.rt, item.interface]);
}
table::println_table(out_list)
}
pub fn console_device_list(list: Vec<DeviceItem>) {
if list.is_empty() {
println!("No other devices found");
return;
}
let mut out_list = Vec::with_capacity(list.len());
//表头
out_list.push(vec!["Name".to_string(), "Virtual Ip".to_string(), "P2P/Relay".to_string(), "Rt".to_string(), "Status".to_string()]);
for item in list {
out_list.push(vec![item.name, item.virtual_ip, item.nat_traversal_type,
item.rt, item.status]);
}
table::println_table(out_list)
}
pub fn console_device_list_all(list: Vec<DeviceItem>) {
if list.is_empty() {
println!("No other devices found");
return;
}
let mut out_list = Vec::with_capacity(list.len());
//表头
out_list.push(vec!["Name".to_string(), "Virtual Ip".to_string(), "NAT Type".to_string(),
"Public Ips".to_string(), "Local Ip".to_string(), "P2P/Relay".to_string(),
"Rt".to_string(), "Status".to_string()]);
for item in list {
out_list.push(vec![item.name, item.virtual_ip, item.nat_type,
item.public_ips, item.local_ip, item.nat_traversal_type,
item.rt, item.status]);
}
table::println_table(out_list)
}
+26
View File
@@ -0,0 +1,26 @@
const NODE: &str = "+";
const EDGE: &str = "-";
const HIGH: &str = "|";
const SPACE: &str = " ";
const EMPTY: &str = "";
pub fn println_table(table: Vec<Vec<String>>) {
if table.is_empty() {
return;
}
let mut width_list = vec![0; table[0].len()];
for in_list in table.iter() {
for (index, item) in in_list.iter().enumerate() {
let width = console::measure_text_width(item)+6;
if width_list[index] < width {
width_list[index] = width;
}
}
}
for in_list in table {
for (index, item) in in_list.iter().enumerate() {
print!("{item:width$}", item = item, width = width_list[index]);
}
println!()
}
}
+179 -189
View File
@@ -1,104 +1,183 @@
use std::io; use std::io;
use std::net::ToSocketAddrs; use std::net::{SocketAddr, ToSocketAddrs};
use std::path::PathBuf; use std::path::PathBuf;
use clap::Parser; use clap::{Parser, Subcommand};
use console::style; use console::style;
use switch::core::{Config, Switch};
use switch::handle::PeerDeviceStatus;
use crate::config::log_config::{log_init, log_init_service};
use switch::handle::{PeerDeviceStatus, RouteType};
use switch::*;
#[cfg(windows)]
mod command; mod command;
#[cfg(windows)]
mod config; mod config;
#[cfg(windows)] #[cfg(windows)]
mod windows; mod windows;
mod unix;
mod console_out;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command( #[command(
author = "Lu Beilin", author = "Lu Beilin",
version, version,
about = "一个虚拟网络工具,启动后会获取一个ip,相同token下的设备之间可以用ip直接通信" about = "一个虚拟网络工具,启动后会获取一个ip,相同token下的设备之间可以用ip直接通信"
)] )]
struct Args { pub struct BaseArgs {
/// 32位字符 // /// 不超过64个字符
// /// 相同token的设备之间才能通信。
// /// 建议使用uuid保证唯一性。
// /// No more than 64 characters
// /// Only devices with the same token can communicate with each other.
// /// It is recommended to use uuid to ensure uniqueness
// #[arg(long)]
// token: Option<String>,
// /// 给设备一个名称,为空时默认用系统版本信息
// /// Give the device a name. If it is blank, the system version information will be used by default
// #[arg(long)]
// name: Option<String>,
// /// 设备唯一标识,为空时默认使用MAC地址,不超过64个字符
// /// Unique identification of the device. If it is blank, the MAC address is used by default. No more than 64 characters
// #[arg(long)]
// device_id: Option<String>,
// /// 注册和中继服务器地址
// /// Register and relay server address
// #[arg(long)]
// server: Option<String>,
// /// NAT检测服务地址,使用逗号分隔
// /// NAT detection service address. Use comma to separate
// #[arg(long)]
// nat_test_server: Option<String>,
// /// 开机自启动
// /// Software automatically start up at boot.
// #[cfg(windows)]
// #[arg(long)]
// auto: bool,
// #[arg(long)]
// start: bool,
//
// // /// 启动,启动时可以附加参数 --token,如果没有token,则会读取配置文件中上一次使用的token
// // /// 安装服务后,会以服务的方式在后台启动,此时可以关闭命令行窗口
// // /// When starting, you can attach the parameter -- token. If there is no token, the last token used in the configuration file will be read. After installing the service, it will be started in the background as a service. At this time, you can close the command line window
// // #[arg(subcommand)]
// // start111: Option<StartArgs>,
// #[arg(long)]
// /// 停止,启动服务后,使用 --stop停止服务
// /// Stop. After starting the service, use -- stop to stop the service
// stop: bool,
// /// 启动服务后,使用 --list 查看设备列表
// /// After starting the service, use -- list to view the device list
// #[arg(long)]
// list: bool,
// /// 启动服务后,使用 --status 查看设备状态
// /// After starting the service, use -- status to view the device status
// #[arg(long)]
// status: bool,
// /// 启动服务后,使用 --route 查看所有路由
// /// After starting the service, use -- route to View all routes
// #[arg(long)]
// route: bool,
//
// /// 安装服务,安装后可以后台运行,需要指定安装路径
// /// The installation service can run in the background after installation, and the installation path needs to be specified
// #[cfg(windows)]
// #[arg(long)]
// install: Option<String>,
// /// 卸载服务
// /// Uninstall service
// #[cfg(windows)]
// #[arg(long)]
// uninstall: bool,
#[clap(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
/// 启动
Start(StartArgs),
/// 停止后台服务
Stop,
/// 安装服务
/// Install service
#[cfg(windows)]
Install(InstallArgs),
/// 卸载服务
/// Uninstall service
#[cfg(windows)]
Uninstall,
/// 配置
#[cfg(windows)]
Config(ConfigArgs),
/// 查看路由
/// View route
Route,
/// 查看设备列表
/// View device list
List {
/// 查看所有
#[arg(short, long)]
all: bool
},
/// 查看设备当前状态
/// View the current status of the device
Status,
}
#[derive(Parser, Debug)]
pub struct StartArgs {
/// 不超过64个字符
/// 相同token的设备之间才能通信。 /// 相同token的设备之间才能通信。
/// 建议使用uuid保证唯一性。 /// 建议使用uuid保证唯一性。
/// 32-bit characters. /// No more than 64 characters
/// Only devices with the same token can communicate with each other. /// Only devices with the same token can communicate with each other.
/// It is recommended to use uuid to ensure uniqueness /// It is recommended to use uuid to ensure uniqueness
#[arg(long)] #[arg(long)]
token: String, token: Option<String>,
/// 给设备一个名称,为空时默认用系统版本信息 /// 给设备一个名称,为空时默认用系统版本信息
/// Give the device a name. If it is blank, the system version information will be used by default /// Give the device a name. If it is blank, the system version information will be used by default
#[arg(long)] #[arg(long, action)]
name: Option<String>, name: Option<String>,
/// 设备唯一标识,为空时默认使用MAC地址,不超过64个字符
/// Unique identification of the device. If it is blank, the MAC address is used by default. No more than 64 characters
#[arg(long)]
device_id: Option<String>,
/// 注册和中继服务器地址
/// Register and relay server address
#[arg(long)]
server: Option<String>,
/// NAT检测服务地址,使用逗号分隔
/// NAT detection service address. Use comma to separate
#[arg(long)]
nat_test_server: Option<String>,
} }
#[cfg(windows)] #[derive(Parser, Debug)]
fn log_init_service(home: PathBuf) -> io::Result<()> { pub struct InstallArgs {
if !home.exists() { /// 安装路径
std::fs::create_dir(&home)?; /// Service installation path
} #[arg(long)]
let logfile = log4rs::append::file::FileAppender::builder() path: String,
// Pattern: https://docs.rs/log4rs/*/log4rs/encode/pattern/index.html /// 服务开机自启动
.encoder(Box::new(log4rs::encode::pattern::PatternEncoder::new( /// Autostart on system startup
"{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}\n", #[arg(long)]
))) auto: bool,
.build(home.join("switch-service.log"))?;
match log4rs::Config::builder()
.appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile)))
.build(
log4rs::config::Root::builder()
.appender("logfile")
.build(log::LevelFilter::Info),
) {
Ok(config) => {
let _ = log4rs::init_config(config);
}
Err(_) => {}
}
Ok(())
} }
fn log_init() -> io::Result<()> { #[derive(Parser, Debug)]
let home = dirs::home_dir().unwrap().join(".switch"); pub struct ConfigArgs {
if !home.exists() { /// 服务开机自启动
std::fs::create_dir(&home)?; /// Autostart on system startup
} #[arg(long)]
let stderr = log4rs::append::console::ConsoleAppender::builder() auto: bool,
.target(log4rs::append::console::Target::Stderr) /// 取消服务开机自启动
.build(); /// started manually
let logfile = log4rs::append::file::FileAppender::builder() #[arg(long)]
// Pattern: https://docs.rs/log4rs/*/log4rs/encode/pattern/index.html not_auto: bool,
.encoder(Box::new(log4rs::encode::pattern::PatternEncoder::new(
"{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}\n",
)))
.build(home.join("switch.log"))?;
match log4rs::Config::builder()
.appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile)))
.appender(
log4rs::config::Appender::builder()
.filter(Box::new(log4rs::filter::threshold::ThresholdFilter::new(
log::LevelFilter::Error,
)))
.build("stderr", Box::new(stderr)),
)
.build(
log4rs::config::Root::builder()
.appender("logfile")
.appender("stderr")
.build(log::LevelFilter::Info),
) {
Ok(config) => {
let _ = log4rs::init_config(config);
}
Err(_) => {}
}
Ok(())
} }
#[cfg(windows)] #[cfg(windows)]
fn main() { fn main() {
let args: Vec<_> = std::env::args().collect(); let args: Vec<_> = std::env::args().collect();
@@ -111,10 +190,12 @@ fn main() {
windows::service::start(); windows::service::start();
return; return;
} else { } else {
let home = dirs::home_dir().unwrap().join(".switch");
config::set_home(home);
let _ = log_init(); let _ = log_init();
windows::main0(); let args = BaseArgs::parse();
windows::main0(args);
} }
// println!("{}", style("starting...").green());
} }
#[cfg(any(target_os = "linux", target_os = "macos"))] #[cfg(any(target_os = "linux", target_os = "macos"))]
@@ -132,50 +213,16 @@ fn main() {
start(args.token, args.name); start(args.token, args.name);
} }
pub fn start(token: String, name: Option<String>) { pub fn start(token: String, name: String, server_address: SocketAddr, nat_test_server: Vec<SocketAddr>, device_id: String) {
let mac_address = mac_address::get_mac_address().unwrap().unwrap().to_string(); let config = Config::new(
let server_address = "nat1.wherewego.top:29875"
.to_socket_addrs()
.unwrap()
.next()
.unwrap();
let nat_test_server = vec![
"nat1.wherewego.top:35061"
.to_socket_addrs()
.unwrap()
.next()
.unwrap(),
"nat1.wherewego.top:35062"
.to_socket_addrs()
.unwrap()
.next()
.unwrap(),
"nat2.wherewego.top:35061"
.to_socket_addrs()
.unwrap()
.next()
.unwrap(),
"nat2.wherewego.top:35062"
.to_socket_addrs()
.unwrap()
.next()
.unwrap(),
];
let switch = match Config::new(
token, token,
mac_address, device_id,
name, name,
server_address, server_address,
nat_test_server, nat_test_server,
|| {}, );
) { let switch = match Switch::start(config) {
Ok(config) => match Switch::start(config) { Ok(switch) => switch,
Ok(switch) => switch,
Err(e) => {
log::error!("{:?}", e);
return;
}
},
Err(e) => { Err(e) => {
log::error!("{:?}", e); log::error!("{:?}", e);
return; return;
@@ -187,11 +234,11 @@ pub fn start(token: String, name: Option<String>) {
let current_device = switch.current_device(); let current_device = switch.current_device();
println!( println!(
"当前虚拟ip(virtual ip): {:?}", "当前虚拟ip(virtual ip): {:?}",
style(current_device.virtual_ip).green() style(current_device.virtual_ip()).green()
); );
println!( println!(
"虚拟网关(virtual gateway): {:?}", "虚拟网关(virtual gateway): {:?}",
style(current_device.virtual_gateway).green() style(current_device.virtual_gateway()).green()
); );
loop { loop {
println!( println!(
@@ -202,14 +249,18 @@ pub fn start(token: String, name: Option<String>) {
Ok(cmd) => { Ok(cmd) => {
if command(cmd.trim(), &switch).is_err() { if command(cmd.trim(), &switch).is_err() {
println!("{}", style("stopping").red()); println!("{}", style("stopping").red());
switch.stop(); if let Err(e) = switch.stop() {
println!("stop:{:?}", e);
}
break; break;
} }
} }
Err(e) => { Err(e) => {
println!("read_line:{:?}", e); println!("read_line:{:?}", e);
println!("{}", style("stopping...").red()); println!("{}", style("stopping...").red());
switch.stop(); if let Err(e) = switch.stop() {
println!("stop:{:?}", e);
}
break; break;
} }
} }
@@ -218,81 +269,20 @@ pub fn start(token: String, name: Option<String>) {
std::process::exit(1); std::process::exit(1);
} }
fn command(cmd: &str, switch: &Switch) -> Result<(), ()> { fn command(cmd: &str, switch: &Switch) -> Result<(), ()> {
match cmd { match cmd {
"route" => {
let list = command::server::command_route(switch);
console_out::console_route_table(list);
}
"list" => { "list" => {
let server_rt = switch.server_rt(); let list = command::server::command_list(switch);
let device_list = switch.device_list(); console_out::console_device_list(list);
if device_list.is_empty() {
println!("No other devices found");
return Ok(());
}
for peer_device_info in device_list {
let route = switch.route(&peer_device_info.virtual_ip);
if peer_device_info.status == PeerDeviceStatus::Online {
if route.route_type == RouteType::P2P {
let str = if route.rt >= 0 {
format!(
"[{}] {}(p2p delay:{}ms)",
peer_device_info.name, peer_device_info.virtual_ip, route.rt
)
} else {
format!(
"[{}] {}(p2p)",
peer_device_info.name, peer_device_info.virtual_ip
)
};
println!("{}", style(str).green());
} else {
let str = if server_rt >= 0 {
format!(
"[{}] {}(relay delay:{}ms)",
peer_device_info.name,
peer_device_info.virtual_ip,
server_rt * 2
)
} else {
format!(
"[{}] {}(relay)",
peer_device_info.name, peer_device_info.virtual_ip
)
};
println!("{}", style(str).blue());
}
} else {
let str = format!(
"[{}] {}(Offline)",
peer_device_info.name, peer_device_info.virtual_ip
);
println!("{}", style(str).red());
}
}
} }
"status" => { "status" => {
let server_rt = switch.server_rt(); let status = command::server::command_status(switch);
let current_device = switch.current_device(); console_out::console_status(status);
println!("Virtual ip:{}", style(current_device.virtual_ip).green());
println!(
"Virtual gateway:{}",
style(current_device.virtual_gateway).green()
);
println!(
"Connection status :{}",
style(format!("{:?}", switch.connection_status())).green()
);
println!(
"Relay server :{}",
style(current_device.connect_server).green()
);
if server_rt >= 0 {
println!("Delay of relay server :{}ms", style(server_rt).green());
}
if let Some(nat_info) = switch.nat_info() {
println!(
"NAT type :{}",
style(format!("{:?}", nat_info.nat_type)).green()
);
}
} }
"help" | "h" => { "help" | "h" => {
println!("Options: "); println!("Options: ");
View File
+178 -140
View File
@@ -2,8 +2,8 @@ use std::ffi::OsString;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
use std::{io, thread}; use std::{io, thread};
use std::net::ToSocketAddrs;
use clap::Parser;
use console::style; use console::style;
use windows_service::service::{ use windows_service::service::{
@@ -12,173 +12,206 @@ use windows_service::service::{
use windows_service::service_manager::{ServiceManager, ServiceManagerAccess}; use windows_service::service_manager::{ServiceManager, ServiceManagerAccess};
use windows_service::Error; use windows_service::Error;
use crate::config; use crate::{BaseArgs, Commands, config, console_out};
use crate::config::BaseConfig;
pub mod service; pub mod service;
mod windows_admin_check; mod windows_admin_check;
#[derive(Parser, Debug)] pub const SERVICE_FLAG: &'static str = "start_switch_service_v1_";
#[command( pub const SERVICE_NAME: &'static str = "switch-service-v1";
author = "Lu Beilin",
version,
about = "一个虚拟网络工具,启动后会获取一个ip,相同token下的设备之间可以用ip直接通信"
)]
struct Args {
/// 32位字符
/// 相同token的设备之间才能通信。
/// 建议使用uuid保证唯一性。
/// 32-bit characters.
/// Only devices with the same token can communicate with each other.
/// It is recommended to use uuid to ensure uniqueness
#[arg(long)]
token: Option<String>,
/// 给设备一个名称,为空时默认用系统版本信息
/// Give the device a name. If it is blank, the system version information will be used by default
#[arg(long)]
name: Option<String>,
/// 安装服务,安装后可以后台运行,需要指定安装路径
/// The installation service can run in the background after installation, and the installation path needs to be specified
#[arg(long)]
install: Option<String>,
/// 卸载服务
/// Uninstall service
#[arg(long)]
uninstall: bool,
/// 启动,启动时可以附加参数 --token,如果没有token,则会读取配置文件中上一次使用的token
/// 安装服务后,会以服务的方式在后台启动,此时可以关闭命令行窗口
/// When starting, you can attach the parameter -- token. If there is no token, the last token used in the configuration file will be read. After installing the service, it will be started in the background as a service. At this time, you can close the command line window
#[arg(long)]
start: bool,
#[arg(long)]
/// 停止,安装服务后,使用 --stop停止服务
/// Stop. After installing the service, use -- stop to stop the service
stop: bool,
/// 启动服务后,使用 --list 查看设备列表
/// After starting the service, use -- list to view the device list
#[arg(long)]
list: bool,
/// 启动服务后,使用 --status 查看设备状态
/// After starting the service, use -- status to view the device status
#[arg(long)]
status: bool,
}
pub const SERVICE_FLAG: &'static str = "start_switch_service_";
pub const SERVICE_NAME: &'static str = "switch-service";
pub const SERVICE_TYPE: ServiceType = ServiceType::OWN_PROCESS; pub const SERVICE_TYPE: ServiceType = ServiceType::OWN_PROCESS;
pub fn main0() { fn command(cmd: &str) {
let args = Args::parse(); if let Err(e) = command_(cmd) {
if args.list || args.status { println!("{}:{:?}", style("连接服务错误(Connection service error)").red(), e);
match service_state() { }
Ok(state) => { }
if state == ServiceState::Running {
let command_client = crate::command::client::CommandClient::new().unwrap(); fn command_(cmd: &str) -> io::Result<()> {
let out = if args.list { match crate::command::client::CommandClient::new() {
command_client.list().unwrap() Ok(command_client) => {
} else if args.status { match cmd {
command_client.status().unwrap() "route" => {
} else { let list = command_client.route()?;
"".to_string() console_out::console_route_table(list);
};
println!("{}", out);
} else {
println!("服务未启动")
} }
} "list" => {
Err(e) => { let list = command_client.list()?;
println!("{:?}", e); console_out::console_device_list(list);
}
"list-all" => {
let list = command_client.list()?;
console_out::console_device_list_all(list);
}
"status" => {
let status = command_client.status()?;
console_out::console_status(status);
}
_ => {}
} }
} }
return; Err(e) => {
} log::error!("{:?}",e);
println!(
"{}:{:?}",
style("连接服务错误(Connection service error)").red(), e
);
}
};
Ok(())
}
fn admin_check() -> bool {
if !windows_admin_check::is_app_elevated() { if !windows_admin_check::is_app_elevated() {
println!( println!(
"{}", "{}",
style("请使用管理员权限运行(Please run with administrator privileges)").red() style("请使用管理员权限运行(Please run with administrator privileges)").red()
); );
return; true
} else {
false
} }
if let Some(path) = args.install { }
let path: PathBuf = path.into();
if !path.exists() { fn not_started() -> bool {
std::fs::create_dir_all(&path).unwrap(); match service_state() {
} Ok(state) => {
if !path.is_dir() { if state == ServiceState::Running {
println!("参数必须为文件目录(Parameter must be a file directory)"); return false;
} else {
if let Err(e) = install(path) {
log::error!("{:?}", e);
} else { } else {
println!("{}", style("安装成功(Installation succeeded)").green()) println!("服务未启动")
} }
} }
} else if args.uninstall { Err(e) => {
if let Err(e) = uninstall() { println!("{:?}", e);
log::error!("{:?}", e);
} else {
println!("{}", style("卸载成功(Uninstall succeeded)").green())
} }
} else if args.start { }
if args.token.is_none() { return true;
println!("{}", style("需要参数(require parameters) --token").red()); }
} else {
let token = args.token.clone().unwrap(); pub fn main0(base_args: BaseArgs) {
match service_state() { match base_args.command {
Ok(state) => { Commands::Start(args) => {
if state == ServiceState::Stopped { if admin_check() {
config::save_config(config::ArgsConfig::new( return;
token.clone(), }
args.name.clone(), match config::default_config(args) {
)) Ok(base_config) => {
.unwrap(); match service_state() {
match start() { Ok(state) => {
Ok(_) => { if state == ServiceState::Stopped {
//需要检查启动状态 config::save_config(config::ArgsConfig::new(
println!("{}", style("启动成功(Start successfully)").green()) base_config.token.clone(),
} base_config.name.clone(),
Err(e) => { base_config.server.to_string(),
log::error!("{:?}", e); base_config.nat_test_server.iter().map(|v| v.to_string()).collect::<Vec<String>>(),
base_config.device_id.clone(),
))
.unwrap();
match start() {
Ok(_) => {
//需要检查启动状态
std::thread::sleep(std::time::Duration::from_secs(2));
println!("{}", style("启动成功(Start successfully)").green())
}
Err(e) => {
log::error!("{:?}", e);
}
}
} else {
println!("服务未停止(Service not stopped)");
} }
} }
} else { Err(e) => {
println!("服务未停止(Service not stopped)"); match e {
Error::Winapi(ref e) => {
if let Some(code) = e.raw_os_error() {
if code == 1060 {
//指定的服务未安装。
println!(
"{}",
style("服务未安装,在当前进程启动(The service is not installed and started in the current process)").red()
);
crate::start(base_config.token, base_config.name, base_config.server, base_config.nat_test_server, base_config.device_id);
return;
}
}
}
_ => {}
}
println!("{:?}", e);
}
} }
} }
Err(e) => { Err(e) => {
match e { println!("{}", style(e).red());
Error::Winapi(ref e) => { }
if let Some(code) = e.raw_os_error() { };
if code == 1060 { pause();
//指定的服务未安装。 }
println!( Commands::Stop => {
"{}", if not_started() {
style("服务未安装,在当前进程启动(The service is not installed and started in the current process)").red() return;
); }
crate::start(token, args.name); match stop() {
return; Ok(_) => {
} println!("{}", style("停止成功(Stopped successfully)").green())
} }
} Err(e) => {
_ => {} log::error!("{:?}", e);
}
println!("{:?}", e);
} }
} }
pause();
} }
} else if args.stop { Commands::Install(args) => {
match stop() { let path: PathBuf = args.path.into();
Ok(_) => { if !path.exists() {
println!("{}", style("停止成功(Stopped successfully)").green()) std::fs::create_dir_all(&path).unwrap();
} }
Err(e) => { if !path.is_dir() {
println!("参数必须为文件目录(Parameter must be a file directory)");
} else {
if let Err(e) = install(path, args.auto) {
log::error!("{:?}", e);
} else {
println!("{}", style("安装成功(Installation succeeded)").green())
}
}
pause();
}
Commands::Uninstall => {
if let Err(e) = uninstall() {
log::error!("{:?}", e); log::error!("{:?}", e);
} else {
println!("{}", style("卸载成功(Uninstall succeeded)").green())
}
pause();
}
Commands::Config(args) => {}
Commands::Route => {
if not_started() {
return;
}
command("route");
}
Commands::List { all } => {
if not_started() {
return;
}
if all {
command("list-all");
} else {
command("list");
} }
} }
} else { Commands::Status => {
println!("使用参数 -h 查看帮助(Use the parameter - h to view help)") if not_started() {
return;
}
command("status");
}
} }
pause();
} }
fn pause() { fn pause() {
@@ -191,11 +224,11 @@ fn pause() {
let _ = term.read_char().unwrap(); let _ = term.read_char().unwrap();
} }
fn install(path: PathBuf) -> Result<(), Error> { fn install(path: PathBuf, auto: bool) -> Result<(), Error> {
let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE; let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE;
let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?; let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;
let current_exe_path = std::env::current_exe().unwrap(); let current_exe_path = std::env::current_exe().unwrap();
let service_path = path.join("switch-service.exe"); let service_path = path.join("switch-service-v1.exe");
std::fs::copy(current_exe_path, service_path.as_path()).unwrap(); std::fs::copy(current_exe_path, service_path.as_path()).unwrap();
if let Err(e) = std::fs::copy("wintun.dll", path.join("wintun.dll").as_path()) { if let Err(e) = std::fs::copy("wintun.dll", path.join("wintun.dll").as_path()) {
if e.kind() == io::ErrorKind::NotFound { if e.kind() == io::ErrorKind::NotFound {
@@ -210,11 +243,16 @@ fn install(path: PathBuf) -> Result<(), Error> {
launch_arguments.push(OsString::from( launch_arguments.push(OsString::from(
dirs::home_dir().unwrap().join(".switch").to_str().unwrap(), dirs::home_dir().unwrap().join(".switch").to_str().unwrap(),
)); ));
let start_type = if auto {
ServiceStartType::AutoStart
} else {
ServiceStartType::OnDemand
};
let service_info = ServiceInfo { let service_info = ServiceInfo {
name: OsString::from(SERVICE_NAME), name: OsString::from(SERVICE_NAME),
display_name: OsString::from("switch service"), display_name: OsString::from("switch service v1"),
service_type: ServiceType::OWN_PROCESS, service_type: ServiceType::OWN_PROCESS,
start_type: ServiceStartType::OnDemand, start_type,
error_control: ServiceErrorControl::Normal, error_control: ServiceErrorControl::Normal,
executable_path: service_path.into(), executable_path: service_path.into(),
launch_arguments, launch_arguments,
+50 -69
View File
@@ -6,13 +6,12 @@ use std::sync::Arc;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use std::net::ToSocketAddrs; use std::net::ToSocketAddrs;
use switch::{Config, Switch};
use windows_service::service::{ use windows_service::service::{
ServiceControl, ServiceControlAccept, ServiceExitCode, ServiceState, ServiceStatus, ServiceControl, ServiceControlAccept, ServiceExitCode, ServiceState, ServiceStatus,
}; };
use windows_service::service_control_handler::ServiceControlHandlerResult; use windows_service::service_control_handler::ServiceControlHandlerResult;
use windows_service::{define_windows_service, service_control_handler, service_dispatcher}; use windows_service::{define_windows_service, service_control_handler, service_dispatcher};
use switch::core::{Config, Switch};
use crate::windows::config::read_config; use crate::windows::config::read_config;
define_windows_service!(ffi_service_main, switch_service_main); define_windows_service!(ffi_service_main, switch_service_main);
@@ -36,8 +35,8 @@ fn service_main() -> windows_service::Result<()> {
// Handle stop // Handle stop
ServiceControl::Stop => { ServiceControl::Stop => {
log::info!("handler 服务停止");
un_parker.unpark(); un_parker.unpark();
log::info!("handler 服务停止");
ServiceControlHandlerResult::NoError ServiceControlHandlerResult::NoError
} }
_ => ServiceControlHandlerResult::NotImplemented, _ => ServiceControlHandlerResult::NotImplemented,
@@ -59,72 +58,11 @@ fn service_main() -> windows_service::Result<()> {
wait_hint: Duration::default(), wait_hint: Duration::default(),
process_id: None, process_id: None,
})?; })?;
if let Some(config) = read_config() { if let Ok(switch) = start_switch() {
let mac_address = mac_address::get_mac_address().unwrap().unwrap().to_string(); parker.park();
let un_parker = parker.unparker().clone(); if let Err(e) = switch.stop() {
let server_address = "nat1.wherewego.top:29875" log::warn!("switch stop:{:?}",e)
.to_socket_addrs() }
.unwrap()
.next()
.unwrap();
let nat_test_server = vec![
"nat1.wherewego.top:35061"
.to_socket_addrs()
.unwrap()
.next()
.unwrap(),
"nat1.wherewego.top:35062"
.to_socket_addrs()
.unwrap()
.next()
.unwrap(),
"nat2.wherewego.top:35061"
.to_socket_addrs()
.unwrap()
.next()
.unwrap(),
"nat2.wherewego.top:35062"
.to_socket_addrs()
.unwrap()
.next()
.unwrap(),
];
match Config::new(
config.token,
mac_address,
config.name,
server_address,
nat_test_server,
move || {
un_parker.unpark();
},
) {
Ok(config) => match Switch::start(config) {
Ok(switch) => {
log::info!("switch-service服务启动");
let switch = Arc::new(switch);
let command_server = crate::command::server::CommandServer::new();
let switch1 = switch.clone();
thread::spawn(move || {
if let Err(e) = command_server.start(switch1) {
log::warn!("{:?}", e);
}
});
parker.park();
switch.stop_async();
thread::sleep(Duration::from_secs(1));
log::info!("switch-service服务停止");
}
Err(e) => {
log::error!("{:?}", e);
}
},
Err(e) => {
log::error!("{:?}", e);
}
};
} else {
log::info!("配置文件为空");
} }
status_handle.set_service_status(ServiceStatus { status_handle.set_service_status(ServiceStatus {
service_type: crate::windows::SERVICE_TYPE, service_type: crate::windows::SERVICE_TYPE,
@@ -137,6 +75,49 @@ fn service_main() -> windows_service::Result<()> {
}) })
} }
fn start_switch() -> switch::Result<Arc<Switch>> {
if let Some(config) = read_config() {
let device_id = config.device_id;
if device_id.trim().is_empty() {
return Err(switch::error::Error::Stop("MAC address error".to_string()));
}
let server_address = if let Some(server_address) = config.server
.to_socket_addrs()?
.next() {
server_address
} else {
return Err(switch::error::Error::Stop("server address error".to_string()));
};
let mut nat_test_server = config.nat_test_server.iter()
.flat_map(|a| a.to_socket_addrs())
.flatten()
.collect::<Vec<_>>();
;
if nat_test_server.is_empty() {
return Err(switch::error::Error::Stop("nat test server address error".to_string()));
}
let config = Config::new(
config.token,
device_id,
config.name,
server_address,
nat_test_server);
let switch = Switch::start(config)?;
log::info!("switch-service服务启动");
let switch = Arc::new(switch);
let command_server = crate::command::server::CommandServer::new();
let switch1 = switch.clone();
thread::spawn(move || {
if let Err(e) = command_server.start(switch1) {
log::warn!("{:?}", e);
}
});
Ok(switch)
} else {
Err(switch::error::Error::Stop("配置文件为空".to_string()))
}
}
pub fn start() { pub fn start() {
log::info!("以服务的方式启动"); log::info!("以服务的方式启动");
service_dispatcher::start("switch-service", ffi_service_main).unwrap(); service_dispatcher::start("switch-service", ffi_service_main).unwrap();
+8 -5
View File
@@ -7,13 +7,14 @@ edition = "2021"
[dependencies] [dependencies]
packet = { path = "./packet" } packet = { path = "./packet" }
nat_traversal = { path = "./nat_traversal" } nat_traversal = { path = "./p2p_channel" }
bytes = "1.3.0" bytes = "1.3.0"
log = "0.4.17" log = "0.4.17"
libc = "0.2.137" libc = "0.2.137"
dashmap = "5.4.0" dashmap = "5.4.0"
crossbeam = "0.8.2" crossbeam = "0.8.2"
crossbeam-skiplist = "0.1"
parking_lot = "0.12.1" parking_lot = "0.12.1"
rsa = "0.7.2" rsa = "0.7.2"
@@ -22,11 +23,13 @@ sha2 = { version = "0.10.6", features = ["oid"] }
thiserror = "1.0.37" thiserror = "1.0.37"
chrono = "0.4.23" chrono = "0.4.23"
lazy_static = "1.4.0" #lazy_static = "1.4.0"
moka = "0.9.6" #moka = "0.9.6"
protobuf = "3.2.0" protobuf = "3.2.0"
os_info = "3.5.1" local-ip-address = "0.5.2"
tokio = { version = "1.24.1", features = ["full"] }
#mio = {version = "0.8.6",features = ["os-poll", "net"]}
#tokio = { version = "1.24.1", features = ["full"] }
[target.'cfg(any(unix))'.dependencies] [target.'cfg(any(unix))'.dependencies]
tun = { path = "./rust-tun" } tun = { path = "./rust-tun" }
-11
View File
@@ -1,11 +0,0 @@
[package]
name = "nat_traversal"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.24.1", features = ["net"] }
futures = "0.3"
crossbeam-skiplist = "0.1"
-39
View File
@@ -1,39 +0,0 @@
use std::io;
use std::net::SocketAddr;
use tokio::net::UdpSocket;
/// 锥形网络,使用一个端口
pub struct Channel {
udp: UdpSocket,
server_address: SocketAddr,
}
impl Channel {
pub async fn new(server_address: SocketAddr) -> io::Result<Self> {
Ok(Self {
udp: UdpSocket::bind("0:0").await?,
server_address,
})
}
}
impl Channel {
#[inline]
pub async fn recv(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
self.udp.recv_from(buf).await
}
}
impl Channel {
#[inline]
pub async fn send_to(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
self.udp.send_to(buf, addr).await
}
#[inline]
pub async fn send_server(&self, buf: &[u8]) -> io::Result<usize> {
self.udp.send_to(buf, self.server_address).await
}
}
-5
View File
@@ -1,5 +0,0 @@
pub use cone::Channel as ConeChannel;
pub use symmetric::Channel as SymmetricChannel;
mod cone;
mod symmetric;
-86
View File
@@ -1,86 +0,0 @@
use std::io;
use std::net::SocketAddr;
use std::sync::Arc;
use crossbeam_skiplist::SkipMap;
use tokio::net::UdpSocket;
/// 对称网络,绑定多个端口
///
///
/// 假设一方是对称网络,一方是锥形网络
/// 如果对称网络一方绑定n个端口,通过NAT对外映射出n个 公网ip:公网端口,随机尝试k次的情况下
/// 猜中的概率 p = 1-((65535-n)/65535)*((65535-n-1)/(65535-1))*...*((65535-n-k+1)/(65535-k+1))
/// n取76k取600,猜中的概率就超过50%了
///
/// 如果两方都是对称网络则不可取,因为尝试k次需要发送 k*n个包,数据量太大
pub struct Channel {
udp_list: Vec<Arc<UdpSocket>>,
addr_map: SkipMap<SocketAddr, usize>,
server_address: SocketAddr,
}
impl Channel {
pub async fn new(server_address: SocketAddr, num: usize) -> io::Result<Self> {
let mut udp_list = Vec::with_capacity(num);
for _ in 0..num {
udp_list.push(Arc::new(UdpSocket::bind("0:0").await?));
}
Ok(Self {
udp_list,
addr_map: SkipMap::new(),
server_address,
})
}
}
impl Channel {
#[inline]
pub async fn recv(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
let mut list = Vec::with_capacity(self.udp_list.len());
for udp in &self.udp_list {
let udp = udp.clone();
list.push(Box::pin(async move {
udp.readable().await
}));
}
let (rs, index, _) = futures::future::select_all(list.into_iter()).await;
let _ = rs?;
let (len, addr) = self.udp_list[index].try_recv_from(buf)?;
self.addr_map.insert(addr, index);
Ok((len, addr))
}
}
impl Channel {
/// 向一个已经穿透成功洞地址发数据
#[inline]
pub async fn send_to(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
if let Some(entry) = self.addr_map.get(&addr) {
self.udp_list[*entry.value()].send_to(buf, addr).await
} else {
Err(io::Error::from(io::ErrorKind::NotConnected))
}
}
/// 向所有渠道发数据,用于打洞
#[inline]
pub async fn send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> {
for udp in &self.udp_list {
udp.send_to(buf, addr).await?;
}
Ok(())
}
/// 向服务器发送数据
#[inline]
pub async fn send_server(&self, buf: &[u8]) -> io::Result<usize> {
self.udp_list[0].send_to(buf, self.server_address).await
}
}
impl Channel {
pub fn remove_hole(&self, hole: &SocketAddr) {
self.addr_map.remove(hole);
}
}
Submodule switch/p2p_channel added at 4a971a34dd
+6 -5
View File
@@ -1,7 +1,7 @@
syntax = "proto3"; syntax = "proto3";
message RegistrationRequest{ message RegistrationRequest{
string token = 1; string token = 1;
string mac_address = 2; string device_id = 2;
string name = 3; string name = 3;
bool is_fast = 4; bool is_fast = 4;
} }
@@ -26,15 +26,16 @@ message DeviceList{
repeated DeviceInfo device_info_list = 2; repeated DeviceInfo device_info_list = 2;
} }
message Punch{ message PunchInfo{
fixed32 virtual_ip = 1;
repeated fixed32 public_ip_list = 2; repeated fixed32 public_ip_list = 2;
uint32 public_port = 3; uint32 public_port = 3;
uint32 public_port_range = 4; uint32 public_port_range = 4;
NatType nat_type = 5; PunchNatType nat_type = 5;
bool reply = 6; bool reply = 6;
fixed32 local_ip = 7;
uint32 local_port = 8;
} }
enum NatType{ enum PunchNatType{
Symmetric = 0; Symmetric = 0;
Cone = 1; Cone = 1;
} }
+144
View File
@@ -0,0 +1,144 @@
use std::io;
use std::net::{Ipv4Addr, SocketAddr};
use std::sync::Arc;
use crossbeam::atomic::AtomicCell;
use crossbeam_skiplist::SkipMap;
use parking_lot::Mutex;
use nat_traversal::boot::Boot;
use nat_traversal::channel::{Channel, Route, RouteKey};
use nat_traversal::punch::NatInfo;
use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, recv_handler, registration_handler, tun_handler};
use crate::nat::NatTest;
use crate::tun_device;
use crate::tun_device::TunReader;
pub struct Switch {
name: String,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
tun_reader: TunReader,
nat_channel: Channel<Ipv4Addr>,
/// 0. 机器纪元,每一次上线或者下线都会增1,用于感知网络中机器变化
/// 服务端和客户端的不一致,则服务端会推送新的设备列表
/// 1. 网络中的虚拟ip列表
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
nat_test: NatTest,
connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
}
impl Switch {
pub fn start(config: Config) -> crate::Result<Switch> {
let (mut channel, punch, idle) = Boot::new::<Ipv4Addr>(100, 9000, 0)?;
let response = registration_handler::registration(&mut channel, config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone())?;
let register = Arc::new(registration_handler::Register::new(channel.sender()?, config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone()));
let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> = Arc::new(Mutex::new((0, Vec::new())));
let peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>> = Arc::new(SkipMap::new());
let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected));
let virtual_ip = Ipv4Addr::from(response.virtual_ip);
let virtual_gateway = Ipv4Addr::from(response.virtual_gateway);
let virtual_netmask = Ipv4Addr::from(response.virtual_netmask);
let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, config.server_address)));
let local_addr = channel.local_addr()?;
let local_ip = if local_addr.ip().is_unspecified() {
local_ip_address::local_ip().unwrap_or(local_addr.ip())
} else {
local_addr.ip()
};
// NAT检测
let nat_test = NatTest::new(config.nat_test_server.clone(), Ipv4Addr::from(response.public_ip), response.public_port as u16, local_ip, local_addr.port());
// tun通道
let (tun_writer, tun_reader) = tun_device::create_tun(virtual_ip, virtual_netmask, virtual_gateway)?;
// 定时心跳
heartbeat_handler::start_heartbeat(channel.sender()?, device_list.clone(), current_device.clone());
// 空闲检查
heartbeat_handler::start_idle(idle, channel.sender()?);
// 打洞处理
punch_handler::start_cone(punch.try_clone()?, current_device.clone());
punch_handler::start_symmetric(punch, current_device.clone());
punch_handler::start_punch(nat_test.clone(), device_list.clone(), channel.sender()?, current_device.clone());
//tun数据接收处理
for _ in 0..2 {
tun_handler::start(channel.sender()?, tun_reader.clone(), tun_writer.clone(), current_device.clone());
}
//外部数据接收处理
let channel_recv_handler = recv_handler::RecvHandler::new(channel.try_clone()?, current_device.clone(), device_list.clone(), register.clone(),
nat_test.clone(), tun_writer.clone(), connect_status.clone(), peer_nat_info_map.clone());
for _ in 0..2 {
recv_handler::start(channel_recv_handler.try_clone()?);
}
Ok(Switch {
name: config.name,
current_device,
tun_reader,
nat_channel: channel,
nat_test,
device_list,
connect_status,
peer_nat_info_map,
})
}
}
impl Switch {
pub fn name(&self) -> &str {
&self.name
}
pub fn current_device(&self) -> CurrentDeviceInfo {
self.current_device.load()
}
pub fn peer_nat_info(&self, ip: &Ipv4Addr) -> Option<NatInfo> {
self.peer_nat_info_map.get(ip).map(|e| e.value().clone())
}
pub fn connection_status(&self) -> ConnectStatus {
self.connect_status.load()
}
pub fn nat_info(&self) -> NatInfo {
self.nat_test.nat_info()
}
pub fn device_list(&self) -> Vec<PeerDeviceInfo> {
let device_list_lock = self.device_list.lock();
let (_epoch, device_list) = device_list_lock.clone();
drop(device_list_lock);
device_list
}
pub fn route(&self, ip: &Ipv4Addr) -> Option<Route> {
self.nat_channel.route(ip)
}
pub fn route_key(&self, route_key: &RouteKey) -> Option<Ipv4Addr> {
self.nat_channel.route_to_id(route_key)
}
pub fn route_table(&self) -> Vec<(Ipv4Addr, Route)> {
self.nat_channel.route_list()
}
pub fn stop(&self) -> io::Result<()> {
self.tun_reader.close();
self.nat_channel.close()?;
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct Config {
pub token: String,
pub device_id: String,
pub name: String,
pub server_address: SocketAddr,
pub nat_test_server: Vec<SocketAddr>,
}
impl Config {
pub fn new(token: String,
device_id: String,
name: String,
server_address: SocketAddr,
nat_test_server: Vec<SocketAddr>, ) -> Self {
Self {
token,
device_id,
name,
server_address,
nat_test_server,
}
}
}
+2 -2
View File
@@ -7,8 +7,6 @@ use thiserror::Error;
pub enum Error { pub enum Error {
#[error("packet error")] #[error("packet error")]
PacketError(#[from] packet::error::Error), PacketError(#[from] packet::error::Error),
#[error("TokioWatchRecvError")]
TokioWatchRecvError(#[from] tokio::sync::watch::error::RecvError),
#[error("Io error")] #[error("Io error")]
Io(#[from] io::Error), Io(#[from] io::Error),
#[error("Channel error")] #[error("Channel error")]
@@ -21,6 +19,8 @@ pub enum Error {
NotSupport, NotSupport,
#[error("Stop")] #[error("Stop")]
Stop(String), Stop(String),
#[error("Warn")]
Warn(String),
} }
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
+78 -54
View File
@@ -1,80 +1,104 @@
use std::net::{SocketAddr, UdpSocket}; use std::{io, thread};
use std::net::Ipv4Addr;
use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use chrono::Local; use chrono::Local;
use tokio::sync::watch::Receiver; use crossbeam::atomic::AtomicCell;
use tokio::time::sleep; use parking_lot::Mutex;
use rand::prelude::SliceRandom;
use nat_traversal::channel::Route;
use crate::error::*; use nat_traversal::channel::sender::Sender;
use crate::handle::{ApplicationStatus, DIRECT_ROUTE_TABLE}; use nat_traversal::idle::Idle;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, Version};
use crate::protocol::control_packet::PingPacket; use crate::protocol::control_packet::PingPacket;
use crate::protocol::{control_packet, NetPacket, Protocol, Version};
use crate::{CurrentDeviceInfo, DEVICE_LIST};
pub async fn start<F>( pub fn start_idle(idle: Idle<Ipv4Addr>, sender: Sender<Ipv4Addr>) {
status_watch: Receiver<ApplicationStatus>, thread::spawn(move || {
udp: UdpSocket, if let Err(e) = start_idle_(idle, sender) {
cur_info: CurrentDeviceInfo, log::info!("空闲检测线程停止:{:?}",e);
stop_fn: F,
) where
F: FnOnce() + Send + 'static,
{
tokio::spawn(async move {
match handle_loop(status_watch, udp, cur_info.connect_server).await {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
} }
stop_fn();
}); });
} }
async fn handle_loop( fn start_idle_(idle: Idle<Ipv4Addr>, sender: Sender<Ipv4Addr>) -> io::Result<()> {
mut status_watch: Receiver<ApplicationStatus>, loop {
udp: UdpSocket, let (idle_status, peer_ip, route) = idle.next_idle()?;
server_addr: SocketAddr, log::warn!("peer_ip:{:?},route:{:?},idle_status:{:?}",peer_ip,route,idle_status);
) -> Result<()> { sender.remove_route(&peer_ip);
const INTERVAL: u64 = 3000; }
const MAX_INTERVAL: i64 = 3000 * 3; }
let mut buf = [0u8; (4 + 8 + 4)];
let mut net_packet = NetPacket::new(&mut buf)?; pub fn start_heartbeat(sender: Sender<Ipv4Addr>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
thread::spawn(move || {
if let Err(e) = start_heartbeat_(sender, device_list, current_device) {
log::info!("空闲检测线程停止:{:?}",e);
}
});
}
fn start_heartbeat_(sender: Sender<Ipv4Addr>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<()> {
let mut net_packet = NetPacket::new([0u8; 16])?;
net_packet.set_version(Version::V1); net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Control); net_packet.set_protocol(Protocol::Control);
net_packet.set_transport_protocol(control_packet::Protocol::Ping.into()); net_packet.set_transport_protocol(control_packet::Protocol::Ping.into());
net_packet.set_ttl(255); net_packet.first_set_ttl(MAX_TTL);
let mut count = 0;
loop { loop {
let current_time = Local::now().timestamp_millis(); let current_device = current_device.load();
net_packet.set_source(current_device.virtual_ip());
{ {
let current_time = Local::now().timestamp_millis() as u16;
let mut ping = PingPacket::new(net_packet.payload_mut())?; let mut ping = PingPacket::new(net_packet.payload_mut())?;
ping.set_time(current_time); ping.set_time(current_time);
let epoch = { DEVICE_LIST.lock().0 }; let epoch = { device_list.lock().0 };
ping.set_epoch(epoch); ping.set_epoch(epoch);
} }
let _ = udp.send_to(net_packet.buffer(), server_addr); if count % 7 == 0 {
// 不clone会死锁? let mut route_list: Option<Vec<(Ipv4Addr, Route)>> = None;
for x in DIRECT_ROUTE_TABLE.clone().iter() { let peer_list = device_list.lock().1.clone();
let virtual_ip = x.key().clone(); for peer in peer_list {
let route = x.value().clone(); net_packet.first_set_ttl(MAX_TTL);
drop(x); net_packet.set_destination(peer.virtual_ip);
if current_time - route.recv_time <= MAX_INTERVAL { if sender.send_to_id(net_packet.buffer(), &peer.virtual_ip).is_err() {
let _ = udp.send_to(net_packet.buffer(), route.address); //没有路由则发送到网关
} else { let _ = sender.send_to_addr(net_packet.buffer(), current_device.connect_server);
DIRECT_ROUTE_TABLE.remove_if(&virtual_ip, |_, route| { //再随机发送到其他地址,看有没有客户端符合转发条件
current_time - route.recv_time > MAX_INTERVAL let route_list = route_list.get_or_insert_with(|| {
}); let mut l = sender.route_list();
l.shuffle(&mut rand::thread_rng());
l
});
let mut num = 0;
net_packet.first_set_ttl(2);
for (peer_ip, route) in route_list.iter() {
if peer_ip != &peer.virtual_ip && route.metric == 1 {
let _ = sender.send_to_route(net_packet.buffer(), &route.route_key());
num += 1;
}
if num >= 3 {
break;
}
}
}
} }
} net_packet.set_destination(current_device.virtual_gateway());
tokio::select! { if let Err(e) = sender.send_to_addr(net_packet.buffer(), current_device.connect_server) {
_ = sleep(Duration::from_millis(INTERVAL))=>{ log::warn!("connect_server:{:?},e:{:?}",current_device.connect_server,e);
} }
status = status_watch.changed() =>{ } else {
status?; for (peer_ip, route) in sender.route_list().iter() {
if *status_watch.borrow() != ApplicationStatus::Starting{ net_packet.set_destination(*peer_ip);
return Ok(()) if let Err(e) = sender.send_to_route(net_packet.buffer(), &route.route_key()) {
log::warn!("peer_ip:{:?},route:{:?},e:{:?}",peer_ip,route,e);
} }
} }
} }
count += 1;
thread::sleep(Duration::from_secs(5));
} }
} }
+19 -131
View File
@@ -1,38 +1,17 @@
use std::net::{Ipv4Addr, SocketAddr}; use std::net::{Ipv4Addr, SocketAddr};
use std::sync::atomic::AtomicI64;
use std::time::Duration;
use chrono::Local;
use dashmap::DashMap;
use lazy_static::lazy_static;
use moka::sync::Cache;
use parking_lot::{const_mutex, Mutex};
use crate::proto::message::NatType;
pub mod heartbeat_handler; pub mod heartbeat_handler;
pub mod punch_handler; pub mod punch_handler;
pub mod registration_handler; pub mod registration_handler;
pub mod tun_handler; pub mod tun_handler;
pub mod udp_recv_handler; pub mod recv_handler;
lazy_static! {
/// 0. 机器纪元,每一次上线或者下线都会增1,由服务端维护,用于感知网络中机器变化 /// 是否在一个网段
/// 服务端和客户端的不一致,则服务端会推送新的设备列表 fn check_dest(dest: Ipv4Addr, virtual_netmask: Ipv4Addr, virtual_network: Ipv4Addr) -> bool {
/// 1. 网络中的虚拟ip列表 u32::from_be_bytes(dest.octets()) & u32::from_be_bytes(virtual_netmask.octets())
pub static ref DEVICE_LIST:Mutex<(u32,Vec<PeerDeviceInfo>)> = const_mutex((0,Vec::new())); == u32::from_be_bytes(virtual_network.octets())
/// 服务器延迟
pub static ref SERVER_RT:AtomicI64 = AtomicI64::new(-1);
/// id
pub static ref ID:AtomicI64 = AtomicI64::new(0);
/// 直连路由表
pub static ref DIRECT_ROUTE_TABLE:DashMap<Ipv4Addr,Route> = DashMap::new();
/// 地址映射
pub static ref ADDR_TABLE:Cache<SocketAddr,Ipv4Addr> = Cache::builder()
.time_to_idle(Duration::from_secs(60*5)).build();
/// 当前设备的nat信息
pub static ref NAT_INFO:Mutex<Option<NatInfo>> = const_mutex(None);
static ref NAT_TEST_ADDRESS:Mutex<Vec<SocketAddr>> = const_mutex(Vec::new());
} }
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct PeerDeviceInfo { pub struct PeerDeviceInfo {
pub virtual_ip: Ipv4Addr, pub virtual_ip: Ipv4Addr,
@@ -74,82 +53,15 @@ impl From<u8> for PeerDeviceStatus {
} }
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ApplicationStatus {
Starting,
Stopping,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ConnectStatus { pub enum ConnectStatus {
Connecting, Connecting,
Connected, Connected,
} }
impl Into<u8> for ConnectStatus { #[derive(Copy, Clone, Debug, Eq, PartialEq)]
fn into(self) -> u8 {
match self {
ConnectStatus::Connecting => 0,
ConnectStatus::Connected => 1,
}
}
}
#[derive(Clone, Debug)]
pub struct NatInfo {
pub public_ips: Vec<u32>,
pub public_port: u16,
pub public_port_range: u16,
pub nat_type: NatType,
}
impl NatInfo {
pub fn new(
public_ips: Vec<u32>,
public_port: u16,
public_port_range: u16,
nat_type: NatType,
) -> Self {
Self {
public_ips,
public_port,
public_port_range,
nat_type,
}
}
}
pub fn init_nat_test_addr(addrs: Vec<SocketAddr>) {
NAT_TEST_ADDRESS.lock().extend_from_slice(&addrs);
}
/// 初始化nat信息
pub fn init_nat_info(public_ip: u32, public_port: u16) {
let addrs = NAT_TEST_ADDRESS.lock().clone();
match crate::nat::check::public_ip_list(&addrs) {
Ok((nat_type, ips, port_range)) => {
let mut public_ips = Vec::new();
public_ips.push(public_ip);
for ip in ips {
let ip = u32::from_be_bytes(ip.octets());
if ip != public_ip {
public_ips.push(ip);
}
}
let nat_info = NatInfo::new(public_ips, public_port, port_range, nat_type);
// println!("nat信息:{:?}",nat_info);
let mut nat_info_lock = NAT_INFO.lock();
nat_info_lock.replace(nat_info);
}
Err(e) => {
println!("获取nat数据失败,将无法进行udp打洞:{:?}", e);
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct CurrentDeviceInfo { pub struct CurrentDeviceInfo {
pub virtual_ip: Ipv4Addr, virtual_ip: Ipv4Addr,
pub virtual_gateway: Ipv4Addr, pub virtual_gateway: Ipv4Addr,
pub virtual_netmask: Ipv4Addr, pub virtual_netmask: Ipv4Addr,
//网络地址 //网络地址
@@ -182,40 +94,16 @@ impl CurrentDeviceInfo {
connect_server, connect_server,
} }
} }
} #[inline]
pub fn virtual_ip(&self) -> Ipv4Addr {
#[derive(Clone, Debug)] self.virtual_ip
pub struct Route { }
pub route_type: RouteType, #[inline]
pub address: SocketAddr, pub fn virtual_gateway(&self) -> Ipv4Addr {
//用心跳探测延迟,收包时更新 self.virtual_gateway
pub rt: i64,
//收包时更新,如果太久没有收到消息则剔除
pub recv_time: i64,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum RouteType {
ServerRelay,
P2P,
}
impl Into<u8> for RouteType {
fn into(self) -> u8 {
match self {
RouteType::ServerRelay => 0,
RouteType::P2P => 1,
}
} }
} }
impl Route {
pub fn new(address: SocketAddr) -> Self {
Self {
route_type: RouteType::P2P,
address,
rt: -1,
recv_time: Local::now().timestamp_millis(),
}
}
}
+112 -374
View File
@@ -1,402 +1,140 @@
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
use std::time::Duration;
use std::{io, thread}; use std::{io, thread};
use std::net::{IpAddr, Ipv4Addr};
use std::sync::Arc;
use std::time::Duration;
use crossbeam::atomic::AtomicCell;
use parking_lot::Mutex;
use protobuf::Message; use protobuf::Message;
use rand::prelude::SliceRandom; use rand::prelude::SliceRandom;
use tokio::sync::mpsc::error::TrySendError; use nat_traversal::channel::sender::Sender;
use tokio::sync::mpsc::{Receiver, Sender}; use nat_traversal::punch::{NatInfo, NatType, Punch};
use tokio::sync::watch; use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
use crate::nat::NatTest;
use crate::proto::message::{PunchInfo, PunchNatType};
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, turn_packet, Version};
use crate::error::*; pub fn start_cone(punch: Punch<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
use crate::handle::{ApplicationStatus, DIRECT_ROUTE_TABLE}; thread::spawn(move || {
use crate::proto::message::{NatType, Punch}; if let Err(e) = start_(true, punch, current_device) {
use crate::protocol::control_packet::PunchRequestPacket; log::warn!("锥形网络打洞处理线程停止 {:?}",e);
use crate::protocol::turn_packet::TurnPacket;
use crate::protocol::{control_packet, turn_packet, NetPacket, Protocol, Version};
use crate::{handle::NatInfo, handle::NAT_INFO, CurrentDeviceInfo, DEVICE_LIST};
/// 每一种类型一个通道,减少相互干扰
pub fn bounded() -> (
PunchSender,
ConeReceiver,
ReqSymmetricReceiver,
ResSymmetricReceiver,
) {
let (cone_sender, cone_receiver) = tokio::sync::mpsc::channel(3);
let (req_symmetric_sender, req_symmetric_receiver) = tokio::sync::mpsc::channel(1);
let (res_symmetric_sender, res_symmetric_receiver) = tokio::sync::mpsc::channel(1);
(
PunchSender::new(cone_sender, req_symmetric_sender, res_symmetric_sender),
ConeReceiver(cone_receiver),
ReqSymmetricReceiver(req_symmetric_receiver),
ResSymmetricReceiver(res_symmetric_receiver),
)
}
pub struct ConeReceiver(Receiver<Punch>);
pub struct ReqSymmetricReceiver(Receiver<Punch>);
pub struct ResSymmetricReceiver(Receiver<Punch>);
#[derive(Clone)]
pub struct PunchSender {
cone_sender: Sender<Punch>,
req_symmetric_sender: Sender<Punch>,
res_symmetric_sender: Sender<Punch>,
}
impl PunchSender {
pub fn new(
cone_sender: Sender<Punch>,
req_symmetric_sender: Sender<Punch>,
res_symmetric_sender: Sender<Punch>,
) -> Self {
Self {
cone_sender,
req_symmetric_sender,
res_symmetric_sender,
} }
} });
// pub fn send(&self, punch: Punch) -> std::result::Result<(), SendError<Punch>> { }
// match punch.nat_type.enum_value_or_default() {
// NatType::Symmetric => { pub fn start_symmetric(punch: Punch<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
// if punch.reply { thread::spawn(move || {
// // 为true表示回应,也就是主动发起的打洞操作 if let Err(e) = start_(false, punch, current_device) {
// self.res_symmetric_sender.blocking_send(punch) log::warn!("对称网络打洞处理线程停止 {:?}",e);
// } else { }
// self.req_symmetric_sender.blocking_send(punch) });
// } }
// }
// NatType::Cone => { fn start_(is_cone: bool, mut punch: Punch<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<()> {
// self.cone_sender.blocking_send(punch) let mut packet = NetPacket::new([0u8; 12])?;
// } packet.set_version(Version::V1);
// } packet.first_set_ttl(1);
// } packet.set_protocol(Protocol::Control);
pub fn try_send(&self, punch: Punch) -> std::result::Result<(), TrySendError<Punch>> { packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
match punch.nat_type.enum_value_or_default() { loop {
NatType::Symmetric => { let (peer_ip, nat_info) = if is_cone {
if punch.reply { punch.next_cone(None)?
// 为true表示回应,也就是主动发起的打洞操作 } else {
self.res_symmetric_sender.try_send(punch) punch.next_symmetric(None)?
} else { };
self.req_symmetric_sender.try_send(punch) if let Some(route) = punch.sender().route(&peer_ip) {
} if route.metric == 1 {
//直连地址不需要打洞
continue;
} }
NatType::Cone => self.cone_sender.try_send(punch), }
packet.set_source(current_device.load().virtual_ip());
packet.set_destination(peer_ip);
log::info!("发起打洞,目标:{:?},{:?}",peer_ip,nat_info);
if let Err(e) = punch.punch(packet.buffer(), peer_ip, nat_info) {
log::warn!("peer_ip:{:?},e:{:?}",peer_ip,e);
} }
} }
} }
fn handle( pub fn start_punch(nat_test: NatTest, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, sender: Sender<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
_status_watch: &watch::Receiver<ApplicationStatus>, thread::spawn(move || {
udp: &UdpSocket, if let Err(e) = start_punch_(nat_test, device_list, sender, current_device) {
punch_list: Vec<Punch>, log::warn!("对称网络打洞处理线程停止 {:?}",e);
buf: &[u8],
) -> Result<()> {
let mut counter = 0u64;
for punch in punch_list {
let dest = Ipv4Addr::from(punch.virtual_ip);
if DIRECT_ROUTE_TABLE.contains_key(&dest) {
continue;
} }
// println!("punch {:?}", punch); });
match punch.nat_type.enum_value_or_default() { }
NatType::Symmetric => {
// 假设绑定n个端口,通过NAT对外映射出n个 公网ip:公网端口,随机尝试k次的情况下 fn start_punch_(nat_test: NatTest, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, sender: Sender<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> crate::Result<()> {
// 猜中的概率 p = 1-((65535-n)/65535)*((65535-n-1)/(65535-1))*...*((65535-n-k+1)/(65535-k+1)) loop {
// n取76,k取600,猜中的概率就超过50%了 if sender.is_close() {
// 前提 自己是锥形网络,否则猜中了也通信不了 return Ok(());
let mut send_f = |min_port: u16, max_port: u16, k: usize| -> io::Result<()> { }
let mut nums: Vec<u16> = (min_port..max_port).collect(); let current_device = current_device.load();
nums.push(max_port); let nat_info = nat_test.nat_info();
let mut rng = rand::thread_rng(); {
nums.shuffle(&mut rng); let mut list = device_list.lock().clone().1;
for pub_ip in &punch.public_ip_list { list.shuffle(&mut rand::thread_rng());
let pub_ip = Ipv4Addr::from(*pub_ip); let mut count = 0;
for port in &nums[..k] { for info in list {
udp.send_to(buf, SocketAddr::V4(SocketAddrV4::new(pub_ip, *port)))?; if info.virtual_ip <= current_device.virtual_ip {
select_sleep(&mut counter); continue;
}
}
Ok(())
};
if punch.public_port_range < 600 {
//端口变化不大时,在预测的范围内随机发送
let min_port = if punch.public_port > punch.public_port_range {
punch.public_port - punch.public_port_range
} else {
1
};
let max_port = if punch.public_port + punch.public_port_range > 65535 {
65535
} else {
punch.public_port + punch.public_port_range
};
let k = if max_port - min_port + 1 > 60 {
60
} else {
max_port - min_port + 1
};
send_f(min_port as u16, max_port as u16, k as usize)?;
} }
// 全端口范围,随机取600个端口发送 if let Some(route) = sender.route(&info.virtual_ip) {
send_f(1, 65535, 600)?; if route.metric == 1 {
//直连地址不需要打洞
continue;
}
}
count += 1;
if count > 3 {
break;
}
let buf = punch_packet(current_device.virtual_ip(), &nat_info, info.virtual_ip)?;
sender.send_to_addr(&buf, current_device.connect_server)?;
}
}
match nat_info.nat_type {
NatType::Symmetric => {
thread::sleep(Duration::from_secs(28));
} }
NatType::Cone => { NatType::Cone => {
for pub_ip in punch.public_ip_list { thread::sleep(Duration::from_secs(20));
udp.send_to(
buf,
SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::from(pub_ip),
punch.public_port as u16,
)),
)?;
select_sleep(&mut counter);
}
}
}
}
Ok(())
}
/// 给对称nat发送打洞数据包
pub async fn req_symmetric_handler_start<F>(
status_watch: watch::Receiver<ApplicationStatus>,
receiver: ReqSymmetricReceiver,
udp: UdpSocket,
cur_info: CurrentDeviceInfo,
stop_fn: F,
) where
F: FnOnce() + Send + 'static,
{
let receiver = receiver.0;
tokio::spawn(async move {
match handle_loop(status_watch, receiver, udp, cur_info).await {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
stop_fn()
});
}
// pub fn req_symmetric_handle_loop(
// receiver: ReqSymmetricReceiver,
// udp: UdpSocket,
// cur_info: CurrentDeviceInfo,
// ) -> Result<()> {
// let receiver = receiver.0;
// handle_loop(receiver, udp, cur_info)
// }
/// 给对称nat发送打洞数据包,处理主动发起的打洞操作
pub async fn res_symmetric_handler_start<F>(
status_watch: watch::Receiver<ApplicationStatus>,
receiver: ResSymmetricReceiver,
udp: UdpSocket,
cur_info: CurrentDeviceInfo,
stop_fn: F,
) where
F: FnOnce() + Send + 'static,
{
let receiver = receiver.0;
tokio::spawn(async move {
match res_symmetric_handle_loop(status_watch, receiver, udp, cur_info).await {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
stop_fn()
});
}
async fn res_symmetric_handle_loop(
mut status_watch: watch::Receiver<ApplicationStatus>,
mut receiver: Receiver<Punch>,
udp: UdpSocket,
cur_info: CurrentDeviceInfo,
) -> Result<()> {
let mut buf = [0u8; 12];
let mut packet = NetPacket::new(&mut buf)?;
packet.set_version(Version::V1);
packet.set_ttl(255);
packet.set_protocol(Protocol::Control);
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
{
let mut punch_packet = PunchRequestPacket::new(packet.payload_mut())?;
punch_packet.set_source(cur_info.virtual_ip);
}
loop {
tokio::select! {
rs = tokio::time::timeout(Duration::from_secs(20), receiver.recv()) =>{
match rs {
Ok(punch) => {
if let Some(punch) = punch{
let mut list = Vec::new();
list.push(punch);
loop {
match receiver.try_recv() {
Ok(punch) => {
list.push(punch);
}
Err(_) => {
break;
}
}
}
if let Err(e) = handle(&status_watch,&udp, list, packet.buffer()) {
log::warn!("{:?}",e)
}
}else {
return Err(Error::Stop("打洞线程通道关闭".to_string()));
}
}
Err(_) => {
punch_request_handle(&udp, &cur_info)?;
}
}
}
status = status_watch.changed() =>{
status?;
if *status_watch.borrow() != ApplicationStatus::Starting{
return Ok(())
}
} }
} }
} }
} }
/// 给锥形nat发送打洞数据包 pub fn punch_packet(virtual_ip: Ipv4Addr, nat_info: &NatInfo, dest: Ipv4Addr) -> crate::Result<Vec<u8>> {
pub async fn cone_handler_start<F>( let mut punch_reply = PunchInfo::new();
status_watch: watch::Receiver<ApplicationStatus>,
receiver: ConeReceiver,
udp: UdpSocket,
cur_info: CurrentDeviceInfo,
stop_fn: F,
) where
F: FnOnce() + Send + 'static,
{
let receiver = receiver.0;
tokio::spawn(async move {
match handle_loop(status_watch, receiver, udp, cur_info).await {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
stop_fn();
});
}
async fn handle_loop(
mut status_watch: watch::Receiver<ApplicationStatus>,
mut receiver: Receiver<Punch>,
udp: UdpSocket,
cur_info: CurrentDeviceInfo,
) -> Result<()> {
let mut buf = [0u8; 12];
let mut packet = NetPacket::new(&mut buf)?;
packet.set_version(Version::V1);
packet.set_ttl(255);
packet.set_protocol(Protocol::Control);
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
{
let mut punch_packet = PunchRequestPacket::new(packet.payload_mut())?;
punch_packet.set_source(cur_info.virtual_ip);
}
loop {
tokio::select! {
punch = receiver.recv() =>{
if let Some(punch) = punch{
let mut list = Vec::new();
list.push(punch);
loop {
match receiver.try_recv() {
Ok(punch) => {
list.push(punch);
}
Err(_) => {
break;
}
}
}
if let Err(e) = handle(&status_watch,&udp, list, packet.buffer()) {
log::warn!("{:?}",e)
}
}else {
return Err(Error::Stop("打洞线程通道关闭".to_string()));
}
}
status = status_watch.changed() =>{
status?;
if *status_watch.borrow() != ApplicationStatus::Starting{
return Ok(())
}
}
}
}
}
fn select_sleep(counter: &mut u64) {
*counter += 1;
if *counter & 10 == 10 {
thread::sleep(Duration::from_millis(2));
} else {
thread::sleep(Duration::from_millis(1));
}
}
fn punch_request_handle(udp: &UdpSocket, cur_info: &CurrentDeviceInfo) -> Result<()> {
let nat_info_lock = NAT_INFO.lock();
let nat_info = nat_info_lock.clone();
drop(nat_info_lock);
if let Some(nat_info) = nat_info {
if let Err(e) = send_punch(&udp, &cur_info, nat_info) {
log::warn!("发送打洞数据失败 {:?}", e)
}
Ok(())
} else {
Err(Error::Stop("未初始化nat信息".to_string()))
}
}
fn send_punch(udp: &UdpSocket, cur_info: &CurrentDeviceInfo, nat_info: NatInfo) -> Result<()> {
let lock = DEVICE_LIST.lock();
let list = lock.1.clone();
drop(lock);
for peer_info in list {
let ip = peer_info.virtual_ip;
//只向ip比自己大的发起打洞,避免双方同时发起打洞浪费流量
if ip > cur_info.virtual_ip && !DIRECT_ROUTE_TABLE.contains_key(&ip) {
log::info!("发起打洞 {:?}, peer_info:{:?}", nat_info, peer_info);
let bytes = punch_packet(cur_info.virtual_ip, nat_info.clone(), ip)?;
udp.send_to(&bytes, cur_info.connect_server)?;
}
}
Ok(())
}
fn punch_packet(virtual_ip: Ipv4Addr, nat_info: NatInfo, dest: Ipv4Addr) -> Result<Vec<u8>> {
let mut punch_reply = Punch::new();
punch_reply.reply = false; punch_reply.reply = false;
punch_reply.virtual_ip = u32::from_be_bytes(virtual_ip.octets()); punch_reply.public_ip_list = nat_info.public_ips.iter().map(|i| {
punch_reply.public_ip_list = nat_info.public_ips; match i {
IpAddr::V4(ip) => {
u32::from_be_bytes(ip.octets())
}
IpAddr::V6(_) => {
panic!()
}
}
}).collect();
punch_reply.public_port = nat_info.public_port as u32; punch_reply.public_port = nat_info.public_port as u32;
punch_reply.public_port_range = nat_info.public_port_range as u32; punch_reply.public_port_range = nat_info.public_port_range as u32;
punch_reply.nat_type = protobuf::EnumOrUnknown::new(nat_info.nat_type); punch_reply.local_ip = match nat_info.local_ip {
IpAddr::V4(ip) => u32::from_be_bytes(ip.octets()),
IpAddr::V6(_) => {
panic!()
}
};
punch_reply.local_port = nat_info.local_port as u32;
punch_reply.nat_type = protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type));
let bytes = punch_reply.write_to_bytes()?; let bytes = punch_reply.write_to_bytes()?;
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + bytes.len()])?; let mut net_packet = NetPacket::new(vec![0u8; 12 + bytes.len()])?;
net_packet.set_version(Version::V1); net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::OtherTurn); net_packet.set_protocol(Protocol::OtherTurn);
net_packet.set_transport_protocol(turn_packet::Protocol::Punch.into()); net_packet.set_transport_protocol(turn_packet::Protocol::Punch.into());
net_packet.set_ttl(255); net_packet.first_set_ttl(MAX_TTL);
let mut turn_packet = TurnPacket::new(net_packet.payload_mut())?; net_packet.set_source(virtual_ip);
turn_packet.set_source(virtual_ip); net_packet.set_destination(dest);
turn_packet.set_destination(dest); net_packet.set_payload(&bytes);
turn_packet.set_payload(&bytes);
Ok(net_packet.into_buffer()) Ok(net_packet.into_buffer())
} }
+385
View File
@@ -0,0 +1,385 @@
use std::{io, thread};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::Arc;
use chrono::Local;
use crossbeam::atomic::AtomicCell;
use crossbeam_skiplist::SkipMap;
use parking_lot::Mutex;
use protobuf::Message;
use nat_traversal::channel::{Channel, Route, RouteKey};
use nat_traversal::punch::NatInfo;
use packet::icmp::{icmp, Kind};
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::error::Error;
use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo};
use crate::handle::registration_handler::Register;
use crate::nat::NatTest;
use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse};
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, service_packet, turn_packet, Version};
use crate::protocol::control_packet::ControlPacket;
use crate::protocol::error_packet::InErrorPacket;
use crate::tun_device::TunWriter;
pub fn start(mut handler: RecvHandler) {
thread::spawn(move || {
let mut buf = [0; 4096];
loop {
match handler.channel.recv_from(&mut buf, None) {
Ok((len, route)) => {
if let Err(e) = handler.handle(&mut buf[..len], &route) {
log::warn!("数据处理失败:{:?},e:{:?}",route,e);
if let Error::Stop(_) = e {
let _ = handler.channel.close();
break;
}
}
}
Err(e) => {
log::warn!("{:?}",e);
// 检查关闭状态
if handler.channel.is_close() {
break;
}
}
}
}
});
}
pub struct RecvHandler {
channel: Channel<Ipv4Addr>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
register: Arc<Register>,
nat_test: NatTest,
tun_writer: TunWriter,
connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
}
impl RecvHandler {
pub fn new(channel: Channel<Ipv4Addr>,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
register: Arc<Register>,
nat_test: NatTest,
tun_writer: TunWriter,
connect_status: Arc<AtomicCell<ConnectStatus>>,
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
) -> Self {
Self {
channel,
current_device,
device_list,
register,
nat_test,
tun_writer,
connect_status,
peer_nat_info_map,
}
}
pub fn try_clone(&self) -> io::Result<Self> {
Ok(Self {
channel: self.channel.try_clone()?,
current_device: self.current_device.clone(),
device_list: self.device_list.clone(),
register: self.register.clone(),
nat_test: self.nat_test.clone(),
tun_writer: self.tun_writer.clone(),
connect_status: self.connect_status.clone(),
peer_nat_info_map: self.peer_nat_info_map.clone(),
})
}
}
impl RecvHandler {
fn handle(&self, buf: &mut [u8], route_key: &RouteKey) -> crate::Result<()> {
let mut net_packet = NetPacket::new(buf)?;
if net_packet.ttl() == 0 {
return Ok(());
}
let source = net_packet.source();
let current_device = self.current_device.load();
if source == current_device.virtual_ip() {
return Ok(());
}
let destination = net_packet.destination();
if current_device.virtual_ip() != destination && self.connect_status.load() == ConnectStatus::Connected {
if !check_dest(source, current_device.virtual_netmask, current_device.virtual_network) {
log::warn!("转发数据,源地址错误:{:?},当前网络:{:?},route_key:{:?}",source,current_device.virtual_network,route_key);
return Ok(());
}
if !check_dest(destination, current_device.virtual_netmask, current_device.virtual_network) {
log::warn!("转发数据,目的地址错误:{:?},当前网络:{:?},route_key:{:?}",destination,current_device.virtual_network,route_key);
return Ok(());
}
let ttl = net_packet.ttl();
if ttl > 1 {
// 转发
net_packet.set_ttl(ttl - 1);
if let Some(route) = self.channel.route(&destination) {
if route.metric <= net_packet.ttl() {
self.channel.send_to_route(net_packet.buffer(), &route.route_key())?;
}
} else if (ttl > 2 || destination == current_device.virtual_gateway())
&& source != current_device.virtual_gateway() {
//网关默认要转发一次,生存时间不够的发到网关也会被丢弃
self.channel.send_to_addr(net_packet.buffer(), current_device.connect_server)?;
}
}
return Ok(());
}
match net_packet.protocol() {
Protocol::Ipv4Turn => {
let mut ipv4 = IpV4Packet::new(net_packet.payload_mut())?;
if ipv4.protocol() == ipv4::protocol::Protocol::Icmp {
let mut icmp_packet = icmp::IcmpPacket::new(ipv4.payload_mut())?;
if icmp_packet.kind() == Kind::EchoRequest {
//开启ping
icmp_packet.set_kind(Kind::EchoReply);
icmp_packet.update_checksum();
ipv4.set_source_ip(destination);
ipv4.set_destination_ip(source);
ipv4.update_checksum();
net_packet.set_source(destination);
net_packet.set_destination(source);
self.channel.send_to_route(net_packet.buffer(), route_key)?;
return Ok(());
}
}
self.tun_writer.write(net_packet.payload())?;
}
Protocol::Service => {
self.service(current_device, source, net_packet, route_key)?;
}
Protocol::Error => {
self.error(current_device, source, net_packet, route_key)?;
}
Protocol::Control => {
self.control(current_device, source, net_packet, route_key)?;
}
Protocol::OtherTurn => {
self.other_turn(current_device, source, net_packet, route_key)?;
}
Protocol::UnKnow(e) => {
log::info!("不支持的协议:{}",e);
}
}
Ok(())
}
fn service(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
if route_key.addr != current_device.connect_server || source != current_device.virtual_gateway() {
return Ok(());
}
match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::RegistrationRequest => {}
service_packet::Protocol::RegistrationResponse => {
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?;
let local_addr = self.channel.local_addr()?;
let local_ip = if local_addr.ip().is_unspecified() {
local_ip_address::local_ip().unwrap_or(local_addr.ip())
} else {
local_addr.ip()
};
let nat_info = self.nat_test.re_test(Ipv4Addr::from(response.public_ip), response.public_port as u16, local_ip, local_addr.port());
self.channel.set_nat_type(nat_info.nat_type)?;
let new_ip = Ipv4Addr::from(response.virtual_ip);
let current_ip = current_device.virtual_ip();
if current_ip != new_ip {
// ip发生变化
log::info!("ip发生变化,old_ip:{:?},new_ip:{:?}",current_ip,new_ip);
let old_netmask = current_device.virtual_netmask;
let old_gateway = current_device.virtual_gateway();
let virtual_ip = Ipv4Addr::from(response.virtual_ip);
let virtual_gateway = Ipv4Addr::from(response.virtual_gateway);
let virtual_netmask = Ipv4Addr::from(response.virtual_netmask);
self.tun_writer.change_ip(virtual_ip, virtual_netmask, virtual_gateway, old_netmask, old_gateway)?;
let new_current_device = CurrentDeviceInfo::new(virtual_ip, virtual_gateway,
virtual_netmask, current_device.connect_server);
if let Err(e) = self.current_device.compare_exchange(current_device, new_current_device) {
log::warn!("替换失败:{:?}",e);
}
}
self.connect_status.store(ConnectStatus::Connected);
}
service_packet::Protocol::PollDeviceList => {}
service_packet::Protocol::PushDeviceList => {
let device_list_t = DeviceList::parse_from_bytes(net_packet.payload())?;
let ip_list = device_list_t
.device_info_list
.into_iter()
.map(|info| {
PeerDeviceInfo::new(
Ipv4Addr::from(info.virtual_ip),
info.name,
info.device_status as u8,
)
})
.collect();
let mut dev = self.device_list.lock();
if dev.0 < device_list_t.epoch as u16 || device_list_t.epoch as u16 - dev.0 > u16::MAX >> 2 {
dev.0 = device_list_t.epoch as u16;
dev.1 = ip_list;
}
}
service_packet::Protocol::UnKnow(u) => {
log::warn!("未知服务协议:{}",u);
}
}
Ok(())
}
fn error(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
if route_key.addr != current_device.connect_server || source != current_device.virtual_gateway() {
return Ok(());
}
match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
InErrorPacket::TokenError => {
return Err(Error::Stop("Token error".to_string()));
}
InErrorPacket::Disconnect => {
self.connect_status.store(ConnectStatus::Connecting);
self.register.fast_register()?;
}
InErrorPacket::AddressExhausted => {
//地址用尽
return Err(Error::Stop("IP address has been exhausted".to_string()));
}
InErrorPacket::OtherError(e) => {
log::error!("OtherError {:?}", e.message());
}
}
Ok(())
}
fn control(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, mut net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
ControlPacket::PingPacket(_) => {
net_packet.set_transport_protocol(control_packet::Protocol::Pong.into());
net_packet.set_source(current_device.virtual_ip());
net_packet.set_destination(source);
net_packet.first_set_ttl(MAX_TTL);
self.channel.send_to_route(net_packet.buffer(), route_key)?;
}
ControlPacket::PongPacket(pong_packet) => {
let current_time = Local::now().timestamp_millis() as u16;
if current_time < pong_packet.time() {
return Ok(());
}
let rt = (current_time - pong_packet.time()) as i64;
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
if let Some(current_route) = self.channel.route(&source) {
if &current_route.route_key() == route_key {
self.channel.update_route(&source, metric, rt);
} else if current_route.metric >= metric && current_route.rt > rt {
let route = Route::from(*route_key, metric, rt);
self.channel.add_route(source, route);
}
} else {
let route = Route::from(*route_key, metric, rt);
self.channel.add_route(source, route);
}
if route_key.addr == current_device.connect_server && source == current_device.virtual_gateway() {
let epoch = self.device_list.lock().0;
if pong_packet.epoch() != epoch {
let mut poll_device = NetPacket::new([0; 12])?;
poll_device.set_source(current_device.virtual_ip());
poll_device.set_destination(source);
poll_device.set_version(Version::V1);
poll_device.first_set_ttl(MAX_TTL);
poll_device.set_protocol(Protocol::Service);
poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into());
self.channel.send_to_route(poll_device.buffer(), route_key)?;
}
}
}
ControlPacket::PunchRequest => {
log::info!("PunchRequest route_key:{:?}",route_key);
//回应
net_packet.set_transport_protocol(control_packet::Protocol::PunchResponse.into());
net_packet.set_source(current_device.virtual_ip());
net_packet.set_destination(source);
net_packet.first_set_ttl(1);
self.channel.send_to_route(net_packet.buffer(), route_key)?;
let route = Route::from(*route_key, 1, -1);
self.channel.add_route(source, route);
}
ControlPacket::PunchResponse => {
log::info!("PunchResponse route_key:{:?}",route_key);
let route = Route::from(*route_key, 1, -1);
self.channel.add_route(net_packet.source(), route);
}
}
Ok(())
}
fn other_turn(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
match turn_packet::Protocol::from(net_packet.transport_protocol()) {
turn_packet::Protocol::Punch => {
let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?;
let public_ips = punch_info.public_ip_list.
iter().map(|v| { IpAddr::from(v.to_be_bytes()) }).collect();
let peer_nat_info = NatInfo::new(public_ips,
punch_info.public_port as u16,
punch_info.public_port_range as u16,
IpAddr::from(punch_info.local_ip.to_be_bytes()),
punch_info.local_port as u16,
punch_info.nat_type.enum_value_or_default().into());
self.peer_nat_info_map.insert(source, peer_nat_info.clone());
if !punch_info.reply {
let mut punch_reply = PunchInfo::new();
punch_reply.reply = true;
let nat_info = self.nat_test.nat_info();
punch_reply.public_ip_list = nat_info.public_ips.iter().map(|i| {
match i {
IpAddr::V4(ip) => {
u32::from_be_bytes(ip.octets())
}
IpAddr::V6(_) => {
panic!()
}
}
}).collect();
punch_reply.public_port = nat_info.public_port as u32;
punch_reply.public_port_range = nat_info.public_port_range as u32;
punch_reply.nat_type =
protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type));
let bytes = punch_reply.write_to_bytes()?;
let mut net_packet =
NetPacket::new(vec![0u8; 12 + bytes.len()])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::OtherTurn);
net_packet.set_transport_protocol(
turn_packet::Protocol::Punch.into(),
);
net_packet.first_set_ttl(MAX_TTL);
net_packet.set_source(current_device.virtual_ip());
net_packet.set_destination(source);
net_packet.set_payload(&bytes);
if !peer_nat_info.local_ip.is_unspecified() {
let mut packet = NetPacket::new([0u8; 12])?;
packet.set_version(Version::V1);
packet.first_set_ttl(1);
packet.set_protocol(Protocol::Control);
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
packet.set_source(current_device.virtual_ip());
packet.set_destination(source);
let _ = self.channel.send_to_addr(packet.buffer(), SocketAddr::new(peer_nat_info.local_ip, peer_nat_info.local_port));
}
if let Err(e) = self.channel.punch(source, peer_nat_info) {
log::warn!("发送到打洞通道失败 {:?}",e);
return Ok(());
}
self.channel.send_to_route(net_packet.buffer(), route_key)?;
} else {
let _ = self.channel.punch(source, peer_nat_info);
}
}
turn_packet::Protocol::UnKnow(e) => {
log::warn!("不支持的转发协议 {:?},source:{:?}",e,source);
}
}
Ok(())
}
}
+93 -96
View File
@@ -1,139 +1,136 @@
use std::io; use std::io;
use std::net::{SocketAddr, UdpSocket}; use std::net::{Ipv4Addr, SocketAddr};
use std::sync::atomic::{AtomicI64, Ordering}; use std::sync::atomic::{AtomicI64, Ordering};
use std::time::Duration; use std::time::Duration;
use chrono::Local; use chrono::Local;
use crossbeam::atomic::AtomicCell;
use parking_lot::RwLock;
use protobuf::Message; use protobuf::Message;
use nat_traversal::channel::Channel;
use nat_traversal::channel::sender::Sender;
use crate::error::*; use crate::error::*;
use crate::handle::ConnectStatus;
use crate::proto::message::{RegistrationRequest, RegistrationResponse}; use crate::proto::message::{RegistrationRequest, RegistrationResponse};
use crate::protocol::error_packet::InErrorPacket; use crate::protocol::error_packet::InErrorPacket;
use crate::protocol::{service_packet, NetPacket, Protocol, Version}; use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
lazy_static::lazy_static! { ///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致
static ref REQUEST:RwLock<Option<(String,String,String)>> = parking_lot::const_rwlock(None);
static ref REGISTRATION_TIME:AtomicI64=AtomicI64::new(0);
pub(crate) static ref CONNECTION_STATUS:AtomicCell<ConnectStatus> = AtomicCell::new(ConnectStatus::Connecting);
}
///向中继服务器注册,token标识一个虚拟网关,mac_address防止多次注册时得到的ip不一致
pub fn registration( pub fn registration(
udp: &UdpSocket, channel: &mut Channel<Ipv4Addr>,
server_address: SocketAddr, server_address: SocketAddr,
token: String, token: String,
mac_address: String, device_id: String,
name: String, name: String,
) -> Result<RegistrationResponse> { ) -> Result<RegistrationResponse> {
// todo 和服务器通信加密
let request_packet = let request_packet =
registration_request_packet(token.clone(), mac_address.clone(), name.clone(), false)?; registration_request_packet(token.clone(), device_id.clone(), name.clone(), false)?;
let buf = request_packet.buffer(); let buf = request_packet.buffer();
let mut counter = 0;
let mut recv_buf = [0u8; 10240]; let mut recv_buf = [0u8; 10240];
udp.set_read_timeout(Some(Duration::from_millis(500)))?; channel.send_to_addr(buf, server_address)?;
loop { let (len, route) = channel.recv_from(&mut recv_buf, Some(Duration::from_millis(300)))?;
counter += 1; if server_address != route.addr {
if counter & 10 == 10 { return Err(Error::Warn(format!("数据来源错误:{:?}", route.addr)));
return Err(Error::Stop("注册请求超时".to_string()));
}
udp.send_to(buf, server_address)?;
let (len, addr) = match udp.recv_from(&mut recv_buf) {
Ok(ok) => ok,
Err(e) => {
if e.kind() == io::ErrorKind::WouldBlock || e.kind() == io::ErrorKind::TimedOut {
continue;
}
return Err(Error::Io(e));
}
};
if server_address != addr {
continue;
}
let net_packet = NetPacket::new(&recv_buf[..len])?;
match net_packet.protocol() {
Protocol::Service => {
match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::RegistrationResponse => {
let response =
RegistrationResponse::parse_from_bytes(net_packet.payload())?;
let _ = REQUEST.write().replace((token, mac_address, name));
udp.set_read_timeout(None)?;
CONNECTION_STATUS.store(ConnectStatus::Connected);
return Ok(response);
}
_ => {}
}
}
Protocol::Error => {
return match InErrorPacket::new(
net_packet.transport_protocol(),
net_packet.payload(),
) {
Ok(e) => match e {
InErrorPacket::TokenError => Err(Error::Stop("token错误".to_string())),
InErrorPacket::Disconnect => Err(Error::Stop("断开连接".to_string())),
InErrorPacket::AddressExhausted => Err(Error::Stop("地址用尽".to_string())),
InErrorPacket::OtherError(e) => match e.message() {
Ok(str) => Err(Error::Stop(str)),
Err(e) => Err(Error::Stop(format!("{:?}", e))),
},
},
Err(e) => Err(Error::Stop(format!("{:?}", e))),
};
}
_ => {
return Err(Error::Stop(format!("数据错误:{:?}", net_packet)));
}
}
} }
let net_packet = NetPacket::new(&recv_buf[..len])?;
return match net_packet.protocol() {
Protocol::Service => {
match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::RegistrationResponse => {
let response =
RegistrationResponse::parse_from_bytes(net_packet.payload())?;
Ok(response)
}
_ => {
Err(Error::Warn(format!("数据错误:{:?}", net_packet)))
}
}
}
Protocol::Error => {
match InErrorPacket::new(
net_packet.transport_protocol(),
net_packet.payload(),
) {
Ok(e) => match e {
InErrorPacket::TokenError => Err(Error::Stop("token错误".to_string())),
InErrorPacket::Disconnect => Err(Error::Warn("断开连接".to_string())),
InErrorPacket::AddressExhausted => Err(Error::Stop("地址用尽".to_string())),
InErrorPacket::OtherError(e) => match e.message() {
Ok(str) => Err(Error::Warn(str)),
Err(e) => Err(Error::Warn(format!("{:?}", e))),
},
},
Err(e) => Err(Error::Warn(format!("{:?}", e))),
}
}
_ => {
Err(Error::Warn(format!("数据错误:{:?}", net_packet)))
}
};
} }
fn registration_request_packet( fn registration_request_packet(
token: String, token: String,
mac_address: String, device_id: String,
name: String, name: String,
is_fast: bool, is_fast: bool,
) -> Result<NetPacket<Vec<u8>>> { ) -> crate::Result<NetPacket<Vec<u8>>> {
let mut request = RegistrationRequest::new(); let mut request = RegistrationRequest::new();
request.token = token; request.token = token;
request.mac_address = mac_address; request.device_id = device_id;
request.name = name; request.name = name;
request.is_fast = is_fast; request.is_fast = is_fast;
let bytes = request.write_to_bytes()?; let bytes = request.write_to_bytes()?;
let buf = vec![0u8; 4 + bytes.len()]; let buf = vec![0u8; 12 + bytes.len()];
let mut net_packet = NetPacket::new(buf)?; let mut net_packet = NetPacket::new(buf)?;
net_packet.set_version(Version::V1); net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Service); net_packet.set_protocol(Protocol::Service);
net_packet.set_transport_protocol(service_packet::Protocol::RegistrationRequest.into()); net_packet.set_transport_protocol(service_packet::Protocol::RegistrationRequest.into());
net_packet.set_ttl(255); net_packet.first_set_ttl(MAX_TTL);
net_packet.set_payload(&bytes); net_packet.set_payload(&bytes);
Ok(net_packet) Ok(net_packet)
} }
pub fn fast_registration(udp: &UdpSocket, server_address: SocketAddr) -> Result<()> { pub struct Register {
let last = REGISTRATION_TIME.load(Ordering::Relaxed); sender: Sender<Ipv4Addr>,
let new = Local::now().timestamp_millis(); server_address: SocketAddr,
if new - last < 2000 token: String,
|| REGISTRATION_TIME device_id: String,
name: String,
time: AtomicI64,
}
impl Register {
pub fn new(sender: Sender<Ipv4Addr>,
server_address: SocketAddr,
token: String,
device_id: String,
name: String, ) -> Self {
Self {
sender,
server_address,
token,
device_id,
name,
time: AtomicI64::new(0),
}
}
pub fn fast_register(&self) -> io::Result<()> {
let last = self.time.load(Ordering::Relaxed);
let new = Local::now().timestamp_millis();
if new - last < 1000
|| self.time
.compare_exchange(last, new, Ordering::Relaxed, Ordering::Relaxed) .compare_exchange(last, new, Ordering::Relaxed, Ordering::Relaxed)
.is_err() .is_err()
{ {
//短时间不重复注册 //短时间不重复注册
return Ok(()); return Ok(());
}
log::info!("重新连接");
let request_packet =
registration_request_packet(self.token.clone(),
self.device_id.clone(),
self.name.clone(), false).unwrap();
let buf = request_packet.buffer();
self.sender.send_to_addr(buf, self.server_address)?;
Ok(())
} }
CONNECTION_STATUS.store(ConnectStatus::Connecting);
let lock = REQUEST.read();
let option = lock.clone();
drop(lock);
if let Some((token, mac_address, name)) = option {
let request_packet = registration_request_packet(token, mac_address, name, true)?;
udp.send_to(request_packet.buffer(), server_address)?;
REGISTRATION_TIME.store(Local::now().timestamp_millis(), Ordering::Relaxed);
return Ok(());
}
return Err(Error::Stop("注册信息不存在".to_string()));
} }
+30 -130
View File
@@ -1,29 +1,22 @@
use std::{io, thread};
/// 接收tun数据,并且转发到udp上 /// 接收tun数据,并且转发到udp上
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket}; use std::net::Ipv4Addr;
use std::thread; use std::sync::Arc;
use crossbeam::atomic::AtomicCell;
use chrono::Local;
use tokio::sync::watch;
use nat_traversal::channel::sender::Sender;
use packet::icmp::icmp::IcmpPacket; use packet::icmp::icmp::IcmpPacket;
use packet::icmp::Kind; use packet::icmp::Kind;
use packet::ip::ipv4; use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet; use packet::ip::ipv4::packet::IpV4Packet;
use crate::error::*; use crate::error::*;
use crate::handle::{CurrentDeviceInfo, DIRECT_ROUTE_TABLE}; use crate::handle::{check_dest, CurrentDeviceInfo};
use crate::protocol::turn_packet::TurnPacket; use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version};
use crate::protocol::{NetPacket, Protocol, Version}; use crate::tun_device::{TunReader, TunWriter};
use crate::tun_device::TunReader;
use crate::ApplicationStatus;
/// 是否在一个网段
fn check_dest(dest: Ipv4Addr, cur_info: &CurrentDeviceInfo) -> bool {
u32::from_be_bytes(dest.octets()) & u32::from_be_bytes(cur_info.virtual_netmask.octets())
== u32::from_be_bytes(cur_info.virtual_network.octets())
}
fn icmp(udp: &UdpSocket, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> { fn icmp(tun_writer: &TunWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> {
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp { if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?; let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
if icmp.kind() == Kind::EchoRequest { if icmp.kind() == Kind::EchoRequest {
@@ -33,21 +26,14 @@ fn icmp(udp: &UdpSocket, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> {
ipv4_packet.set_source_ip(ipv4_packet.destination_ip()); ipv4_packet.set_source_ip(ipv4_packet.destination_ip());
ipv4_packet.set_destination_ip(src); ipv4_packet.set_destination_ip(src);
ipv4_packet.update_checksum(); ipv4_packet.update_checksum();
let mut addr = udp.local_addr()?; tun_writer.write(ipv4_packet.buffer)?;
addr.set_ip(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
udp.send_to(ipv4_packet.buffer, addr)?;
} }
} }
Ok(()) Ok(())
} }
#[inline] #[inline]
fn handle( fn handle(sender: &Sender<Ipv4Addr>, data: &mut [u8], tun_writer: &TunWriter, current_device: CurrentDeviceInfo, net_packet: &mut NetPacket<Vec<u8>>) -> Result<()> {
udp: &UdpSocket,
data: &mut [u8],
cur_info: &CurrentDeviceInfo,
net_packet: &mut NetPacket<Vec<u8>>,
) -> Result<()> {
let data_len = data.len(); let data_len = data.len();
let ipv4_packet = match IpV4Packet::new(data) { let ipv4_packet = match IpV4Packet::new(data) {
Ok(ipv4_packet) => ipv4_packet, Ok(ipv4_packet) => ipv4_packet,
@@ -63,131 +49,45 @@ fn handle(
// // 137端口是在局域网中提供计算机的名字或IP地址查询服务 // // 137端口是在局域网中提供计算机的名字或IP地址查询服务
// return Ok(()); // return Ok(());
// } // }
if src_ip != cur_info.virtual_ip || !check_dest(dest_ip, &cur_info) { if src_ip != current_device.virtual_ip() || !check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) {
return Ok(()); return Ok(());
} }
if src_ip == dest_ip { if src_ip == dest_ip {
return icmp(&udp, ipv4_packet); return icmp(&tun_writer, ipv4_packet);
} }
let mut ipv4_turn_packet = TurnPacket::new(net_packet.payload_mut())?; net_packet.set_source(src_ip);
ipv4_turn_packet.set_source(src_ip); net_packet.set_destination(dest_ip);
ipv4_turn_packet.set_destination(dest_ip); net_packet.set_payload(ipv4_packet.buffer);
ipv4_turn_packet.set_payload(ipv4_packet.buffer);
//优先发到直连到地址 //优先发到直连到地址
if let Some(route) = DIRECT_ROUTE_TABLE.get(&dest_ip) { if sender.send_to_id(&net_packet.buffer()[..(4 + 8 + data_len)], &dest_ip).is_err() {
let current_time = Local::now().timestamp_millis(); sender.send_to_addr(&net_packet.buffer()[..(4 + 8 + data_len)], current_device.connect_server)?;
if current_time - route.recv_time < 3_000 {
if udp
.send_to(&net_packet.buffer()[..(4 + 8 + data_len)], route.address)
.is_ok()
{
return Ok(());
}
}
} }
udp.send_to(
&net_packet.buffer()[..(4 + 8 + data_len)],
cur_info.connect_server,
)?;
return Ok(()); return Ok(());
} }
#[cfg(target_os = "windows")] pub fn start(sender: Sender<Ipv4Addr>,
pub async fn handler_start<F>( tun_reader: TunReader,
mut status_watch: watch::Receiver<ApplicationStatus>, tun_writer: TunWriter,
udp: UdpSocket, current_device: Arc<AtomicCell<CurrentDeviceInfo>>, ) {
tun_reader: TunReader,
cur_info: CurrentDeviceInfo,
stop_fn: F,
) where
F: FnOnce() + Send + 'static,
{
let session = tun_reader.0.clone();
tokio::spawn(async move {
let _ = status_watch.changed().await;
session.shutdown();
let udp = UdpSocket::bind("0.0.0.0:0").unwrap();
let _ = udp.send_to(
&[0],
SocketAddr::new(IpAddr::V4(cur_info.virtual_gateway), 10),
);
});
thread::spawn(move || { thread::spawn(move || {
if let Err(e) = handle_loop(udp, tun_reader, cur_info) { if let Err(e) = start_(sender, tun_reader, tun_writer, current_device) {
log::warn!("tun数据处理线程停止 {:?}", e); log::warn!("{:?}",e);
} }
stop_fn();
}); });
} }
#[cfg(target_os = "windows")] fn start_(sender: Sender<Ipv4Addr>,
fn handle_loop(udp: UdpSocket, tun_reader: TunReader, cur_info: CurrentDeviceInfo) -> Result<()> { tun_reader: TunReader,
tun_writer: TunWriter,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, ) -> io::Result<()> {
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500])?; let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500])?;
net_packet.set_version(Version::V1); net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Ipv4Turn); net_packet.set_protocol(Protocol::Ipv4Turn);
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into()); net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into());
net_packet.set_ttl(255); net_packet.set_ttl(MAX_TTL);
loop { loop {
let mut data = tun_reader.next()?; let mut data = tun_reader.next()?;
match handle(&udp, data.bytes_mut(), &cur_info, &mut net_packet) { match handle(&sender, data.bytes_mut(), &tun_writer, current_device.load(), &mut net_packet) {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
}
}
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "android"))]
pub async fn handler_start<F>(
mut status_watch: watch::Receiver<ApplicationStatus>,
udp: UdpSocket,
tun_reader: TunReader,
cur_info: CurrentDeviceInfo,
stop_fn: F,
) where
F: FnOnce() + Send + 'static,
{
#[cfg(target_os = "macos")]
use std::os::fd::AsRawFd;
#[cfg(target_os = "linux")]
use std::os::unix::io::AsRawFd;
let raw_fd = tun_reader.0.as_raw_fd();
tokio::spawn(async move {
let _ = status_watch.changed().await;
// 让tun接收线程关闭,问题:如果改变tun配置,可能导致tun接收线程无法关闭
unsafe {
libc::close(raw_fd);
}
let udp = UdpSocket::bind("0.0.0.0:0").unwrap();
let _ = udp.send_to(
&[0],
SocketAddr::new(IpAddr::V4(cur_info.virtual_gateway), 10),
);
});
thread::spawn(move || {
if let Err(e) = handle_loop(udp, tun_reader, cur_info) {
log::warn!(" tun数据处理线程停止 {:?}", e);
}
stop_fn();
});
}
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "android"))]
pub fn handle_loop(
udp: UdpSocket,
mut tun_reader: TunReader,
cur_info: CurrentDeviceInfo,
) -> Result<()> {
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Ipv4Turn);
net_packet.set_transport_protocol(0);
net_packet.set_ttl(255);
let mut buf = [0u8; 1500];
loop {
let data = tun_reader.read(&mut buf)?;
match handle(&udp, data, &cur_info, &mut net_packet) {
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
log::warn!("{:?}", e) log::warn!("{:?}", e)
-389
View File
@@ -1,389 +0,0 @@
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use std::sync::atomic::Ordering;
use std::thread;
use chrono::Local;
use packet::icmp::{icmp, Kind};
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use protobuf::Message;
use tokio::sync::mpsc::error::TrySendError;
use tokio::sync::mpsc::{Receiver, Sender};
use tokio::sync::watch;
use crate::error::*;
use crate::handle::punch_handler::PunchSender;
use crate::handle::registration_handler::{fast_registration, CONNECTION_STATUS};
use crate::handle::{
ConnectStatus, Route, ADDR_TABLE, DEVICE_LIST, DIRECT_ROUTE_TABLE, NAT_INFO, SERVER_RT,
};
use crate::proto::message::{DeviceList, Punch, RegistrationResponse};
use crate::protocol::control_packet::{ControlPacket, PunchResponsePacket};
use crate::protocol::error_packet::InErrorPacket;
use crate::protocol::turn_packet::TurnPacket;
use crate::protocol::{control_packet, service_packet, turn_packet, NetPacket, Protocol, Version};
use crate::tun_device::TunWriter;
use crate::{ApplicationStatus, CurrentDeviceInfo, PeerDeviceInfo};
const UDP_STOP_BUF: [u8; 1] = [0u8];
pub async fn udp_recv_start<F>(
mut status_watch: watch::Receiver<ApplicationStatus>,
udp: UdpSocket,
server_addr: SocketAddr,
other_sender: Sender<(SocketAddr, Vec<u8>)>,
tun_writer: TunWriter,
current_device: CurrentDeviceInfo,
stop_fn: F,
) where
F: FnOnce() + Send + 'static,
{
{
let udp = udp.try_clone().unwrap();
tokio::spawn(async move {
let _ = status_watch.changed().await;
let mut addr = udp.local_addr().unwrap();
addr.set_ip(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
udp.send_to(&UDP_STOP_BUF, addr).unwrap();
});
}
thread::spawn(move || {
if let Err(e) = recv_loop(udp, server_addr, other_sender, tun_writer, current_device) {
log::warn!("udp数据处理线程停止 {:?}", e);
}
stop_fn();
});
}
fn recv_loop(
udp: UdpSocket,
server_addr: SocketAddr,
other_sender: Sender<(SocketAddr, Vec<u8>)>,
mut tun_writer: TunWriter,
current_device: CurrentDeviceInfo,
) -> Result<()> {
let mut buf = [0u8; 65536];
let mut local_addr = udp.local_addr()?;
local_addr.set_ip(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
loop {
match udp.recv_from(&mut buf) {
Ok((len, addr)) => {
if addr == local_addr {
if len == 1 && &buf[..len] == &UDP_STOP_BUF {
return Ok(());
}
//本地的包直接再发到网卡,这个主要用于处理当前虚拟ip的icmp ping
if let Ok(ip) = IpV4Packet::new(&buf[..len]) {
if ip.destination_ip() == current_device.virtual_ip {
let _ = tun_writer.write(&buf[..len]);
}
}
continue;
}
match recv_handle(
&udp,
addr,
&mut buf[..len],
&server_addr,
&other_sender,
&mut tun_writer,
&current_device,
) {
Ok(_) => {}
Err(Error::Stop(str)) => {
return Err(Error::Stop(str));
}
Err(e) => {
log::warn!("{:?}", e);
}
}
}
Err(e) => {
log::warn!("{:?}", e);
}
};
}
}
fn recv_handle(
udp: &UdpSocket,
recv_addr: SocketAddr,
buf: &mut [u8],
_server_addr: &SocketAddr,
other_sender: &Sender<(SocketAddr, Vec<u8>)>,
tun_writer: &mut TunWriter,
current_device: &CurrentDeviceInfo,
) -> Result<()> {
let mut net_packet = NetPacket::new(buf)?;
match net_packet.protocol() {
Protocol::Ipv4Turn => {
let mut ipv4_turn_packet = TurnPacket::new(net_packet.payload_mut())?;
let source = ipv4_turn_packet.source();
let destination = ipv4_turn_packet.destination();
let mut ipv4 = IpV4Packet::new(ipv4_turn_packet.payload_mut())?;
if ipv4.source_ip() == source
&& ipv4.destination_ip() == destination
&& current_device.virtual_ip == ipv4.destination_ip()
{
if ipv4.protocol() == ipv4::protocol::Protocol::Icmp {
let mut icmp_packet = icmp::IcmpPacket::new(ipv4.payload_mut())?;
if icmp_packet.kind() == Kind::EchoRequest {
//开启ping
icmp_packet.set_kind(Kind::EchoReply);
icmp_packet.update_checksum();
ipv4.set_source_ip(destination);
ipv4.set_destination_ip(source);
ipv4.update_checksum();
ipv4_turn_packet.set_source(destination);
ipv4_turn_packet.set_destination(source);
udp.send_to(net_packet.buffer(), recv_addr)?;
} else {
tun_writer.write(ipv4_turn_packet.payload())?;
}
} else {
tun_writer.write(ipv4_turn_packet.payload())?;
}
}
}
Protocol::UnKnow(_) => {}
_ => {
//发送到子线程处理
let v = net_packet.buffer().to_vec();
match other_sender.try_send((recv_addr, v)) {
Ok(_) => {}
Err(TrySendError::Closed(_)) => {
return Err(Error::Stop("子处理线程停止".to_string()));
}
Err(e) => {
log::warn!("子线程处理 {:?}", e);
}
}
}
}
Ok(())
}
pub async fn udp_other_recv_start<F>(
status_watch: watch::Receiver<ApplicationStatus>,
udp: UdpSocket,
receiver: Receiver<(SocketAddr, Vec<u8>)>,
current_device: CurrentDeviceInfo,
sender: PunchSender,
stop_fn: F,
) where
F: FnOnce() + Send + 'static,
{
tokio::spawn(async move {
match other_loop(status_watch, udp, receiver, current_device, sender).await {
Ok(_) => {
log::info!("udp子处理线程停止");
}
Err(e) => {
log::warn!("{:?}", e);
}
}
stop_fn();
});
}
async fn other_loop(
mut status_watch: watch::Receiver<ApplicationStatus>,
udp: UdpSocket,
mut receiver: Receiver<(SocketAddr, Vec<u8>)>,
current_device: CurrentDeviceInfo,
sender: PunchSender,
) -> Result<()> {
loop {
tokio::select! {
rs = receiver.recv()=>{
if let Some((peer_addr, buf)) = rs {
match other_handle(&udp, buf, peer_addr, &current_device, &sender) {
Ok(_) => {}
Err(Error::Stop(str)) => {
return Err(Error::Stop(str));
}
Err(e) => {
log::warn!("other_loop {:?}",e);
}
}
}
}
status = status_watch.changed() =>{
status?;
if *status_watch.borrow() != ApplicationStatus::Starting{
return Ok(())
}
}
}
}
}
fn other_handle(
udp: &UdpSocket,
buf: Vec<u8>,
peer_addr: SocketAddr,
current_device: &CurrentDeviceInfo,
sender: &PunchSender,
) -> Result<()> {
let server_addr = current_device.connect_server;
let mut net_packet = NetPacket::new(buf)?;
match net_packet.protocol() {
Protocol::Service => {
if peer_addr != current_device.connect_server {
return Ok(());
}
match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::RegistrationRequest => {}
service_packet::Protocol::RegistrationResponse => {
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?;
crate::handle::init_nat_info(response.public_ip, response.public_port as u16);
CONNECTION_STATUS.store(ConnectStatus::Connected);
//需要保证重连ip不变
}
service_packet::Protocol::UpdateDeviceList => {
let device_list = DeviceList::parse_from_bytes(net_packet.payload())?;
let ip_list = device_list
.device_info_list
.into_iter()
.map(|info| {
PeerDeviceInfo::new(
Ipv4Addr::from(info.virtual_ip),
info.name,
info.device_status as u8,
)
})
.collect();
let mut dev = DEVICE_LIST.lock();
if dev.0 < device_list.epoch || device_list.epoch - dev.0 > u32::MAX >> 2 {
dev.0 = device_list.epoch;
dev.1 = ip_list;
}
}
service_packet::Protocol::UnKnow(_) => {}
}
}
Protocol::Error => {
match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
InErrorPacket::TokenError => {
if server_addr == peer_addr {
//停止整个应用
return Err(Error::Stop("token无效".to_string()));
}
}
InErrorPacket::Disconnect => {
if server_addr == peer_addr {
fast_registration(&udp, server_addr)?;
}
}
InErrorPacket::AddressExhausted => {
return Err(Error::Stop("IP address has been exhausted".to_string()));
}
InErrorPacket::OtherError(e) => {
log::error!("OtherError {:?}", e.message());
}
}
}
Protocol::Control => {
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
ControlPacket::PingPacket(_ping) => {
net_packet.set_transport_protocol(control_packet::Protocol::Pong.into());
udp.send_to(&net_packet.buffer()[..12], peer_addr)?;
}
ControlPacket::PongPacket(pong_packet) => {
let current_time = Local::now().timestamp_millis();
let rt = current_time - pong_packet.time();
if rt >= 0 {
if peer_addr == server_addr {
SERVER_RT.store(rt, Ordering::Relaxed)
} else {
//其他设备
if let Some(virtual_ip) = ADDR_TABLE.get(&peer_addr) {
if let Some(mut info) = DIRECT_ROUTE_TABLE.get_mut(&virtual_ip) {
info.rt = rt;
info.recv_time = current_time;
}
}
}
}
}
ControlPacket::PunchRequest(punch_request) => {
// println!("打洞请求:{:?}", punch_request);
let src = punch_request.source();
drop(punch_request);
//回应
let mut punch_response = PunchResponsePacket::new(net_packet.payload_mut())?;
punch_response.set_source(current_device.virtual_ip);
net_packet
.set_transport_protocol(control_packet::Protocol::PunchResponse.into());
udp.send_to(net_packet.buffer(), peer_addr)?;
let route = Route::new(peer_addr);
DIRECT_ROUTE_TABLE.insert(src, route);
ADDR_TABLE.insert(peer_addr, src);
}
ControlPacket::PunchResponse(punch_response) => {
// println!("打洞响应:{:?}", punch_response);
let route = Route::new(peer_addr);
DIRECT_ROUTE_TABLE.insert(punch_response.source(), route);
ADDR_TABLE.insert(peer_addr, punch_response.source());
}
}
}
Protocol::Ipv4Turn => {}
Protocol::OtherTurn => {
let turn_packet = TurnPacket::new(net_packet.payload())?;
// println!("{:?}",turn_packet);
let src = turn_packet.source();
let dest = turn_packet.destination();
if dest == current_device.virtual_ip {
match turn_packet::Protocol::from(net_packet.transport_protocol()) {
turn_packet::Protocol::Punch => {
let punch = Punch::parse_from_bytes(turn_packet.payload())?;
if punch.virtual_ip.to_be_bytes() == src.octets() {
if !punch.reply {
let mut punch_reply = Punch::new();
punch_reply.reply = true;
punch_reply.virtual_ip =
u32::from_be_bytes(current_device.virtual_ip.octets());
if let Err(_) = sender.try_send(punch) {
return Ok(());
}
let nat_info = NAT_INFO.lock();
if let Some(info) = nat_info.as_ref() {
punch_reply.public_ip_list = info.public_ips.clone();
punch_reply.public_port = info.public_port as u32;
punch_reply.public_port_range = info.public_port_range as u32;
punch_reply.nat_type =
protobuf::EnumOrUnknown::new(info.nat_type);
drop(nat_info);
let bytes = punch_reply.write_to_bytes()?;
let mut net_packet =
NetPacket::new(vec![0u8; 4 + 8 + bytes.len()])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::OtherTurn);
net_packet.set_transport_protocol(
turn_packet::Protocol::Punch.into(),
);
net_packet.set_ttl(255);
let mut turn_packet =
TurnPacket::new(net_packet.payload_mut())?;
turn_packet.set_source(current_device.virtual_ip);
turn_packet.set_destination(src);
turn_packet.set_payload(&bytes);
udp.send_to(net_packet.buffer(), peer_addr)?;
}
} else {
let _ = sender.try_send(punch);
}
}
}
turn_packet::Protocol::UnKnow(_) => {}
}
}
}
Protocol::UnKnow(p) => {
log::warn!("未知协议 {}", p);
}
}
Ok(())
}
+358 -365
View File
@@ -1,21 +1,27 @@
use std::io; use crate::error::Error;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::time::Duration;
use crossbeam::atomic::AtomicCell; // use std::io;
use crossbeam::sync::WaitGroup; // use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
use parking_lot::Mutex; // use std::sync::atomic::Ordering;
use tokio::sync::watch; // use std::sync::Arc;
// use std::time::Duration;
//
// use crossbeam::atomic::AtomicCell;
// use crossbeam::sync::WaitGroup;
// use parking_lot::Mutex;
// use tokio::sync::watch;
//
// use error::*;
//
// use crate::handle::registration_handler::CONNECTION_STATUS;
// use crate::handle::{
// ApplicationStatus, ConnectStatus, CurrentDeviceInfo, NatInfo, PeerDeviceInfo, Route, RouteType,
// DEVICE_LIST, DIRECT_ROUTE_TABLE, NAT_INFO, SERVER_RT,
// };
// use crate::nat::channel::NatChannel;
pub use nat_traversal::channel::{Route, RouteKey};
use error::*; pub type Result<T> = std::result::Result<T, Error>;
use crate::handle::registration_handler::CONNECTION_STATUS;
use crate::handle::{
ApplicationStatus, ConnectStatus, CurrentDeviceInfo, NatInfo, PeerDeviceInfo, Route, RouteType,
DEVICE_LIST, DIRECT_ROUTE_TABLE, NAT_INFO, SERVER_RT,
};
pub mod error; pub mod error;
pub mod handle; pub mod handle;
@@ -23,353 +29,340 @@ pub mod nat;
pub mod proto; pub mod proto;
pub mod protocol; pub mod protocol;
pub mod tun_device; pub mod tun_device;
pub mod core;
#[derive(Clone, Debug)] //
pub struct Config<F> { // #[derive(Clone, Debug)]
pub token: String, // pub struct Config<F> {
pub mac_address: String, // pub token: String,
pub name: String, // pub mac_address: String,
pub server_address: SocketAddr, // pub name: String,
pub nat_test_server: Vec<SocketAddr>, // pub server_address: SocketAddr,
pub abnormal_call: F, // pub nat_test_server: Vec<SocketAddr>,
} // pub abnormal_call: F,
// }
impl<F> Config<F> { //
pub fn new( // impl<F> Config<F> {
token: String, // pub fn new(
mac_address: String, // token: String,
name: Option<String>, // mac_address: String,
server_address: SocketAddr, // name: Option<String>,
nat_test_server: Vec<SocketAddr>, // server_address: SocketAddr,
abnormal_call: F, // nat_test_server: Vec<SocketAddr>,
) -> Result<Self> // abnormal_call: F,
where // ) -> Result<Self>
F: FnOnce() + Send + 'static, // where
{ // F: FnOnce() + Send + 'static,
if token.is_empty() || token.len() > 64 { // {
return Err(Error::Stop("token invalid".to_string())); // if token.is_empty() || token.len() > 64 {
} // return Err(Error::Stop("token invalid".to_string()));
if mac_address.len() != 12 + 5 { // }
return Err(Error::Stop("mac_address invalid".to_string())); // if mac_address.len() != 12 + 5 {
} // return Err(Error::Stop("mac_address invalid".to_string()));
if let Some(name) = name { // }
if name.is_empty() || name.len() > 64 { // if let Some(name) = name {
return Err(Error::Stop("name invalid".to_string())); // if name.is_empty() || name.len() > 64 {
} // return Err(Error::Stop("name invalid".to_string()));
Ok(Self { // }
token, // Ok(Self {
mac_address, // token,
name, // mac_address,
server_address, // name,
nat_test_server, // server_address,
abnormal_call, // nat_test_server,
}) // abnormal_call,
} else { // })
let info = os_info::get(); // } else {
let name = if info.version() != &os_info::Version::Unknown { // let info = os_info::get();
format!("{} {}", info.os_type(), info.version()) // let name = if info.version() != &os_info::Version::Unknown {
} else { // format!("{} {}", info.os_type(), info.version())
format!("{}", info.os_type()) // } else {
}; // format!("{}", info.os_type())
Ok(Self { // };
token, // Ok(Self {
mac_address, // token,
name, // mac_address,
server_address, // name,
nat_test_server, // server_address,
abnormal_call, // nat_test_server,
}) // abnormal_call,
} // })
} // }
} // }
// }
pub struct Switch { //
current_device: CurrentDeviceInfo, // pub struct Switch {
status_sender: Arc<Mutex<watch::Sender<ApplicationStatus>>>, // current_device: CurrentDeviceInfo,
wait_group: WaitGroup, // status_sender: Arc<Mutex<watch::Sender<ApplicationStatus>>>,
runtime: Option<tokio::runtime::Runtime>, // wait_group: WaitGroup,
} // runtime: Option<tokio::runtime::Runtime>,
// }
impl Switch { //
pub fn start<F>(config: Config<F>) -> Result<Self> // impl Switch {
where // pub fn start<F>(config: Config<F>) -> Result<Self>
F: FnOnce() + Send + 'static, // where
{ // F: FnOnce() + Send + 'static,
let runtime = tokio::runtime::Builder::new_multi_thread() // {
.enable_all() // let runtime = tokio::runtime::Builder::new_multi_thread()
.build() // .enable_all()
.unwrap(); // .build()
return match runtime.block_on(Switch::start_(config)) { // .unwrap();
Ok(mut switch) => { // todo!()
switch.runtime = Some(runtime); // // return match runtime.block_on(Switch::start_(config)) {
Ok(switch) // // Ok(mut switch) => {
} // // switch.runtime = Some(runtime);
Err(e) => Err(e), // // Ok(switch)
}; // // }
} // // Err(e) => Err(e),
pub fn stop(self) { // // };
Self::call_stop(self.status_sender); // }
self.wait_group.wait(); // pub fn stop(self) {
} // Self::call_stop(self.status_sender);
pub fn stop_async(&self) { // self.wait_group.wait();
Self::call_stop(self.status_sender.clone()); // }
} // pub fn stop_async(&self) {
pub fn current_device(&self) -> &CurrentDeviceInfo { // Self::call_stop(self.status_sender.clone());
&self.current_device // }
} // pub fn current_device(&self) -> &CurrentDeviceInfo {
pub fn nat_info(&self) -> Option<NatInfo> { // &self.current_device
NAT_INFO.lock().clone() // }
} // pub fn nat_info(&self) -> Option<NatInfo> {
pub fn server_rt(&self) -> i64 { // NAT_INFO.lock().clone()
SERVER_RT.load(Ordering::Relaxed) // }
} // pub fn server_rt(&self) -> i64 {
pub fn connection_status(&self) -> ConnectStatus { // SERVER_RT.load(Ordering::Relaxed)
CONNECTION_STATUS.load() // }
} // pub fn connection_status(&self) -> ConnectStatus {
pub fn device_list(&self) -> Vec<PeerDeviceInfo> { // CONNECTION_STATUS.load()
let device_list_lock = DEVICE_LIST.lock(); // }
let (_epoch, device_list) = device_list_lock.clone(); // pub fn device_list(&self) -> Vec<PeerDeviceInfo> {
drop(device_list_lock); // let device_list_lock = DEVICE_LIST.lock();
device_list // let (_epoch, device_list) = device_list_lock.clone();
} // drop(device_list_lock);
pub fn route(&self, ip: &Ipv4Addr) -> Route { // device_list
if let Some(route_ref) = DIRECT_ROUTE_TABLE.get(ip) { // }
route_ref.value().clone() // pub fn route(&self, ip: &Ipv4Addr) -> Route {
} else { // if let Some(route_ref) = DIRECT_ROUTE_TABLE.get(ip) {
let mut route = Route::new(self.current_device.connect_server); // route_ref.value().clone()
route.route_type = RouteType::ServerRelay; // } else {
route.rt = self.server_rt() * 2; // let mut route = Route::new(self.current_device.connect_server);
route.recv_time = -1; // route.route_type = RouteType::ServerRelay;
route // route.rt = self.server_rt() * 2;
} // route.recv_time = -1;
} // route
} // }
// }
impl Switch { // }
fn call_stop(status_sender: Arc<Mutex<watch::Sender<ApplicationStatus>>>) -> bool { //
let lock = status_sender.lock(); // impl Switch {
let status = lock.send_replace(ApplicationStatus::Stopping); // fn call_stop(status_sender: Arc<Mutex<watch::Sender<ApplicationStatus>>>) -> bool {
return status == ApplicationStatus::Starting; // let lock = status_sender.lock();
} // let status = lock.send_replace(ApplicationStatus::Stopping);
pub async fn start_<F>(config: Config<F>) -> Result<Self> // return status == ApplicationStatus::Starting;
where // }
F: FnOnce() + Send + 'static, // // pub async fn start_<F>(config: Config<F>) -> Result<Self>
{ // // where
// let server_address = "nat1.wherewego.top:29876" // // F: FnOnce() + Send + 'static,
// let server_address = "nat1.wherewego.top:29875".to_socket_addrs().unwrap().next().unwrap(); // // {
let server_address = config.server_address; // // // let server_address = "nat1.wherewego.top:29876"
let mut port = 101 as u16; // // // let server_address = "nat1.wherewego.top:29875".to_socket_addrs().unwrap().next().unwrap();
let udp = loop { // // let server_address = config.server_address;
match UdpSocket::bind(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(0), port))) { // // let nat_channel = NatChannel::new(server_address,100,).await?;
Ok(udp) => { // // //注册
break udp; // // let response = handle::registration_handler::registration(
} // // &udp,
Err(e) => { // // server_address,
if e.kind() == io::ErrorKind::AddrInUse { // // config.token,
port += 1; // // config.mac_address,
} else { // // config.name,
log::error!("创建udp失败 {:?}", e); // // )?;
return Err(Error::Stop("udp bind error".to_string())); // // {
} // // let ip_list = response
} // // .device_info_list
} // // .into_iter()
}; // // .map(|info| {
udp.set_write_timeout(Some(Duration::from_millis(2000)))?; // // PeerDeviceInfo::new(
//注册 // // Ipv4Addr::from(info.virtual_ip),
let response = handle::registration_handler::registration( // // info.name,
&udp, // // info.device_status as u8,
server_address, // // )
config.token, // // })
config.mac_address, // // .collect();
config.name, // // let mut dev = DEVICE_LIST.lock();
)?; // // dev.0 = response.epoch;
{ // // dev.1 = ip_list;
let ip_list = response // // }
.device_info_list // // let virtual_ip = Ipv4Addr::from(response.virtual_ip);
.into_iter() // // let virtual_gateway = Ipv4Addr::from(response.virtual_gateway);
.map(|info| { // // let virtual_netmask = Ipv4Addr::from(response.virtual_netmask);
PeerDeviceInfo::new( // // let (status_sender, status_receiver) = watch::channel(ApplicationStatus::Starting);
Ipv4Addr::from(info.virtual_ip), // // let current_device =
info.name, // // CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, server_address);
info.device_status as u8, // // let wait_group = WaitGroup::new();
) // // let status_sender = Arc::new(parking_lot::const_mutex(status_sender));
}) // // let call = Arc::new(AtomicCell::new(Some(config.abnormal_call)));
.collect(); // // //心跳线程
let mut dev = DEVICE_LIST.lock(); // // {
dev.0 = response.epoch; // // let udp = udp.try_clone()?;
dev.1 = ip_list; // // let wait_group1 = wait_group.clone();
} // // let status_sender1 = status_sender.clone();
let virtual_ip = Ipv4Addr::from(response.virtual_ip); // // let call1 = call.clone();
let virtual_gateway = Ipv4Addr::from(response.virtual_gateway); // // handle::heartbeat_handler::start(
let virtual_netmask = Ipv4Addr::from(response.virtual_netmask); // // status_receiver.clone(),
let (status_sender, status_receiver) = watch::channel(ApplicationStatus::Starting); // // udp,
let current_device = // // current_device,
CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, server_address); // // move || {
let wait_group = WaitGroup::new(); // // if Self::call_stop(status_sender1) {
let status_sender = Arc::new(parking_lot::const_mutex(status_sender)); // // if let Some(call) = call1.take() {
let call = Arc::new(AtomicCell::new(Some(config.abnormal_call))); // // call();
//心跳线程 // // }
{ // // }
let udp = udp.try_clone()?; // // drop(wait_group1);
let wait_group1 = wait_group.clone(); // // },
let status_sender1 = status_sender.clone(); // // )
let call1 = call.clone(); // // .await;
handle::heartbeat_handler::start( // // }
status_receiver.clone(), // // //初始化nat数据
udp, // // handle::init_nat_test_addr(config.nat_test_server);
current_device, // // handle::init_nat_info(response.public_ip, response.public_port as u16);
move || { // // // tun服务
if Self::call_stop(status_sender1) { // // let (tun_writer, tun_reader) =
if let Some(call) = call1.take() { // // tun_device::create_tun(virtual_ip, virtual_netmask, virtual_gateway)?;
call(); // // // 打洞数据通道
} // // let (punch_sender, cone_receiver, req_symmetric_receiver, res_symmetric_receiver) =
} // // handle::punch_handler::bounded();
drop(wait_group1); // // //udp数据处理
}, // // {
) // // // 低优先级的udp数据通道
.await; // // let (sender, receiver) = tokio::sync::mpsc::channel(50);
} // // let udp1 = udp.try_clone()?;
//初始化nat数据 // // let wait_group1 = wait_group.clone();
handle::init_nat_test_addr(config.nat_test_server); // // let status_sender1 = status_sender.clone();
handle::init_nat_info(response.public_ip, response.public_port as u16); // // let call1 = call.clone();
// tun服务 // // handle::udp_recv_handler::udp_recv_start(
let (tun_writer, tun_reader) = // // status_receiver.clone(),
tun_device::create_tun(virtual_ip, virtual_netmask, virtual_gateway)?; // // udp1,
// 打洞数据通道 // // server_address,
let (punch_sender, cone_receiver, req_symmetric_receiver, res_symmetric_receiver) = // // sender,
handle::punch_handler::bounded(); // // tun_writer,
//udp数据处理 // // current_device,
{ // // move || {
// 低优先级的udp数据通道 // // if Self::call_stop(status_sender1) {
let (sender, receiver) = tokio::sync::mpsc::channel(50); // // if let Some(call) = call1.take() {
let udp1 = udp.try_clone()?; // // call();
let wait_group1 = wait_group.clone(); // // }
let status_sender1 = status_sender.clone(); // // }
let call1 = call.clone(); // // drop(wait_group1);
handle::udp_recv_handler::udp_recv_start( // // },
status_receiver.clone(), // // )
udp1, // // .await;
server_address, // // let udp1 = udp.try_clone()?;
sender, // // let wait_group1 = wait_group.clone();
tun_writer, // // let status_sender1 = status_sender.clone();
current_device, // // let call1 = call.clone();
move || { // // handle::udp_recv_handler::udp_other_recv_start(
if Self::call_stop(status_sender1) { // // status_receiver.clone(),
if let Some(call) = call1.take() { // // udp1,
call(); // // receiver,
} // // current_device,
} // // punch_sender,
drop(wait_group1); // // move || {
}, // // if Self::call_stop(status_sender1) {
) // // if let Some(call) = call1.take() {
.await; // // call();
let udp1 = udp.try_clone()?; // // }
let wait_group1 = wait_group.clone(); // // }
let status_sender1 = status_sender.clone(); // // drop(wait_group1);
let call1 = call.clone(); // // },
handle::udp_recv_handler::udp_other_recv_start( // // )
status_receiver.clone(), // // .await;
udp1, // // }
receiver, // // //打洞处理
current_device, // // {
punch_sender, // // let udp1 = udp.try_clone()?;
move || { // // let wait_group1 = wait_group.clone();
if Self::call_stop(status_sender1) { // // let status_sender1 = status_sender.clone();
if let Some(call) = call1.take() { // // let call1 = call.clone();
call(); // // handle::punch_handler::cone_handler_start(
} // // status_receiver.clone(),
} // // cone_receiver,
drop(wait_group1); // // udp1,
}, // // current_device,
) // // move || {
.await; // // if Self::call_stop(status_sender1) {
} // // if let Some(call) = call1.take() {
//打洞处理 // // call();
{ // // }
let udp1 = udp.try_clone()?; // // }
let wait_group1 = wait_group.clone(); // // drop(wait_group1);
let status_sender1 = status_sender.clone(); // // },
let call1 = call.clone(); // // )
handle::punch_handler::cone_handler_start( // // .await;
status_receiver.clone(), // // let udp1 = udp.try_clone()?;
cone_receiver, // // let wait_group1 = wait_group.clone();
udp1, // // let status_sender1 = status_sender.clone();
current_device, // // let call1 = call.clone();
move || { // // handle::punch_handler::req_symmetric_handler_start(
if Self::call_stop(status_sender1) { // // status_receiver.clone(),
if let Some(call) = call1.take() { // // req_symmetric_receiver,
call(); // // udp1,
} // // current_device,
} // // move || {
drop(wait_group1); // // if Self::call_stop(status_sender1) {
}, // // if let Some(call) = call1.take() {
) // // call();
.await; // // }
let udp1 = udp.try_clone()?; // // }
let wait_group1 = wait_group.clone(); // // drop(wait_group1);
let status_sender1 = status_sender.clone(); // // },
let call1 = call.clone(); // // )
handle::punch_handler::req_symmetric_handler_start( // // .await;
status_receiver.clone(), // // let udp1 = udp.try_clone()?;
req_symmetric_receiver, // // let wait_group1 = wait_group.clone();
udp1, // // let status_sender1 = status_sender.clone();
current_device, // // let call1 = call.clone();
move || { // // handle::punch_handler::res_symmetric_handler_start(
if Self::call_stop(status_sender1) { // // status_receiver.clone(),
if let Some(call) = call1.take() { // // res_symmetric_receiver,
call(); // // udp1,
} // // current_device,
} // // move || {
drop(wait_group1); // // if Self::call_stop(status_sender1) {
}, // // if let Some(call) = call1.take() {
) // // call();
.await; // // }
let udp1 = udp.try_clone()?; // // }
let wait_group1 = wait_group.clone(); // // drop(wait_group1);
let status_sender1 = status_sender.clone(); // // },
let call1 = call.clone(); // // )
handle::punch_handler::res_symmetric_handler_start( // // .await;
status_receiver.clone(), // // }
res_symmetric_receiver, // // //tun数据处理
udp1, // // {
current_device, // // let wait_group1 = wait_group.clone();
move || { // // let status_sender1 = status_sender.clone();
if Self::call_stop(status_sender1) { // // let call1 = call.clone();
if let Some(call) = call1.take() { // // handle::tun_handler::handler_start(
call(); // // status_receiver.clone(),
} // // udp,
} // // tun_reader,
drop(wait_group1); // // current_device,
}, // // move || {
) // // if Self::call_stop(status_sender1) {
.await; // // if let Some(call) = call1.take() {
} // // call();
//tun数据处理 // // }
{ // // }
let wait_group1 = wait_group.clone(); // // drop(wait_group1);
let status_sender1 = status_sender.clone(); // // },
let call1 = call.clone(); // // )
handle::tun_handler::handler_start( // // .await;
status_receiver.clone(), // // }
udp, // // Ok(Switch {
tun_reader, // // current_device,
current_device, // // status_sender,
move || { // // wait_group,
if Self::call_stop(status_sender1) { // // runtime: None,
if let Some(call) = call1.take() { // // })
call(); // // }
} // }
}
drop(wait_group1);
},
)
.await;
}
Ok(Switch {
current_device,
status_sender,
wait_group,
runtime: None,
})
}
}
+1 -5
View File
@@ -2,8 +2,8 @@ use std::collections::HashSet;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket}; use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use std::time::Duration; use std::time::Duration;
use std::{io, thread}; use std::{io, thread};
use nat_traversal::punch::NatType;
use crate::proto::message::NatType;
// #[derive(Debug, Copy, Clone, PartialEq)] // #[derive(Debug, Copy, Clone, PartialEq)]
// pub enum NatType { // pub enum NatType {
@@ -79,9 +79,6 @@ pub fn public_ip_list_(
for addr in addrs { for addr in addrs {
let _ = udp.send_to(b"NatTest", addr)?; let _ = udp.send_to(b"NatTest", addr)?;
} }
// let _ = udp.send_to(b"NatTest", "nat1.wherewego.top:35062")?;
// let _ = udp.send_to(b"NatTest", "nat2.wherewego.top:35061")?;
// let _ = udp.send_to(b"NatTest", "nat2.wherewego.top:35062")?;
let mut hash_set = HashSet::new(); let mut hash_set = HashSet::new();
let mut count = 0; let mut count = 0;
let mut min_port = 65535; let mut min_port = 65535;
@@ -99,7 +96,6 @@ pub fn public_ip_list_(
max_port = port; max_port = port;
} }
let ip = Ipv4Addr::new(buf[10], buf[11], buf[12], buf[13]); let ip = Ipv4Addr::new(buf[10], buf[11], buf[12], buf[13]);
// println!("pub {:?}:{}", ip, port);
hash_set.insert(ip); hash_set.insert(ip);
count += 1; count += 1;
} }
+77
View File
@@ -1 +1,78 @@
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::Arc;
use parking_lot::Mutex;
use nat_traversal::punch::{NatInfo, NatType};
use crate::proto::message::PunchNatType;
pub mod check; pub mod check;
#[derive(Clone)]
pub struct NatTest {
nat_test_server: Arc<Vec<SocketAddr>>,
info: Arc<Mutex<NatInfo>>,
}
impl From<NatType> for PunchNatType {
fn from(value: NatType) -> Self {
match value {
NatType::Symmetric => PunchNatType::Symmetric,
NatType::Cone => PunchNatType::Cone
}
}
}
impl Into<NatType> for PunchNatType {
fn into(self) -> NatType {
match self {
PunchNatType::Symmetric => NatType::Symmetric,
PunchNatType::Cone => NatType::Cone
}
}
}
impl NatTest {
pub fn new(nat_test_server: Vec<SocketAddr>, public_ip: Ipv4Addr, public_port: u16, local_ip: IpAddr, local_port: u16) -> NatTest {
let info = NatTest::re_test_(&nat_test_server, public_ip, public_port, local_ip, local_port);
NatTest {
nat_test_server: Arc::new(nat_test_server),
info: Arc::new(Mutex::new(info)),
}
}
pub fn nat_info(&self) -> NatInfo {
self.info.lock().clone()
}
pub fn re_test(&self, public_ip: Ipv4Addr, public_port: u16, local_ip: IpAddr, local_port: u16) -> NatInfo {
let info = NatTest::re_test_(&self.nat_test_server, public_ip, public_port, local_ip, local_port);
*self.info.lock() = info.clone();
info
}
fn re_test_(nat_test_server: &Vec<SocketAddr>, public_ip: Ipv4Addr, public_port: u16, local_ip: IpAddr, local_port: u16) -> NatInfo {
return match check::public_ip_list(nat_test_server) {
Ok((nat_type, ips, port_range)) => {
let mut public_ips = Vec::new();
public_ips.push(IpAddr::from(public_ip));
for ip in ips {
if ip != public_ip {
public_ips.push(IpAddr::from(ip));
}
}
NatInfo::new(public_ips,
public_port,
port_range,
local_ip, local_port,
nat_type, )
}
Err(e) => {
log::warn!("{:?}",e);
NatInfo::new(
vec![IpAddr::from(public_ip)],
public_port,
0,
local_ip, local_port,
NatType::Cone,
)
}
};
}
}
+130 -112
View File
@@ -31,8 +31,8 @@ pub struct RegistrationRequest {
// message fields // message fields
// @@protoc_insertion_point(field:RegistrationRequest.token) // @@protoc_insertion_point(field:RegistrationRequest.token)
pub token: ::std::string::String, pub token: ::std::string::String,
// @@protoc_insertion_point(field:RegistrationRequest.mac_address) // @@protoc_insertion_point(field:RegistrationRequest.device_id)
pub mac_address: ::std::string::String, pub device_id: ::std::string::String,
// @@protoc_insertion_point(field:RegistrationRequest.name) // @@protoc_insertion_point(field:RegistrationRequest.name)
pub name: ::std::string::String, pub name: ::std::string::String,
// @@protoc_insertion_point(field:RegistrationRequest.is_fast) // @@protoc_insertion_point(field:RegistrationRequest.is_fast)
@@ -62,9 +62,9 @@ impl RegistrationRequest {
|m: &mut RegistrationRequest| { &mut m.token }, |m: &mut RegistrationRequest| { &mut m.token },
)); ));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"mac_address", "device_id",
|m: &RegistrationRequest| { &m.mac_address }, |m: &RegistrationRequest| { &m.device_id },
|m: &mut RegistrationRequest| { &mut m.mac_address }, |m: &mut RegistrationRequest| { &mut m.device_id },
)); ));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"name", "name",
@@ -98,7 +98,7 @@ impl ::protobuf::Message for RegistrationRequest {
self.token = is.read_string()?; self.token = is.read_string()?;
}, },
18 => { 18 => {
self.mac_address = is.read_string()?; self.device_id = is.read_string()?;
}, },
26 => { 26 => {
self.name = is.read_string()?; self.name = is.read_string()?;
@@ -121,8 +121,8 @@ impl ::protobuf::Message for RegistrationRequest {
if !self.token.is_empty() { if !self.token.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.token); my_size += ::protobuf::rt::string_size(1, &self.token);
} }
if !self.mac_address.is_empty() { if !self.device_id.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.mac_address); my_size += ::protobuf::rt::string_size(2, &self.device_id);
} }
if !self.name.is_empty() { if !self.name.is_empty() {
my_size += ::protobuf::rt::string_size(3, &self.name); my_size += ::protobuf::rt::string_size(3, &self.name);
@@ -139,8 +139,8 @@ impl ::protobuf::Message for RegistrationRequest {
if !self.token.is_empty() { if !self.token.is_empty() {
os.write_string(1, &self.token)?; os.write_string(1, &self.token)?;
} }
if !self.mac_address.is_empty() { if !self.device_id.is_empty() {
os.write_string(2, &self.mac_address)?; os.write_string(2, &self.device_id)?;
} }
if !self.name.is_empty() { if !self.name.is_empty() {
os.write_string(3, &self.name)?; os.write_string(3, &self.name)?;
@@ -166,7 +166,7 @@ impl ::protobuf::Message for RegistrationRequest {
fn clear(&mut self) { fn clear(&mut self) {
self.token.clear(); self.token.clear();
self.mac_address.clear(); self.device_id.clear();
self.name.clear(); self.name.clear();
self.is_fast = false; self.is_fast = false;
self.special_fields.clear(); self.special_fields.clear();
@@ -175,7 +175,7 @@ impl ::protobuf::Message for RegistrationRequest {
fn default_instance() -> &'static RegistrationRequest { fn default_instance() -> &'static RegistrationRequest {
static instance: RegistrationRequest = RegistrationRequest { static instance: RegistrationRequest = RegistrationRequest {
token: ::std::string::String::new(), token: ::std::string::String::new(),
mac_address: ::std::string::String::new(), device_id: ::std::string::String::new(),
name: ::std::string::String::new(), name: ::std::string::String::new(),
is_fast: false, is_fast: false,
special_fields: ::protobuf::SpecialFields::new(), special_fields: ::protobuf::SpecialFields::new(),
@@ -732,80 +732,87 @@ impl ::protobuf::reflect::ProtobufValue for DeviceList {
} }
#[derive(PartialEq,Clone,Default,Debug)] #[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:Punch) // @@protoc_insertion_point(message:PunchInfo)
pub struct Punch { pub struct PunchInfo {
// message fields // message fields
// @@protoc_insertion_point(field:Punch.virtual_ip) // @@protoc_insertion_point(field:PunchInfo.public_ip_list)
pub virtual_ip: u32,
// @@protoc_insertion_point(field:Punch.public_ip_list)
pub public_ip_list: ::std::vec::Vec<u32>, pub public_ip_list: ::std::vec::Vec<u32>,
// @@protoc_insertion_point(field:Punch.public_port) // @@protoc_insertion_point(field:PunchInfo.public_port)
pub public_port: u32, pub public_port: u32,
// @@protoc_insertion_point(field:Punch.public_port_range) // @@protoc_insertion_point(field:PunchInfo.public_port_range)
pub public_port_range: u32, pub public_port_range: u32,
// @@protoc_insertion_point(field:Punch.nat_type) // @@protoc_insertion_point(field:PunchInfo.nat_type)
pub nat_type: ::protobuf::EnumOrUnknown<NatType>, pub nat_type: ::protobuf::EnumOrUnknown<PunchNatType>,
// @@protoc_insertion_point(field:Punch.reply) // @@protoc_insertion_point(field:PunchInfo.reply)
pub reply: bool, 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,
// special fields // special fields
// @@protoc_insertion_point(special_field:Punch.special_fields) // @@protoc_insertion_point(special_field:PunchInfo.special_fields)
pub special_fields: ::protobuf::SpecialFields, pub special_fields: ::protobuf::SpecialFields,
} }
impl<'a> ::std::default::Default for &'a Punch { impl<'a> ::std::default::Default for &'a PunchInfo {
fn default() -> &'a Punch { fn default() -> &'a PunchInfo {
<Punch as ::protobuf::Message>::default_instance() <PunchInfo as ::protobuf::Message>::default_instance()
} }
} }
impl Punch { impl PunchInfo {
pub fn new() -> Punch { pub fn new() -> PunchInfo {
::std::default::Default::default() ::std::default::Default::default()
} }
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(6); let mut fields = ::std::vec::Vec::with_capacity(7);
let mut oneofs = ::std::vec::Vec::with_capacity(0); let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_ip",
|m: &Punch| { &m.virtual_ip },
|m: &mut Punch| { &mut m.virtual_ip },
));
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>( fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"public_ip_list", "public_ip_list",
|m: &Punch| { &m.public_ip_list }, |m: &PunchInfo| { &m.public_ip_list },
|m: &mut Punch| { &mut m.public_ip_list }, |m: &mut PunchInfo| { &mut m.public_ip_list },
)); ));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_port", "public_port",
|m: &Punch| { &m.public_port }, |m: &PunchInfo| { &m.public_port },
|m: &mut Punch| { &mut m.public_port }, |m: &mut PunchInfo| { &mut m.public_port },
)); ));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_port_range", "public_port_range",
|m: &Punch| { &m.public_port_range }, |m: &PunchInfo| { &m.public_port_range },
|m: &mut Punch| { &mut m.public_port_range }, |m: &mut PunchInfo| { &mut m.public_port_range },
)); ));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"nat_type", "nat_type",
|m: &Punch| { &m.nat_type }, |m: &PunchInfo| { &m.nat_type },
|m: &mut Punch| { &mut m.nat_type }, |m: &mut PunchInfo| { &mut m.nat_type },
)); ));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"reply", "reply",
|m: &Punch| { &m.reply }, |m: &PunchInfo| { &m.reply },
|m: &mut Punch| { &mut m.reply }, |m: &mut PunchInfo| { &mut m.reply },
)); ));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<Punch>( fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"Punch", "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 },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<PunchInfo>(
"PunchInfo",
fields, fields,
oneofs, oneofs,
) )
} }
} }
impl ::protobuf::Message for Punch { impl ::protobuf::Message for PunchInfo {
const NAME: &'static str = "Punch"; const NAME: &'static str = "PunchInfo";
fn is_initialized(&self) -> bool { fn is_initialized(&self) -> bool {
true true
@@ -814,9 +821,6 @@ impl ::protobuf::Message for Punch {
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? { while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag { match tag {
13 => {
self.virtual_ip = is.read_fixed32()?;
},
18 => { 18 => {
is.read_repeated_packed_fixed32_into(&mut self.public_ip_list)?; is.read_repeated_packed_fixed32_into(&mut self.public_ip_list)?;
}, },
@@ -835,6 +839,12 @@ impl ::protobuf::Message for Punch {
48 => { 48 => {
self.reply = is.read_bool()?; self.reply = is.read_bool()?;
}, },
61 => {
self.local_ip = is.read_fixed32()?;
},
64 => {
self.local_port = is.read_uint32()?;
},
tag => { tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
}, },
@@ -847,9 +857,6 @@ impl ::protobuf::Message for Punch {
#[allow(unused_variables)] #[allow(unused_variables)]
fn compute_size(&self) -> u64 { fn compute_size(&self) -> u64 {
let mut my_size = 0; let mut my_size = 0;
if self.virtual_ip != 0 {
my_size += 1 + 4;
}
my_size += 5 * self.public_ip_list.len() as u64; my_size += 5 * self.public_ip_list.len() as u64;
if self.public_port != 0 { if self.public_port != 0 {
my_size += ::protobuf::rt::uint32_size(3, self.public_port); my_size += ::protobuf::rt::uint32_size(3, self.public_port);
@@ -857,21 +864,24 @@ impl ::protobuf::Message for Punch {
if self.public_port_range != 0 { if self.public_port_range != 0 {
my_size += ::protobuf::rt::uint32_size(4, self.public_port_range); my_size += ::protobuf::rt::uint32_size(4, self.public_port_range);
} }
if self.nat_type != ::protobuf::EnumOrUnknown::new(NatType::Symmetric) { if self.nat_type != ::protobuf::EnumOrUnknown::new(PunchNatType::Symmetric) {
my_size += ::protobuf::rt::int32_size(5, self.nat_type.value()); my_size += ::protobuf::rt::int32_size(5, self.nat_type.value());
} }
if self.reply != false { if self.reply != false {
my_size += 1 + 1; 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);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32); self.special_fields.cached_size().set(my_size as u32);
my_size my_size
} }
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { 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)?;
}
for v in &self.public_ip_list { for v in &self.public_ip_list {
os.write_fixed32(2, *v)?; os.write_fixed32(2, *v)?;
}; };
@@ -881,12 +891,18 @@ impl ::protobuf::Message for Punch {
if self.public_port_range != 0 { if self.public_port_range != 0 {
os.write_uint32(4, self.public_port_range)?; os.write_uint32(4, self.public_port_range)?;
} }
if self.nat_type != ::protobuf::EnumOrUnknown::new(NatType::Symmetric) { if self.nat_type != ::protobuf::EnumOrUnknown::new(PunchNatType::Symmetric) {
os.write_enum(5, ::protobuf::EnumOrUnknown::value(&self.nat_type))?; os.write_enum(5, ::protobuf::EnumOrUnknown::value(&self.nat_type))?;
} }
if self.reply != false { if self.reply != false {
os.write_bool(6, self.reply)?; 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)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?; os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(()) ::std::result::Result::Ok(())
} }
@@ -899,85 +915,87 @@ impl ::protobuf::Message for Punch {
&mut self.special_fields &mut self.special_fields
} }
fn new() -> Punch { fn new() -> PunchInfo {
Punch::new() PunchInfo::new()
} }
fn clear(&mut self) { fn clear(&mut self) {
self.virtual_ip = 0;
self.public_ip_list.clear(); self.public_ip_list.clear();
self.public_port = 0; self.public_port = 0;
self.public_port_range = 0; self.public_port_range = 0;
self.nat_type = ::protobuf::EnumOrUnknown::new(NatType::Symmetric); self.nat_type = ::protobuf::EnumOrUnknown::new(PunchNatType::Symmetric);
self.reply = false; self.reply = false;
self.local_ip = 0;
self.local_port = 0;
self.special_fields.clear(); self.special_fields.clear();
} }
fn default_instance() -> &'static Punch { fn default_instance() -> &'static PunchInfo {
static instance: Punch = Punch { static instance: PunchInfo = PunchInfo {
virtual_ip: 0,
public_ip_list: ::std::vec::Vec::new(), public_ip_list: ::std::vec::Vec::new(),
public_port: 0, public_port: 0,
public_port_range: 0, public_port_range: 0,
nat_type: ::protobuf::EnumOrUnknown::from_i32(0), nat_type: ::protobuf::EnumOrUnknown::from_i32(0),
reply: false, reply: false,
local_ip: 0,
local_port: 0,
special_fields: ::protobuf::SpecialFields::new(), special_fields: ::protobuf::SpecialFields::new(),
}; };
&instance &instance
} }
} }
impl ::protobuf::MessageFull for Punch { impl ::protobuf::MessageFull for PunchInfo {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor { fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("Punch").unwrap()).clone() descriptor.get(|| file_descriptor().message_by_package_relative_name("PunchInfo").unwrap()).clone()
} }
} }
impl ::std::fmt::Display for Punch { impl ::std::fmt::Display for PunchInfo {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f) ::protobuf::text_format::fmt(self, f)
} }
} }
impl ::protobuf::reflect::ProtobufValue for Punch { impl ::protobuf::reflect::ProtobufValue for PunchInfo {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>; type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
} }
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)] #[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:NatType) // @@protoc_insertion_point(enum:PunchNatType)
pub enum NatType { pub enum PunchNatType {
// @@protoc_insertion_point(enum_value:NatType.Symmetric) // @@protoc_insertion_point(enum_value:PunchNatType.Symmetric)
Symmetric = 0, Symmetric = 0,
// @@protoc_insertion_point(enum_value:NatType.Cone) // @@protoc_insertion_point(enum_value:PunchNatType.Cone)
Cone = 1, Cone = 1,
} }
impl ::protobuf::Enum for NatType { impl ::protobuf::Enum for PunchNatType {
const NAME: &'static str = "NatType"; const NAME: &'static str = "PunchNatType";
fn value(&self) -> i32 { fn value(&self) -> i32 {
*self as i32 *self as i32
} }
fn from_i32(value: i32) -> ::std::option::Option<NatType> { fn from_i32(value: i32) -> ::std::option::Option<PunchNatType> {
match value { match value {
0 => ::std::option::Option::Some(NatType::Symmetric), 0 => ::std::option::Option::Some(PunchNatType::Symmetric),
1 => ::std::option::Option::Some(NatType::Cone), 1 => ::std::option::Option::Some(PunchNatType::Cone),
_ => ::std::option::Option::None _ => ::std::option::Option::None
} }
} }
const VALUES: &'static [NatType] = &[ const VALUES: &'static [PunchNatType] = &[
NatType::Symmetric, PunchNatType::Symmetric,
NatType::Cone, PunchNatType::Cone,
]; ];
} }
impl ::protobuf::EnumFull for NatType { impl ::protobuf::EnumFull for PunchNatType {
fn enum_descriptor() -> ::protobuf::reflect::EnumDescriptor { fn enum_descriptor() -> ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::Lazy::new(); static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().enum_by_package_relative_name("NatType").unwrap()).clone() descriptor.get(|| file_descriptor().enum_by_package_relative_name("PunchNatType").unwrap()).clone()
} }
fn descriptor(&self) -> ::protobuf::reflect::EnumValueDescriptor { fn descriptor(&self) -> ::protobuf::reflect::EnumValueDescriptor {
@@ -986,41 +1004,41 @@ impl ::protobuf::EnumFull for NatType {
} }
} }
impl ::std::default::Default for NatType { impl ::std::default::Default for PunchNatType {
fn default() -> Self { fn default() -> Self {
NatType::Symmetric PunchNatType::Symmetric
} }
} }
impl NatType { impl PunchNatType {
fn generated_enum_descriptor_data() -> ::protobuf::reflect::GeneratedEnumDescriptorData { fn generated_enum_descriptor_data() -> ::protobuf::reflect::GeneratedEnumDescriptorData {
::protobuf::reflect::GeneratedEnumDescriptorData::new::<NatType>("NatType") ::protobuf::reflect::GeneratedEnumDescriptorData::new::<PunchNatType>("PunchNatType")
} }
} }
static file_descriptor_proto_data: &'static [u8] = b"\ static file_descriptor_proto_data: &'static [u8] = b"\
\n\rmessage.proto\"y\n\x13RegistrationRequest\x12\x14\n\x05token\x18\x01\ \n\rmessage.proto\"u\n\x13RegistrationRequest\x12\x14\n\x05token\x18\x01\
\x20\x01(\tR\x05token\x12\x1f\n\x0bmac_address\x18\x02\x20\x01(\tR\nmacA\ \x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\tR\x08device\
ddress\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\x07is_fas\ Id\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\x07is_fast\
t\x18\x04\x20\x01(\x08R\x06isFast\"\x92\x02\n\x14RegistrationResponse\ \x18\x04\x20\x01(\x08R\x06isFast\"\x92\x02\n\x14RegistrationResponse\x12\
\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvirtualIp\x12'\n\x0fvirtua\ \x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvirtualIp\x12'\n\x0fvirtual_ga\
l_gateway\x18\x02\x20\x01(\x07R\x0evirtualGateway\x12'\n\x0fvirtual_netm\ teway\x18\x02\x20\x01(\x07R\x0evirtualGateway\x12'\n\x0fvirtual_netmask\
ask\x18\x03\x20\x01(\x07R\x0evirtualNetmask\x12\x14\n\x05epoch\x18\x04\ \x18\x03\x20\x01(\x07R\x0evirtualNetmask\x12\x14\n\x05epoch\x18\x04\x20\
\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x05\x20\x03(\x0b2\ \x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x05\x20\x03(\x0b2\x0b.D\
\x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\n\tpublic_ip\x18\x06\x20\x01(\ eviceInfoR\x0edeviceInfoList\x12\x1b\n\tpublic_ip\x18\x06\x20\x01(\x07R\
\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\x20\x01(\rR\npublicPo\ \x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\x20\x01(\rR\npublicPort\"d\
rt\"d\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\ \n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x1d\n\n\
\x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\x12#\n\rdevice_statu\ virtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\x12#\n\rdevice_status\x18\
s\x18\x03\x20\x01(\rR\x0cdeviceStatus\"Y\n\nDeviceList\x12\x14\n\x05epoc\ \x03\x20\x01(\rR\x0cdeviceStatus\"Y\n\nDeviceList\x12\x14\n\x05epoch\x18\
h\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x02\x20\ \x01\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x02\x20\x03(\
\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xd4\x01\n\x05Punch\x12\ \x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xf8\x01\n\tPunchInfo\x12$\n\
\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvirtualIp\x12$\n\x0epublic_ip_\ \x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\n\x0bpu\
list\x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\n\x0bpublic_port\x18\ blic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11public_port_range\
\x03\x20\x01(\rR\npublicPort\x12*\n\x11public_port_range\x18\x04\x20\x01\ \x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_type\x18\x05\x20\
(\rR\x0fpublicPortRange\x12#\n\x08nat_type\x18\x05\x20\x01(\x0e2\x08.Nat\ \x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\x01\
TypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\x01(\x08R\x05reply*\"\n\ (\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\x07R\x07localIp\
\x07NatType\x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06proto\ \x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort*'\n\x0cPunchNatTyp\
3\ e\x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06proto3\
"; ";
/// `FileDescriptorProto` object which was a source for this generated file /// `FileDescriptorProto` object which was a source for this generated file
@@ -1043,9 +1061,9 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
messages.push(RegistrationResponse::generated_message_descriptor_data()); messages.push(RegistrationResponse::generated_message_descriptor_data());
messages.push(DeviceInfo::generated_message_descriptor_data()); messages.push(DeviceInfo::generated_message_descriptor_data());
messages.push(DeviceList::generated_message_descriptor_data()); messages.push(DeviceList::generated_message_descriptor_data());
messages.push(Punch::generated_message_descriptor_data()); messages.push(PunchInfo::generated_message_descriptor_data());
let mut enums = ::std::vec::Vec::with_capacity(1); let mut enums = ::std::vec::Vec::with_capacity(1);
enums.push(NatType::generated_enum_descriptor_data()); enums.push(PunchNatType::generated_enum_descriptor_data());
::protobuf::reflect::GeneratedFileDescriptor::new_generated( ::protobuf::reflect::GeneratedFileDescriptor::new_generated(
file_descriptor_proto(), file_descriptor_proto(),
deps, deps,
+30 -142
View File
@@ -1,13 +1,22 @@
use std::fmt; use std::{fmt, io};
use std::net::Ipv4Addr;
use crate::error::*;
#[derive(Eq, PartialEq, Copy, Clone, Debug)] #[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Protocol { 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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
Ping, Ping,
/// 维持连接,内容同ping
Pong, Pong,
/// 打洞请求
PunchRequest, PunchRequest,
/// 打洞响应
PunchResponse, PunchResponse,
UnKnow(u8), UnKnow(u8),
} }
@@ -39,22 +48,18 @@ impl Into<u8> for Protocol {
pub enum ControlPacket<B> { pub enum ControlPacket<B> {
PingPacket(PingPacket<B>), PingPacket(PingPacket<B>),
PongPacket(PongPacket<B>), PongPacket(PongPacket<B>),
PunchRequest(PunchRequestPacket<B>), PunchRequest,
PunchResponse(PunchResponsePacket<B>), PunchResponse,
} }
impl<B: AsRef<[u8]>> ControlPacket<B> { impl<B: AsRef<[u8]>> ControlPacket<B> {
pub fn new(protocol: u8, buffer: B) -> Result<ControlPacket<B>> { pub fn new(protocol: u8, buffer: B) -> io::Result<ControlPacket<B>> {
match Protocol::from(protocol) { match Protocol::from(protocol) {
Protocol::Ping => Ok(ControlPacket::PingPacket(PingPacket::new(buffer)?)), Protocol::Ping => Ok(ControlPacket::PingPacket(PingPacket::new(buffer)?)),
Protocol::Pong => Ok(ControlPacket::PongPacket(PongPacket::new(buffer)?)), Protocol::Pong => Ok(ControlPacket::PongPacket(PongPacket::new(buffer)?)),
Protocol::PunchRequest => Ok(ControlPacket::PunchRequest(PunchRequestPacket::new( Protocol::PunchRequest => Ok(ControlPacket::PunchRequest),
buffer, Protocol::PunchResponse => Ok(ControlPacket::PunchResponse),
)?)), Protocol::UnKnow(_) => Err(io::Error::new(io::ErrorKind::InvalidData, "Unsupported")),
Protocol::PunchResponse => Ok(ControlPacket::PunchResponse(PunchResponsePacket::new(
buffer,
)?)),
Protocol::UnKnow(_) => Err(Error::NotSupport),
} }
} }
} }
@@ -65,36 +70,33 @@ pub struct PingPacket<B> {
buffer: B, buffer: B,
} }
#[derive(Copy, Clone)] type PongPacket<B> = PingPacket<B>;
pub struct PongPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> PingPacket<B> { impl<B: AsRef<[u8]>> PingPacket<B> {
pub fn new(buffer: B) -> Result<PingPacket<B>> { pub fn new(buffer: B) -> io::Result<PingPacket<B>> {
let len = buffer.as_ref().len(); let len = buffer.as_ref().len();
if len != 8 + 4 { if len != 4 {
return Err(Error::InvalidPacket); return Err(io::Error::new(io::ErrorKind::InvalidData, "len != 4"));
} }
Ok(PingPacket { buffer }) Ok(PingPacket { buffer })
} }
} }
impl<B: AsRef<[u8]>> PingPacket<B> { impl<B: AsRef<[u8]>> PingPacket<B> {
pub fn time(&self) -> i64 { pub fn time(&self) -> u16 {
i64::from_be_bytes(self.buffer.as_ref()[..8].try_into().unwrap()) u16::from_be_bytes(self.buffer.as_ref()[..2].try_into().unwrap())
} }
pub fn epoch(&self) -> u32 { pub fn epoch(&self) -> u16 {
u32::from_be_bytes(self.buffer.as_ref()[8..12].try_into().unwrap()) u16::from_be_bytes(self.buffer.as_ref()[2..4].try_into().unwrap())
} }
} }
impl<B: AsRef<[u8]> + AsMut<[u8]>> PingPacket<B> { impl<B: AsRef<[u8]> + AsMut<[u8]>> PingPacket<B> {
pub fn set_time(&mut self, time: i64) { pub fn set_time(&mut self, time: u16) {
self.buffer.as_mut()[..8].copy_from_slice(&time.to_be_bytes()) self.buffer.as_mut()[..2].copy_from_slice(&time.to_be_bytes())
} }
pub fn set_epoch(&mut self, epoch: u32) { pub fn set_epoch(&mut self, epoch: u16) {
self.buffer.as_mut()[8..12].copy_from_slice(&epoch.to_be_bytes()) self.buffer.as_mut()[2..4].copy_from_slice(&epoch.to_be_bytes())
} }
} }
@@ -106,117 +108,3 @@ impl<B: AsRef<[u8]>> fmt::Debug for PingPacket<B> {
.finish() .finish()
} }
} }
impl<B: AsRef<[u8]>> PongPacket<B> {
pub fn new(buffer: B) -> Result<PongPacket<B>> {
let len = buffer.as_ref().len();
if len != 8 {
return Err(Error::InvalidPacket);
}
Ok(PongPacket { buffer })
}
}
impl<B: AsRef<[u8]>> PongPacket<B> {
pub fn time(&self) -> i64 {
i64::from_be_bytes(self.buffer.as_ref()[..8].try_into().unwrap())
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> PongPacket<B> {
pub fn set_time(&mut self, time: i64) {
self.buffer.as_mut()[..8].copy_from_slice(&time.to_be_bytes())
}
}
impl<B: AsRef<[u8]>> fmt::Debug for PongPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PongPacket")
.field("time", &self.time())
.finish()
}
}
pub type TurnPongPacket<B> = TurnPingPacket<B>;
/// 探测目标延迟
#[derive(Copy, Clone)]
pub struct TurnPingPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> TurnPingPacket<B> {
pub fn new(buffer: B) -> Result<TurnPingPacket<B>> {
let len = buffer.as_ref().len();
if len != 16 {
return Err(Error::InvalidPacket);
}
Ok(TurnPingPacket { buffer })
}
}
impl<B: AsRef<[u8]>> TurnPingPacket<B> {
// pub fn source(&self) -> Ipv4Addr {
// let tmp:[u8;4] = self.buffer.as_ref()[..4].try_into().unwrap();
// Ipv4Addr::from(tmp)
// }
// pub fn destination(&self) -> Ipv4Addr {
// let tmp:[u8;4] = self.buffer.as_ref()[4..8].try_into().unwrap();
// Ipv4Addr::from(tmp)
// }
pub fn time(&self) -> i64 {
i64::from_be_bytes(self.buffer.as_ref()[8..].try_into().unwrap())
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> TurnPingPacket<B> {
pub fn set_source(&mut self, source: Ipv4Addr) {
self.buffer.as_mut()[..4].copy_from_slice(&source.octets());
}
pub fn set_destination(&mut self, destination: Ipv4Addr) {
self.buffer.as_mut()[4..8].copy_from_slice(&destination.octets());
}
pub fn set_time(&mut self, time: i64) {
self.buffer.as_mut()[8..].copy_from_slice(&time.to_be_bytes())
}
}
pub type PunchResponsePacket<B> = PunchPacket<B>;
pub type PunchRequestPacket<B> = PunchPacket<B>;
/// nat穿透
#[derive(Clone)]
pub struct PunchPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> PunchPacket<B> {
pub fn new(buffer: B) -> Result<PunchPacket<B>> {
let len = buffer.as_ref().len();
if len != 8 {
return Err(Error::InvalidPacket);
}
Ok(Self { buffer })
}
}
impl<B: AsRef<[u8]>> PunchPacket<B> {
pub fn source(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[..4].try_into().unwrap();
Ipv4Addr::from(tmp)
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> PunchPacket<B> {
pub fn set_source(&mut self, source: Ipv4Addr) {
self.buffer.as_mut()[..4].copy_from_slice(&source.octets());
}
}
impl<B: AsRef<[u8]>> fmt::Debug for PunchPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PunchPacket")
.field("source", &self.source())
.finish()
}
}
+52 -10
View File
@@ -1,6 +1,19 @@
use std::fmt; use std::{fmt, io};
use std::net::Ipv4Addr;
use crate::error::*; /*
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 版本(8) | 协议(8) | 上层协议(8) | 初始ttl(4) | 生存时间(4) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源ip地址(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 目的ip地址(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据体 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
pub mod control_packet; pub mod control_packet;
pub mod error_packet; pub mod error_packet;
@@ -41,6 +54,7 @@ pub enum Protocol {
Control, Control,
/// 转发ipv4数据 /// 转发ipv4数据
Ipv4Turn, Ipv4Turn,
/// 转发其他数据
OtherTurn, OtherTurn,
UnKnow(u8), UnKnow(u8),
} }
@@ -71,17 +85,19 @@ impl Into<u8> for Protocol {
} }
} }
pub const MAX_TTL: u8 = 0b1111;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct NetPacket<B> { pub struct NetPacket<B> {
buffer: B, buffer: B,
} }
impl<B: AsRef<[u8]>> NetPacket<B> { impl<B: AsRef<[u8]>> NetPacket<B> {
pub fn new(buffer: B) -> Result<NetPacket<B>> { pub fn new(buffer: B) -> io::Result<NetPacket<B>> {
let len = buffer.as_ref().len(); let len = buffer.as_ref().len();
// 不能大于udp最大载荷长度 // 不能大于udp最大载荷长度
if len < 4 || len > 65535 - 20 - 8 { if len < 12 || len > 65535 - 20 - 8 {
return Err(Error::InvalidPacket); return Err(io::Error::new(io::ErrorKind::InvalidData, "length overflow"));
} }
Ok(NetPacket { buffer }) Ok(NetPacket { buffer })
} }
@@ -104,10 +120,21 @@ impl<B: AsRef<[u8]>> NetPacket<B> {
self.buffer.as_ref()[2] self.buffer.as_ref()[2]
} }
pub fn ttl(&self) -> u8 { pub fn ttl(&self) -> u8 {
self.buffer.as_ref()[3] self.buffer.as_ref()[3] & MAX_TTL
}
pub fn source_ttl(&self) -> u8 {
self.buffer.as_ref()[3] >> 4
}
pub fn source(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[4..8].try_into().unwrap();
Ipv4Addr::from(tmp)
}
pub fn destination(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[8..12].try_into().unwrap();
Ipv4Addr::from(tmp)
} }
pub fn payload(&self) -> &[u8] { pub fn payload(&self) -> &[u8] {
&self.buffer.as_ref()[4..] &self.buffer.as_ref()[12..]
} }
} }
@@ -121,14 +148,26 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
pub fn set_transport_protocol(&mut self, transport_protocol: u8) { pub fn set_transport_protocol(&mut self, transport_protocol: u8) {
self.buffer.as_mut()[2] = transport_protocol; self.buffer.as_mut()[2] = transport_protocol;
} }
pub fn first_set_ttl(&mut self, ttl: u8) {
self.buffer.as_mut()[3] = ttl << 4 | ttl;
}
pub fn set_ttl(&mut self, ttl: u8) { pub fn set_ttl(&mut self, ttl: u8) {
self.buffer.as_mut()[3] = ttl; self.buffer.as_mut()[3] = MAX_TTL & ttl;
}
pub fn set_source_ttl(&mut self, source_ttl: u8) {
self.buffer.as_mut()[3] = (source_ttl << 4) | self.buffer.as_ref()[3];
}
pub fn set_source(&mut self, source: Ipv4Addr) {
self.buffer.as_mut()[4..8].copy_from_slice(&source.octets());
}
pub fn set_destination(&mut self, destination: Ipv4Addr) {
self.buffer.as_mut()[8..12].copy_from_slice(&destination.octets());
} }
pub fn set_payload(&mut self, payload: &[u8]) { pub fn set_payload(&mut self, payload: &[u8]) {
self.buffer.as_mut()[4..payload.len() + 4].copy_from_slice(payload); self.buffer.as_mut()[12..payload.len() + 12].copy_from_slice(payload);
} }
pub fn payload_mut(&mut self) -> &mut [u8] { pub fn payload_mut(&mut self) -> &mut [u8] {
&mut self.buffer.as_mut()[4..] &mut self.buffer.as_mut()[12..]
} }
} }
@@ -139,6 +178,9 @@ impl<B: AsRef<[u8]>> fmt::Debug for NetPacket<B> {
.field("protocol", &self.protocol()) .field("protocol", &self.protocol())
.field("transport_protocol", &self.transport_protocol()) .field("transport_protocol", &self.transport_protocol())
.field("ttl", &self.ttl()) .field("ttl", &self.ttl())
.field("source_ttl", &self.source_ttl())
.field("source", &self.source())
.field("destination", &self.destination())
.field("payload", &self.payload()) .field("payload", &self.payload())
.finish() .finish()
} }
+8 -4
View File
@@ -4,8 +4,10 @@ pub enum Protocol {
RegistrationRequest, RegistrationRequest,
/// 注册响应 /// 注册响应
RegistrationResponse, RegistrationResponse,
/// 更新设备列表 /// 拉取设备列表
UpdateDeviceList, PollDeviceList,
/// 推送设备列表
PushDeviceList,
UnKnow(u8), UnKnow(u8),
} }
@@ -14,7 +16,8 @@ impl From<u8> for Protocol {
match value { match value {
1 => Self::RegistrationRequest, 1 => Self::RegistrationRequest,
2 => Self::RegistrationResponse, 2 => Self::RegistrationResponse,
3 => Self::UpdateDeviceList, 3 => Self::PollDeviceList,
4 => Self::PushDeviceList,
val => Self::UnKnow(val), val => Self::UnKnow(val),
} }
} }
@@ -25,7 +28,8 @@ impl Into<u8> for Protocol {
match self { match self {
Self::RegistrationRequest => 1, Self::RegistrationRequest => 1,
Self::RegistrationResponse => 2, Self::RegistrationResponse => 2,
Self::UpdateDeviceList => 3, Self::PollDeviceList => 3,
Self::PushDeviceList => 4,
Self::UnKnow(val) => val, Self::UnKnow(val) => val,
} }
} }
-56
View File
@@ -1,7 +1,4 @@
use std::fmt;
use std::net::Ipv4Addr;
use crate::error::*;
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Protocol { pub enum Protocol {
@@ -26,56 +23,3 @@ impl Into<u8> for Protocol {
} }
} }
} }
pub struct TurnPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> TurnPacket<B> {
pub fn new(buffer: B) -> Result<TurnPacket<B>> {
let len = buffer.as_ref().len();
if len <= 8 {
return Err(Error::InvalidPacket);
}
Ok(Self { buffer })
}
}
impl<B: AsRef<[u8]>> TurnPacket<B> {
pub fn source(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[..4].try_into().unwrap();
Ipv4Addr::from(tmp)
}
pub fn destination(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[4..8].try_into().unwrap();
Ipv4Addr::from(tmp)
}
pub fn payload(&self) -> &[u8] {
&self.buffer.as_ref()[8..]
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> TurnPacket<B> {
pub fn payload_mut(&mut self) -> &mut [u8] {
&mut self.buffer.as_mut()[8..]
}
pub fn set_source(&mut self, source: Ipv4Addr) {
self.buffer.as_mut()[..4].copy_from_slice(&source.octets());
}
pub fn set_destination(&mut self, destination: Ipv4Addr) {
self.buffer.as_mut()[4..8].copy_from_slice(&destination.octets());
}
pub fn set_payload(&mut self, payload: &[u8]) {
self.buffer.as_mut()[8..payload.len() + 8].copy_from_slice(payload)
}
}
impl<B: AsRef<[u8]>> fmt::Debug for TurnPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TurnPacket")
.field("source", &self.source())
.field("destination", &self.destination())
.field("payload", &self.payload())
.finish()
}
}
+57 -20
View File
@@ -5,9 +5,8 @@ use std::sync::Arc;
use libloading::Library; use libloading::Library;
use wintun::{Adapter, Packet, Session}; use wintun::{Adapter, Packet, Session};
use crate::error::*; #[derive(Clone)]
pub struct TunWriter(Arc<Session>, u32);
pub struct TunWriter(Arc<Session>);
impl TunWriter { impl TunWriter {
pub fn write(&self, buf: &[u8]) -> io::Result<()> { pub fn write(&self, buf: &[u8]) -> io::Result<()> {
@@ -21,10 +20,19 @@ impl TunWriter {
} }
return Err(io::Error::new(io::ErrorKind::Other, "send err")); return Err(io::Error::new(io::ErrorKind::Other, "send err"));
} }
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
gateway: Ipv4Addr, old_netmask: Ipv4Addr, old_gateway: Ipv4Addr) -> io::Result<()> {
if let Err(e) = delete_route(self.1, old_netmask, old_gateway) {
log::warn!("{:?}",e);
}
config_ip(self.1, address, netmask, gateway)
}
} }
#[derive(Clone)]
pub struct TunReader(pub(crate) Arc<Session>); pub struct TunReader(pub(crate) Arc<Session>);
impl TunReader { impl TunReader {
pub fn next(&self) -> io::Result<Packet> { pub fn next(&self) -> io::Result<Packet> {
match self.0.receive_blocking() { match self.0.receive_blocking() {
@@ -35,36 +43,46 @@ impl TunReader {
} }
return Err(io::Error::new(io::ErrorKind::Other, "read err")); return Err(io::Error::new(io::ErrorKind::Other, "read err"));
} }
pub fn close(&self) {
self.0.shutdown()
}
} }
pub fn create_tun( pub fn create_tun(
address: Ipv4Addr, address: Ipv4Addr,
netmask: Ipv4Addr, netmask: Ipv4Addr,
gateway: Ipv4Addr, gateway: Ipv4Addr,
) -> Result<(TunWriter, TunReader)> { ) -> io::Result<(TunWriter, TunReader)> {
let win_tun = unsafe { let win_tun = unsafe {
match Library::new("wintun.dll") { match Library::new("wintun.dll") {
Ok(library) => match wintun::load_from_library(library) { Ok(library) => match wintun::load_from_library(library) {
Ok(win_tun) => win_tun, Ok(win_tun) => win_tun,
Err(e) => { Err(e) => {
return Err(Error::Stop(format!("{:?}", e))); return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
} }
}, },
Err(e) => { Err(e) => {
log::error!("wintun.dll not found"); log::error!("wintun.dll not found");
return Err(Error::Stop(format!("wintun.dll not found {:?}", e))); return Err(io::Error::new(io::ErrorKind::Other, format!("wintun.dll not found {:?}", e)));
} }
} }
}; };
let adapter = match Adapter::open(&win_tun, "Switch") { let adapter = match Adapter::open(&win_tun, "Switch-V1") {
Ok(a) => a, Ok(a) => a,
Err(_) => match Adapter::create(&win_tun, "Switch", "Switch", None) { Err(_) => match Adapter::create(&win_tun, "Switch-V1", "Switch-V1", None) {
Ok(adapter) => adapter, Ok(adapter) => adapter,
Err(e) => return Err(Error::Stop(format!("{:?}", e))), Err(e) => return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e))),
}, },
}; };
let index = adapter.get_adapter_index().unwrap(); let index = adapter.get_adapter_index().unwrap();
config_ip(index, address, netmask, gateway)?;
let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap());
let reader_session = session.clone();
Ok((TunWriter(session.clone(), index), TunReader(reader_session)))
}
fn config_ip(index: u32, address: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
let set_mtu = format!( let set_mtu = format!(
"netsh interface ipv4 set subinterface {} mtu=1420 store=persistent", "netsh interface ipv4 set subinterface {} mtu=1420 store=persistent",
index index
@@ -74,9 +92,6 @@ pub fn create_tun(
"netsh interface ip set address {} static {:?} {:?} ", // gateway={:?} "netsh interface ip set address {} static {:?} {:?} ", // gateway={:?}
index, address, netmask, index, address, netmask,
); );
// println!("{}", set_mtu);
// println!("{}", set_metric);
// println!("{}", set_address);
// 执行网卡初始化命令 // 执行网卡初始化命令
let out = std::process::Command::new("cmd") let out = std::process::Command::new("cmd")
.arg("/C") .arg("/C")
@@ -84,7 +99,7 @@ pub fn create_tun(
.output() .output()
.unwrap(); .unwrap();
if !out.status.success() { if !out.status.success() {
return Err(Error::Stop(format!("设置mtu失败:{:?}", out))); return Err(io::Error::new(io::ErrorKind::Other, format!("设置mtu失败: {:?}", out)));
} }
let out = std::process::Command::new("cmd") let out = std::process::Command::new("cmd")
.arg("/C") .arg("/C")
@@ -92,7 +107,7 @@ pub fn create_tun(
.output() .output()
.unwrap(); .unwrap();
if !out.status.success() { if !out.status.success() {
return Err(Error::Stop(format!("设置接口跃点失败:{:?}", out))); return Err(io::Error::new(io::ErrorKind::Other, format!("设置接口跃点失败: {:?}", out)));
} }
let out = std::process::Command::new("cmd") let out = std::process::Command::new("cmd")
.arg("/C") .arg("/C")
@@ -100,7 +115,7 @@ pub fn create_tun(
.output() .output()
.unwrap(); .unwrap();
if !out.status.success() { if !out.status.success() {
return Err(Error::Stop(format!("设置网络地址失败:{:?}", out))); return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: {:?}", out)));
} }
let dest = { let dest = {
let ip = address.octets(); let ip = address.octets();
@@ -116,7 +131,6 @@ pub fn create_tun(
"route add {:?} mask {:?} {:?} if {}", "route add {:?} mask {:?} {:?} if {}",
dest, netmask, gateway, index dest, netmask, gateway, index
); );
// println!("{}", set_route);
// 执行添加路由命令 // 执行添加路由命令
let out = std::process::Command::new("cmd") let out = std::process::Command::new("cmd")
.arg("/C") .arg("/C")
@@ -124,9 +138,32 @@ pub fn create_tun(
.output() .output()
.unwrap(); .unwrap();
if !out.status.success() { if !out.status.success() {
return Err(Error::Stop(format!("添加路由失败:{:?}", out))); return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", out)));
} }
let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap()); Ok(())
let reader_session = session.clone(); }
Ok((TunWriter(session), TunReader(reader_session)))
fn delete_route(index: u32, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
let mask = netmask.octets();
let ip = gateway.octets();
let dest = Ipv4Addr::from([
ip[0] & mask[0],
ip[1] & mask[1],
ip[2] & mask[2],
ip[3] & mask[3],
]);
let delete_route = format!(
"route delete {:?} mask {:?} {:?} if {}",
dest, netmask, gateway, index
);
// 删除路由
let out = std::process::Command::new("cmd")
.arg("/C")
.arg(delete_route)
.output()
.unwrap();
if !out.status.success() {
return Err(io::Error::new(io::ErrorKind::Other, format!("删除路由失败: {:?}", out)));
}
Ok(())
} }