支持点对网
This commit is contained in:
@@ -1,19 +1,17 @@
|
||||
use std::io;
|
||||
use crate::config::SWITCH_HOME_PATH;
|
||||
use std::path::PathBuf;
|
||||
use crate::config::get_home;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn log_service_init() -> io::Result<()> {
|
||||
log_init_("switch-service.log")
|
||||
log_init_(crate::config::get_win_server_home().join("switch-service.log"))
|
||||
}
|
||||
|
||||
pub fn log_init() -> io::Result<()> {
|
||||
log_init_("switch-desktop.log")
|
||||
log_init_(get_home().join("switch-desktop.log"))
|
||||
}
|
||||
pub fn log_init_(file_name:&str) -> io::Result<()> {
|
||||
let home = SWITCH_HOME_PATH.lock().clone();
|
||||
let home = if let Some(home) = home {
|
||||
home
|
||||
} else {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "not found"));
|
||||
};
|
||||
|
||||
fn log_init_(file_name: PathBuf) -> io::Result<()> {
|
||||
let stderr = log4rs::append::console::ConsoleAppender::builder()
|
||||
.target(log4rs::append::console::Target::Stderr)
|
||||
.build();
|
||||
@@ -22,7 +20,7 @@ pub fn log_init_(file_name:&str) -> io::Result<()> {
|
||||
.encoder(Box::new(log4rs::encode::pattern::PatternEncoder::new(
|
||||
"{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}\n",
|
||||
)))
|
||||
.build(home.join(file_name))?;
|
||||
.build(file_name)?;
|
||||
match log4rs::Config::builder()
|
||||
.appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile)))
|
||||
.appender(
|
||||
|
||||
+259
-113
@@ -1,7 +1,7 @@
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io;
|
||||
use std::io::{Read, Write};
|
||||
use std::net::{SocketAddr, ToSocketAddrs};
|
||||
use std::net::{Ipv4Addr, SocketAddr, ToSocketAddrs};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
@@ -11,6 +11,14 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::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 {
|
||||
"./".into()
|
||||
}
|
||||
|
||||
pub struct StartConfig {
|
||||
pub tap: bool,
|
||||
@@ -19,27 +27,73 @@ pub struct StartConfig {
|
||||
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,
|
||||
}
|
||||
|
||||
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!("========参数配置========");
|
||||
let args_config = read_config();
|
||||
let tap = start_args.tap.unwrap_or_else(|| {
|
||||
if let Some(c) = &args_config {
|
||||
c.tap
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
let tap = start_args.tap;
|
||||
if tap {
|
||||
println!("use tap");
|
||||
} else {
|
||||
println!("use tun");
|
||||
}
|
||||
if args_config.is_none() && start_args.token.is_none() {
|
||||
if 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();
|
||||
let token = start_args.token.unwrap();
|
||||
if token.is_empty() {
|
||||
return Err("token不能为空(Token cannot be empty)".to_string());
|
||||
}
|
||||
@@ -48,11 +102,6 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
|
||||
}
|
||||
println!("token:{:?}", token);
|
||||
let name = start_args.name.unwrap_or_else(|| {
|
||||
if let Some(c) = &args_config {
|
||||
if !c.name.is_empty() {
|
||||
return c.name.clone();
|
||||
}
|
||||
}
|
||||
os_info::get().to_string()
|
||||
});
|
||||
let name = name.trim();
|
||||
@@ -63,11 +112,6 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
|
||||
};
|
||||
println!("name:{:?}", name);
|
||||
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 {
|
||||
@@ -78,12 +122,27 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
|
||||
return Err("设备id不能为空并且长度不能大于64字符(The device id cannot be empty and the length cannot be greater than 64 characters)".to_string());
|
||||
}
|
||||
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("in_ips 参数错误 示例:--in_ip 192.168.10.0/24,10.26.0.3".to_string());
|
||||
};
|
||||
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("out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5".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:29871".to_string()
|
||||
}).to_socket_addrs() {
|
||||
Ok(mut server) => {
|
||||
@@ -99,11 +158,6 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
|
||||
};
|
||||
println!("中继服务器:{:?}", server);
|
||||
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<_>>();
|
||||
@@ -118,19 +172,128 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
|
||||
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,
|
||||
};
|
||||
println!("========参数配置========");
|
||||
Ok(base_config)
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref CONFIG: Mutex<Option<ArgsConfig>> = Mutex::new(None);
|
||||
pub static ref SWITCH_HOME_PATH: Mutex<Option<PathBuf>> = Mutex::new(None);
|
||||
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 tap = args_config.tap;
|
||||
if tap {
|
||||
println!("use tap");
|
||||
} else {
|
||||
println!("use tun");
|
||||
}
|
||||
let token = args_config.token;
|
||||
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());
|
||||
}
|
||||
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("设备id不能为空并且长度不能大于64字符(The device id cannot be empty and the length cannot be greater than 64 characters)".to_string());
|
||||
}
|
||||
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("in_ips 参数错误 示例:--in_ip 192.168.10.0/24,10.26.0.3".to_string());
|
||||
};
|
||||
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("out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5".to_string());
|
||||
};
|
||||
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("中继服务器地址错误( Relay server address error)".to_string());
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(format!("中继服务器地址错误( 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("NAT检测服务地址错误(NAT detection service address error)".to_string());
|
||||
}
|
||||
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,
|
||||
};
|
||||
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_tap")]
|
||||
#[serde(default = "default_false")]
|
||||
pub tap: bool,
|
||||
#[serde(default = "default_version")]
|
||||
pub version: String,
|
||||
@@ -138,18 +301,22 @@ pub struct ArgsConfig {
|
||||
pub token: String,
|
||||
#[serde(default = "default_str")]
|
||||
pub name: String,
|
||||
pub command_port: Option<u16>,
|
||||
#[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_pid")]
|
||||
pub pid: u32,
|
||||
#[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,
|
||||
}
|
||||
|
||||
fn default_tap() -> bool {
|
||||
fn default_false() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
@@ -169,38 +336,35 @@ 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, ) -> 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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 = SWITCH_HOME_PATH.lock().clone().unwrap().join(".lock");
|
||||
let path = get_home().join(".lock");
|
||||
let file = File::create(path)?;
|
||||
file.sync_all()?;
|
||||
Ok(file)
|
||||
}
|
||||
|
||||
pub fn save_config(config: ArgsConfig) -> io::Result<()> {
|
||||
let config_path = SWITCH_HOME_PATH.lock().clone().unwrap().join("config");
|
||||
save_config_(config, config_path)
|
||||
}
|
||||
|
||||
fn save_config_(config: ArgsConfig, config_path: PathBuf) -> io::Result<()> {
|
||||
let mut config_lock = CONFIG.lock();
|
||||
config_lock.replace(config.clone());
|
||||
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())?;
|
||||
@@ -208,41 +372,25 @@ fn save_config_(config: ArgsConfig, config_path: PathBuf) -> io::Result<()> {
|
||||
}
|
||||
|
||||
pub fn update_pid(pid: u32) -> io::Result<()> {
|
||||
let home_lock = SWITCH_HOME_PATH.lock();
|
||||
if let Some(home) = home_lock.clone() {
|
||||
drop(home_lock);
|
||||
let config_path = home.join("config");
|
||||
if let Some(mut config) = read_config() {
|
||||
config.pid = pid;
|
||||
return save_config_(config, config_path);
|
||||
}
|
||||
}
|
||||
Err(io::Error::new(io::ErrorKind::Other, "not found"))
|
||||
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 home = SWITCH_HOME_PATH.lock().clone().unwrap();
|
||||
let config = read_config_(home)?;
|
||||
let config = read_runtime_data()?;
|
||||
Ok(config.pid)
|
||||
}
|
||||
|
||||
pub fn update_command_port(port: u16) -> io::Result<()> {
|
||||
let home_lock = SWITCH_HOME_PATH.lock();
|
||||
if let Some(home) = home_lock.clone() {
|
||||
drop(home_lock);
|
||||
let config_path = home.join("config");
|
||||
if let Some(mut config) = read_config() {
|
||||
config.command_port = Some(port);
|
||||
return save_config_(config, config_path);
|
||||
}
|
||||
}
|
||||
Err(io::Error::new(io::ErrorKind::Other, "not found"))
|
||||
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 home = SWITCH_HOME_PATH.lock().clone().unwrap();
|
||||
let config = read_config_(home)?;
|
||||
let config = read_runtime_data()?;
|
||||
if let Some(p) = config.command_port {
|
||||
Ok(p)
|
||||
} else {
|
||||
@@ -250,37 +398,22 @@ pub fn read_command_port() -> io::Result<u16> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_config() -> Option<ArgsConfig> {
|
||||
let mut lock = CONFIG.lock();
|
||||
let c = lock.clone();
|
||||
if c.is_some() {
|
||||
return c;
|
||||
}
|
||||
if let Some(home) = SWITCH_HOME_PATH.lock().clone() {
|
||||
match read_config_(home.to_path_buf()) {
|
||||
Ok(config) => {
|
||||
lock.replace(config.clone());
|
||||
Some(config)
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?},path:{:?}", e,home);
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_home(home: PathBuf) {
|
||||
pub fn get_home() -> PathBuf {
|
||||
let home = dirs::home_dir().unwrap().join(".switch_desktop");
|
||||
if !home.exists() {
|
||||
std::fs::create_dir(&home).unwrap();
|
||||
}
|
||||
SWITCH_HOME_PATH.lock().replace(home);
|
||||
home
|
||||
}
|
||||
|
||||
fn read_config_(home: PathBuf) -> io::Result<ArgsConfig> {
|
||||
let config_path = home.join("config");
|
||||
pub fn get_runtime_data_path() -> PathBuf {
|
||||
let home = get_home();
|
||||
home.join("config")
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -288,6 +421,19 @@ fn read_config_(home: PathBuf) -> io::Result<ArgsConfig> {
|
||||
};
|
||||
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) => {
|
||||
@@ -295,4 +441,4 @@ fn read_config_(home: PathBuf) -> io::Result<ArgsConfig> {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "config error"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-10
@@ -97,7 +97,18 @@ pub struct StartArgs {
|
||||
log: bool,
|
||||
/// 使用tap网卡
|
||||
#[arg(long)]
|
||||
tap: Option<bool>,
|
||||
tap: bool,
|
||||
/// 配置点对网时使用,--in-ip 192.168.10.0/24,10.26.0.3,表示允许接收网段192.168.10.0/24的数据并转发到10.26.0.3
|
||||
/// Use when configuring peer-to-peer networks
|
||||
#[arg(long)]
|
||||
in_ip:Option<Vec<String>>,
|
||||
/// 配置点对网时使用,--out-ip 192.168.10.0/24,192.168.1.10,表示允许目标为192.168.10.0/24的数据从网卡192.168.1.10转发出去
|
||||
/// Use when configuring peer-to-peer networks
|
||||
#[arg(long)]
|
||||
out_ip:Option<Vec<String>>,
|
||||
/// 读取配置文件 --config config_file_path
|
||||
/// Read configuration file
|
||||
config:Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
@@ -124,28 +135,27 @@ pub struct ConfigArgs {
|
||||
|
||||
|
||||
#[cfg(windows)]
|
||||
fn main() {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let args: Vec<_> = std::env::args().collect();
|
||||
if args.len() == 3 && args[1] == windows::SERVICE_FLAG {
|
||||
//以服务的方式启动
|
||||
config::set_home(std::path::PathBuf::from(&args[2]));
|
||||
windows::service::start();
|
||||
return;
|
||||
} else {
|
||||
let home = dirs::home_dir().unwrap().join(".switch_desktop");
|
||||
config::set_home(home);
|
||||
let args = BaseArgs::parse();
|
||||
if let Commands::Start(start_args) = &args.command {
|
||||
if start_args.log {
|
||||
let _ = log_init();
|
||||
}
|
||||
}
|
||||
windows::main0(args);
|
||||
windows::main0(args).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
fn main() {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
if sudo::RunningAs::Root != sudo::check() {
|
||||
println!(
|
||||
"{}",
|
||||
@@ -154,14 +164,12 @@ fn main() {
|
||||
sudo::escalate_if_needed().unwrap();
|
||||
}
|
||||
let args = BaseArgs::parse();
|
||||
let home = dirs::home_dir().unwrap().join(".switch_desktop");
|
||||
config::set_home(home);
|
||||
if let Commands::Start(start_args) = &args.command {
|
||||
if start_args.log {
|
||||
let _ = log_init();
|
||||
}
|
||||
}
|
||||
unix::main0(args);
|
||||
unix::main0(args).await;
|
||||
}
|
||||
|
||||
pub fn console_listen(switch: &Switch) {
|
||||
|
||||
@@ -9,87 +9,91 @@ use crate::{BaseArgs, Commands, config};
|
||||
use crate::command::{command, CommandEnum};
|
||||
|
||||
|
||||
pub fn main0(base_args: BaseArgs) {
|
||||
pub async fn main0(base_args: BaseArgs) {
|
||||
match base_args.command {
|
||||
Commands::Start(args) => {
|
||||
let off_command_server = args.off_command_server;
|
||||
match config::default_config(args) {
|
||||
Ok(start_config) => {
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token.clone(),
|
||||
start_config.device_id.clone(),
|
||||
start_config.name.clone(),
|
||||
start_config.server,
|
||||
start_config.nat_test_server.clone(),
|
||||
);
|
||||
let args_config = config::ArgsConfig::new(
|
||||
start_config.tap,
|
||||
start_config.token.clone(),
|
||||
start_config.name.clone(),
|
||||
start_config.server,
|
||||
&start_config.nat_test_server,
|
||||
start_config.device_id.clone(),
|
||||
);
|
||||
let lock = match config::lock_file() {
|
||||
Ok(lock) => {
|
||||
lock
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}",e);
|
||||
println!("文件锁定失败:{:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if lock.try_lock_exclusive().is_err() {
|
||||
println!("{}", style("文件被重复打开").red());
|
||||
let start_config = if let Some(config_path) = &args.config {
|
||||
match config::read_config_file(config_path.into()) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}", e);
|
||||
return;
|
||||
}
|
||||
if let Err(e) = config::save_config(args_config) {
|
||||
log::error!("{:?}",e);
|
||||
lock.unlock().unwrap();
|
||||
}
|
||||
} else {
|
||||
match config::default_config(args) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}", e);
|
||||
return;
|
||||
}
|
||||
let switch = match Switch::start(config) {
|
||||
Ok(switch) => {
|
||||
switch
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
println!("启动switch失败:{:?}", e);
|
||||
lock.unlock().unwrap();
|
||||
return;
|
||||
}
|
||||
};
|
||||
let switch = Arc::new(switch);
|
||||
let command_server = crate::command::server::CommandServer::new();
|
||||
if off_command_server {
|
||||
crate::console_listen(&switch);
|
||||
log::info!("前台任务结束");
|
||||
} else {
|
||||
if let Err(e) = config::update_pid(std::process::id()) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
let switch1 = switch.clone();
|
||||
let handle = std::thread::Builder::new().name("cmd-server".into()).spawn(move || {
|
||||
if let Err(e) = command_server.start(switch1) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
}).unwrap();
|
||||
crate::console_listen(&switch);
|
||||
if let Err(e) = handle.join() {
|
||||
log::error!("后台任务异常{:?}",e);
|
||||
} else {
|
||||
log::info!("后台任务结束");
|
||||
}
|
||||
}
|
||||
lock.unlock().unwrap();
|
||||
}
|
||||
};
|
||||
let off_command_server = start_config.off_command_server;
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token.clone(),
|
||||
start_config.device_id.clone(),
|
||||
start_config.name.clone(),
|
||||
start_config.server,
|
||||
start_config.nat_test_server.clone(),
|
||||
start_config.in_ips.clone(),
|
||||
start_config.out_ips.clone(),
|
||||
);
|
||||
let lock = match config::lock_file() {
|
||||
Ok(lock) => {
|
||||
lock
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}",e);
|
||||
println!("文件锁定失败:{:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if lock.try_lock_exclusive().is_err() {
|
||||
println!("{}", style("文件被重复打开").red());
|
||||
return;
|
||||
}
|
||||
let switch = match Switch::start(config).await {
|
||||
Ok(switch) => {
|
||||
switch
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
println!("启动switch失败:{:?}", e);
|
||||
lock.unlock().unwrap();
|
||||
return;
|
||||
}
|
||||
};
|
||||
let switch = Arc::new(switch);
|
||||
let command_server = crate::command::server::CommandServer::new();
|
||||
if off_command_server {
|
||||
crate::console_listen(&switch);
|
||||
log::info!("前台任务结束");
|
||||
} else {
|
||||
if let Err(e) = config::update_pid(std::process::id()) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
let switch1 = switch.clone();
|
||||
let handle = std::thread::Builder::new().name("cmd-server".into()).spawn(move || {
|
||||
if let Err(e) = command_server.start(switch1) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
}).unwrap();
|
||||
crate::console_listen(&switch);
|
||||
if let Err(e) = handle.join() {
|
||||
log::error!("后台任务异常{:?}",e);
|
||||
} else {
|
||||
log::info!("后台任务结束");
|
||||
}
|
||||
}
|
||||
lock.unlock().unwrap();
|
||||
}
|
||||
Commands::Stop => {
|
||||
command(CommandEnum::Stop);
|
||||
|
||||
@@ -52,7 +52,7 @@ fn not_started() -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn main0(base_args: BaseArgs) {
|
||||
pub async fn main0(base_args: BaseArgs) {
|
||||
match base_args.command {
|
||||
Commands::Start(args) => {
|
||||
if admin_check() {
|
||||
@@ -62,92 +62,97 @@ pub fn main0(base_args: BaseArgs) {
|
||||
// 允许应用通过防火墙
|
||||
let _udp = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
}
|
||||
let out_log = args.log;
|
||||
match config::default_config(args) {
|
||||
Ok(start_config) => {
|
||||
if let Err(e) = config::save_config(config::ArgsConfig::new(start_config.tap,
|
||||
start_config.token.clone(),
|
||||
start_config.name.clone(),
|
||||
start_config.server,
|
||||
&start_config.nat_test_server,
|
||||
start_config.device_id.clone(),
|
||||
)) {
|
||||
let start_config = if let Some(config_path) = &args.config {
|
||||
match config::read_config_file(config_path.into()) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}",e);
|
||||
log::error!("{:?}", e);
|
||||
return;
|
||||
}
|
||||
match service_state() {
|
||||
Ok(state) => {
|
||||
if state == ServiceState::Stopped {
|
||||
match start(out_log) {
|
||||
Ok(_) => {
|
||||
//需要检查启动状态
|
||||
thread::sleep(Duration::from_secs(2));
|
||||
println!("{}", style("启动成功(Start successfully)").green())
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("服务未停止(Service not stopped)");
|
||||
}
|
||||
} else {
|
||||
match config::default_config(args) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
match service_state() {
|
||||
Ok(state) => {
|
||||
if state == ServiceState::Stopped {
|
||||
match start() {
|
||||
Ok(_) => {
|
||||
//需要检查启动状态
|
||||
thread::sleep(Duration::from_secs(2));
|
||||
println!("{}", style("启动成功(Start successfully)").green())
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
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()
|
||||
);
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token,
|
||||
start_config.device_id,
|
||||
start_config.name,
|
||||
start_config.server,
|
||||
start_config.nat_test_server,
|
||||
);
|
||||
let lock = match config::lock_file() {
|
||||
Ok(lock) => {
|
||||
lock
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("文件锁定失败:{:?}",e);
|
||||
println!("文件锁定失败:{:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if lock.try_lock_exclusive().is_err() {
|
||||
println!("{}", style("文件被重复打开").red());
|
||||
return;
|
||||
}
|
||||
match Switch::start(config) {
|
||||
Ok(switch) => {
|
||||
crate::console_listen(&switch);
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
println!("启动switch失败:{:?}", e);
|
||||
}
|
||||
}
|
||||
lock.unlock().unwrap();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
println!("{:?}", e);
|
||||
}
|
||||
} else {
|
||||
println!("服务未停止(Service not stopped)");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", style(&e).red());
|
||||
log::error!("{:?}", e);
|
||||
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()
|
||||
);
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token,
|
||||
start_config.device_id,
|
||||
start_config.name,
|
||||
start_config.server,
|
||||
start_config.nat_test_server,
|
||||
start_config.in_ips,
|
||||
start_config.out_ips,
|
||||
);
|
||||
let lock = match config::lock_file() {
|
||||
Ok(lock) => {
|
||||
lock
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("文件锁定失败:{:?}",e);
|
||||
println!("文件锁定失败:{:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if lock.try_lock_exclusive().is_err() {
|
||||
println!("{}", style("文件被重复打开").red());
|
||||
return;
|
||||
}
|
||||
match Switch::start(config).await {
|
||||
Ok(switch) => {
|
||||
crate::console_listen(&switch);
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
println!("启动switch失败:{:?}", e);
|
||||
}
|
||||
}
|
||||
lock.unlock().unwrap();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
println!("{:?}", e);
|
||||
}
|
||||
};
|
||||
pause();
|
||||
@@ -259,7 +264,7 @@ fn install(path: PathBuf, auto: bool) -> Result<(), Error> {
|
||||
let mut launch_arguments = Vec::new();
|
||||
launch_arguments.push(OsString::from(SERVICE_FLAG));
|
||||
launch_arguments.push(OsString::from(
|
||||
dirs::home_dir().unwrap().join(".switch").to_str().unwrap(),
|
||||
config::get_home().to_str().unwrap(),
|
||||
));
|
||||
let start_type = if auto {
|
||||
ServiceStartType::AutoStart
|
||||
@@ -298,7 +303,7 @@ fn change(auto: bool) -> Result<(), Error> {
|
||||
let mut launch_arguments = Vec::new();
|
||||
launch_arguments.push(OsString::from(SERVICE_FLAG));
|
||||
launch_arguments.push(OsString::from(
|
||||
dirs::home_dir().unwrap().join(".switch").to_str().unwrap(),
|
||||
config::get_home().to_str().unwrap(),
|
||||
));
|
||||
let service_info = ServiceInfo {
|
||||
name: OsString::from(SERVICE_NAME),
|
||||
@@ -333,15 +338,12 @@ fn uninstall() -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn start(out_log: bool) -> Result<(), Error> {
|
||||
fn start() -> Result<(), Error> {
|
||||
let manager_access = ServiceManagerAccess::CONNECT;
|
||||
let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;
|
||||
let service = service_manager.open_service(SERVICE_NAME, ServiceAccess::START)?;
|
||||
if out_log {
|
||||
service.start(&["log"])
|
||||
} else {
|
||||
service.start(&[""])
|
||||
}
|
||||
let args: Vec<_> = std::env::args().collect();
|
||||
service.start(&args[1..])
|
||||
}
|
||||
|
||||
fn service_state() -> Result<ServiceState, Error> {
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::ffi::OsString;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use clap::Parser;
|
||||
|
||||
use windows_service::{define_windows_service, service_control_handler, service_dispatcher};
|
||||
use windows_service::service::{
|
||||
@@ -14,27 +15,36 @@ use windows_service::service_control_handler::ServiceControlHandlerResult;
|
||||
|
||||
use switch::core::{Config, Switch};
|
||||
|
||||
use crate::{config, StartArgs};
|
||||
use crate::{BaseArgs, Commands, config, StartArgs};
|
||||
use crate::windows::SERVICE_NAME;
|
||||
|
||||
define_windows_service!(ffi_service_main, switch_service_main);
|
||||
pub fn switch_service_main(arguments: Vec<OsString>) {
|
||||
if !arguments.is_empty() {
|
||||
if let Some(str) = arguments[0].to_str() {
|
||||
if str == "log" {
|
||||
let base_args = BaseArgs::parse_from(arguments);
|
||||
match base_args.command {
|
||||
Commands::Start(args) => {
|
||||
if args.log {
|
||||
let _ = config::log_config::log_service_init();
|
||||
}
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
match service_main(args).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::error!("启动服务失败:{:?}",e);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
thread::spawn(|| match service_main() {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn service_main() -> windows_service::Result<()> {
|
||||
async fn service_main(args: StartArgs) -> windows_service::Result<()> {
|
||||
log::error!("service_main:{:?}",args);
|
||||
let parker = crossbeam::sync::Parker::new();
|
||||
let un_parker = parker.unparker().clone();
|
||||
let event_handler = move |control_event| -> ServiceControlHandlerResult {
|
||||
@@ -68,7 +78,7 @@ fn service_main() -> windows_service::Result<()> {
|
||||
wait_hint: Duration::default(),
|
||||
process_id: None,
|
||||
})?;
|
||||
match start_switch() {
|
||||
match start_switch(args).await {
|
||||
Ok(switch) => {
|
||||
parker.park();
|
||||
if let Err(e) = switch.stop() {
|
||||
@@ -90,36 +100,52 @@ fn service_main() -> windows_service::Result<()> {
|
||||
})
|
||||
}
|
||||
|
||||
fn start_switch() -> switch::Result<Arc<Switch>> {
|
||||
match config::default_config(StartArgs::default()) {
|
||||
Ok(start_config) => {
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token,
|
||||
start_config.device_id,
|
||||
start_config.name,
|
||||
start_config.server,
|
||||
start_config.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) = config::update_pid(std::process::id()) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
if let Err(e) = command_server.start(switch1) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
});
|
||||
Ok(switch)
|
||||
async fn start_switch(args: StartArgs) -> switch::Result<Arc<Switch>> {
|
||||
let start_config = if let Some(config_path) = &args.config {
|
||||
match config::read_config_file(config_path.into()) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
return Err(switch::error::Error::Stop(e));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(switch::error::Error::Stop(e));
|
||||
} else {
|
||||
match config::default_config(args) {
|
||||
Ok(start_config) => {
|
||||
start_config
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
return Err(switch::error::Error::Stop(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let config = Config::new(
|
||||
start_config.tap,
|
||||
start_config.token,
|
||||
start_config.device_id,
|
||||
start_config.name,
|
||||
start_config.server,
|
||||
start_config.nat_test_server,
|
||||
start_config.in_ips,
|
||||
start_config.out_ips,
|
||||
);
|
||||
let switch = Switch::start(config).await?;
|
||||
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) = config::update_pid(std::process::id()) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
if let Err(e) = command_server.start(switch1) {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
});
|
||||
Ok(switch)
|
||||
}
|
||||
|
||||
pub fn start() {
|
||||
|
||||
Reference in New Issue
Block a user