增加桌面端

This commit is contained in:
lubeilin
2023-07-17 01:32:34 +08:00
parent c2b7b02f3f
commit 6b140b0f71
43 changed files with 1038 additions and 2607 deletions
-506
View File
@@ -1,515 +1,9 @@
use std::fs::{File, OpenOptions};
use std::io;
use std::io::{Read, Write};
use std::net::{Ipv4Addr, SocketAddr, ToSocketAddrs};
use std::path::PathBuf;
use lazy_static::lazy_static;
use parking_lot::Mutex;
use serde::{Deserialize, Serialize};
use crate::{i18n, StartArgs};
pub mod log_config;
lazy_static! {
pub static ref SWITCH_HOME_PATH: Mutex<Option<PathBuf>> = Mutex::new(None);
}
#[cfg(windows)]
pub fn get_win_server_home() -> PathBuf {
SWITCH_HOME_PATH.lock().as_ref().unwrap().clone()
}
#[cfg(windows)]
pub fn set_win_server_home(home: PathBuf) {
let _ = SWITCH_HOME_PATH.lock().insert(home);
}
#[derive(Clone, Debug)]
pub struct StartConfig {
pub tap: bool,
pub name: String,
pub token: String,
pub server: SocketAddr,
pub nat_test_server: Vec<SocketAddr>,
pub device_id: String,
pub in_ips: Vec<(u32, u32, Ipv4Addr)>,
pub out_ips: Vec<(u32, u32, Ipv4Addr)>,
#[cfg(any(unix))]
pub off_command_server: bool,
pub log: bool,
pub password: Option<String>,
pub simulate_multicast:bool,
}
fn ips_parse(ips: &Vec<String>) -> Result<Vec<(u32, u32, Ipv4Addr)>, String> {
let mut in_ips_c = vec![];
for x in ips {
let mut split = x.split(",");
let net = if let Some(net) = split.next() {
net
} else {
return Err("参数错误".to_string());
};
let ip = if let Some(ip) = split.next() {
ip
} else {
return Err("参数错误".to_string());
};
let ip = if let Ok(ip) = ip.parse::<Ipv4Addr>() {
ip
} else {
return Err("参数错误".to_string());
};
let mut split = net.split("/");
let dest = if let Some(dest) = split.next() {
dest
} else {
return Err("参数错误".to_string());
};
let mask = if let Some(mask) = split.next() {
mask
} else {
return Err("参数错误".to_string());
};
let dest = if let Ok(dest) = dest.parse::<Ipv4Addr>() {
dest
} else {
return Err("参数错误".to_string());
};
let mask = if let Ok(m) = mask.parse::<u32>() {
let mut mask = 0 as u32;
for i in 0..m {
mask = mask | (1 << (31 - i));
}
mask
} else {
return Err("参数错误".to_string());
};
in_ips_c.push((u32::from_be_bytes(dest.octets()), mask, ip));
}
Ok(in_ips_c)
}
pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
println!("========参数配置========");
if start_args.log {
println!("print log");
}
let tap = start_args.tap;
if tap {
println!("use tap");
} else {
println!("use tun");
}
if start_args.token.is_none() {
return Err(i18n::switch_token_not_found_print());
}
let token = start_args.token.unwrap();
if token.is_empty() {
return Err(i18n::switch_token_cannot_be_empty_print());
}
if token.len() > 64 {
return Err(i18n::switch_token_cannot_exceed_64_print());
}
println!("token:{:?}", token);
let name = start_args.name.unwrap_or_else(|| {
os_info::get().to_string()
});
let name = name.trim();
let name = if name.len() > 64 {
name[..64].to_string()
} else {
name.to_string()
};
println!("name:{:?}", name);
let device_id = start_args.device_id.unwrap_or_else(|| {
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(i18n::switch_device_id_is_empty_print());
}
println!("device_id:{:?}", device_id);
let in_ips = start_args.in_ip.unwrap_or_else(|| {
vec![]
});
let out_ips = start_args.out_ip.unwrap_or_else(|| {
vec![]
});
println!("in_ips:{:?}", in_ips);
let in_ips_c = if let Ok(in_ips_c) = ips_parse(&in_ips) {
in_ips_c
} else {
return Err(i18n::switch_in_ips_example_print());
};
println!("out_ips:{:?}", out_ips);
let out_ips_c = if let Ok(out_ips_c) = ips_parse(&out_ips) {
out_ips_c
} else {
return Err(i18n::switch_out_ips_example_print());
};
let server = match start_args.server.unwrap_or_else(|| {
"nat1.wherewego.top:29871".to_string()
}).to_socket_addrs() {
Ok(mut server) => {
if let Some(addr) = server.next() {
addr
} else {
return Err(i18n::switch_relay_server_address_error());
}
}
Err(e) => {
return Err(format!("{} :{:?}", i18n::switch_relay_server_address_error(), e));
}
};
println!("中继服务器:{:?}", server);
let nat_test_server = start_args.nat_test_server.unwrap_or_else(|| {
"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(i18n::switch_nat_test_server_address_error());
}
println!("NAT探测服务器:{:?}", nat_test_server);
let base_config = StartConfig {
tap,
name,
token,
server,
nat_test_server,
device_id,
in_ips: in_ips_c,
out_ips: out_ips_c,
#[cfg(any(unix))]
off_command_server: start_args.off_command_server,
log: start_args.log,
password: start_args.password,
simulate_multicast:start_args.simulate_multicast,
};
println!("========参数配置========");
Ok(base_config)
}
pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
println!("========读取配置文件========");
let args_config = if let Ok(config) = read_config(config_path) {
config
} else {
return Err("读取配置文件失败".to_string());
};
let log = args_config.log;
if log {
println!("print log");
}
let tap = args_config.tap;
if tap {
println!("use tap");
} else {
println!("use tun");
}
let token = args_config.token;
if token.is_empty() {
return Err(i18n::switch_token_cannot_be_empty_print());
}
if token.len() > 64 {
return Err(i18n::switch_token_cannot_exceed_64_print());
}
println!("token:{:?}", token);
let name = args_config.name;
let name = name.trim();
let name = if name.len() > 64 {
name[..64].to_string()
} else {
name.to_string()
};
println!("name:{:?}", name);
let device_id = if !args_config.device_id.is_empty() {
args_config.device_id
} else {
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(i18n::switch_device_id_is_empty_print());
}
println!("device_id:{:?}", device_id);
let in_ips = args_config.in_ips;
let out_ips = args_config.out_ips;
println!("in_ips:{:?}", in_ips);
let in_ips_c = if let Ok(in_ips_c) = ips_parse(&in_ips) {
in_ips_c
} else {
return Err(i18n::switch_in_ips_example_print());
};
println!("out_ips:{:?}", out_ips);
let out_ips_c = if let Ok(out_ips_c) = ips_parse(&out_ips) {
out_ips_c
} else {
return Err(i18n::switch_out_ips_example_print());
};
let server = match {
if !args_config.server.is_empty() {
args_config.server
} else {
"nat1.wherewego.top:29871".to_string()
}
}.to_socket_addrs()
{
Ok(mut server) => {
if let Some(addr) = server.next() {
addr
} else {
return Err(i18n::switch_relay_server_address_error());
}
}
Err(e) => {
return Err(format!("{}:{:?}", i18n::switch_relay_server_address_error(), e));
}
};
println!("中继服务器:{:?}", server);
let nat_test_server = if args_config.nat_test_server.is_empty() {
vec!["nat1.wherewego.top:35061".to_string(), "nat1.wherewego.top:35062".to_string(), "nat2.wherewego.top:35061".to_string(), "nat2.wherewego.top:35062".to_string()]
} else {
args_config.nat_test_server
}.iter().flat_map(|a| a.to_socket_addrs()).flatten()
.collect::<Vec<_>>();
if nat_test_server.is_empty() {
return Err(i18n::switch_nat_test_server_address_error());
}
println!("NAT探测服务器:{:?}", nat_test_server);
let base_config = StartConfig {
tap,
name,
token,
server,
nat_test_server,
device_id,
in_ips: in_ips_c,
out_ips: out_ips_c,
#[cfg(any(unix))]
off_command_server: args_config.off_command_server,
log,
password:args_config.password,
simulate_multicast:args_config.simulate_multicast
};
println!("========参数配置========");
Ok(base_config)
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RuntimeData {
#[serde(default = "default_pid")]
pub pid: u32,
pub command_port: Option<u16>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ArgsConfig {
#[serde(default = "default_false")]
pub tap: bool,
#[serde(default = "default_version")]
pub version: String,
#[serde(default = "default_str")]
pub token: String,
#[serde(default = "default_str")]
pub name: String,
#[serde(default = "default_str")]
pub server: String,
#[serde(default = "default_vec")]
pub nat_test_server: Vec<String>,
#[serde(default = "default_str")]
pub device_id: String,
#[serde(default = "default_vec")]
pub in_ips: Vec<String>,
#[serde(default = "default_vec")]
pub out_ips: Vec<String>,
#[cfg(any(unix))]
#[serde(default = "default_false")]
pub off_command_server: bool,
#[serde(default = "default_false")]
pub log: bool,
pub password: Option<String>,
#[serde(default = "default_false")]
pub simulate_multicast:bool,
}
#[cfg(windows)]
impl ArgsConfig {
pub fn new(start_config: StartConfig) -> ArgsConfig {
let in_ips = start_config.in_ips.iter().map(|(ip, mask, dest)| {
format!("{}/{},{}", Ipv4Addr::from(*ip), subnet_mask_to_integer(*mask), dest)
}).collect::<Vec<String>>();
let out_ips = start_config.out_ips.iter().map(|(ip, mask, dest)| {
format!("{}/{},{}", Ipv4Addr::from(*ip), subnet_mask_to_integer(*mask), dest)
}).collect::<Vec<String>>();
ArgsConfig {
tap: start_config.tap,
version: "1.0.6".to_string(),
token: start_config.token.to_string(),
name: start_config.name.to_string(),
server: start_config.server.to_string(),
nat_test_server: start_config.nat_test_server.iter().map(|v| v.to_string()).collect(),
device_id: start_config.device_id,
in_ips,
out_ips,
log: start_config.log,
#[cfg(any(unix))]
off_command_server: start_config.off_command_server,
password: start_config.password,
simulate_multicast:start_config.simulate_multicast,
}
}
}
#[cfg(windows)]
fn subnet_mask_to_integer(subnet_mask: u32) -> u8 {
let mut mask_bits = subnet_mask;
let mut num_bits = 0;
while mask_bits != 0 {
num_bits += 1;
mask_bits <<= 1;
}
num_bits as u8
}
fn default_false() -> bool {
false
}
fn default_version() -> String {
"1.0.6".to_string()
}
fn default_str() -> String {
"".to_string()
}
fn default_vec() -> Vec<String> {
vec![]
}
fn default_pid() -> u32 {
0
}
// impl ArgsConfig {
// pub fn new(tap: bool, token: String, name: String, server: SocketAddr,
// nat_test_server: &Vec<SocketAddr>, device_id: String,
// in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>, ) -> Self {
//
// Self {
// tap,
// version: "1.0".to_string(),
// token,
// name,
// command_port: None,
// server: server.to_string(),
// nat_test_server: nat_test_server.iter().map(|v| v.to_string()).collect::<Vec<String>>(),
// device_id,
// pid: 0,
// }
// }
// }
pub fn lock_file() -> io::Result<File> {
let path = get_home().join(".lock");
let file = File::create(path)?;
file.sync_all()?;
Ok(file)
}
fn save_runtime_data(config: RuntimeData) -> io::Result<()> {
let config_path = get_runtime_data_path();
let str = serde_yaml::to_string(&config).unwrap();
let mut file = File::create(config_path)?;
file.write_all(str.as_bytes())?;
file.sync_all()
}
pub fn update_pid(pid: u32) -> io::Result<()> {
let mut config = read_runtime_data()?;
config.pid = pid;
return save_runtime_data(config);
}
#[cfg(any(unix))]
pub fn read_pid() -> io::Result<u32> {
let config = read_runtime_data()?;
Ok(config.pid)
}
pub fn update_command_port(port: u16) -> io::Result<()> {
let mut config = read_runtime_data()?;
config.command_port = Some(port);
return save_runtime_data(config);
}
pub fn read_command_port() -> io::Result<u16> {
let config = read_runtime_data()?;
if let Some(p) = config.command_port {
Ok(p)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not found config"))
}
}
pub fn get_home() -> PathBuf {
#[cfg(windows)]
{
if let Some(path) = SWITCH_HOME_PATH.lock().as_ref() {
return path.clone();
}
}
let home = dirs::home_dir().unwrap().join(".switch_desktop");
if !home.exists() {
std::fs::create_dir(&home).unwrap();
}
home
}
pub fn get_runtime_data_path() -> PathBuf {
let home = get_home();
home.join(".data")
}
fn read_runtime_data() -> io::Result<RuntimeData> {
let config_path = get_runtime_data_path();
let mut file = if config_path.exists() {
File::open(config_path)?
} else {
OpenOptions::new().read(true).write(true).truncate(false).create(true).open(config_path)?
};
let mut str = String::new();
file.read_to_string(&mut str)?;
match serde_yaml::from_str::<RuntimeData>(&str) {
Ok(config) => Ok(config),
Err(e) => {
log::warn!("{:?}", e);
Err(io::Error::new(io::ErrorKind::Other, "config error"))
}
}
}
fn read_config(config_path: PathBuf) -> io::Result<ArgsConfig> {
let mut file = File::open(config_path)?;
let mut str = String::new();
file.read_to_string(&mut str)?;
match serde_yaml::from_str::<ArgsConfig>(&str) {
Ok(config) => Ok(config),
Err(e) => {
log::warn!("{:?}", e);
Err(io::Error::new(io::ErrorKind::Other, "config error"))
}
}
}