支持点对网

This commit is contained in:
lubeilin
2023-05-28 20:28:58 +08:00
parent 94def558fc
commit c412a256b8
27 changed files with 1321 additions and 544 deletions
+9 -11
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
+74 -70
View File
@@ -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);
+89 -87
View File
@@ -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> {
+66 -40
View File
@@ -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() {