增加国际化输出

This commit is contained in:
lubeilin
2023-06-23 15:33:08 +08:00
parent ba2c792e2a
commit 466174ef88
10 changed files with 523 additions and 70 deletions
+2 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "switch-desktop"
version = "1.0.5"
version = "1.0.6"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -16,6 +16,7 @@ log4rs = "1.2.0"
tokio = { version = "1.28.1", features = ["full"] }
chrono = "0.4.23"
rust-i18n = "1.2.2"
serde = "1.0"
serde_yaml = "0.9"
serde_json = "1.0.94"
+49
View File
@@ -0,0 +1,49 @@
switch_about: "A virtual network tool that will obtain an ip after startup. Devices under the same token will form a virtual local area network, and can use ip to communicate directly with each other."
switch_usage: "switch-desktop.exe <COMMAND>"
switch_start_about: "Start switch"
switch_token_help: "Using the same token, you can build a local area network. It is recommended to use a more complex token to avoid connecting to other people's local area network"
switch_name_help: "Give the device a name, the system version information will be used by default"
switch_device_id_help: "The unique identifier of the device, the ip is assigned according to the id, and the MAC address is used by default"
switch_server_help: "Registry and relay server address, public server is used by default"
switch_nat_test_server_help: "NAT detection server addresses, separated by commas"
switch_log_help: "Record the log, the output is in the '${home}/.switch_desktop' directory, it is not recommended to open it for long-term use"
switch_tap_help: "Use tap mode, tun mode will be used by default"
switch_in_ip_help: "Use when configuring point-to-network (IP proxy), --in-ip 192.168.10.0/24,10.26.0.3, which means it is allowed to receive data from the network segment 192.168.10.0/24 and forward it to 10.26.0.3"
switch_out_ip_help: "Use when configuring point-to-network, --out-ip 192.168.10.0/24,192.168.1.10, which means that the data with the target of 192.168.10.0/24 is allowed to be forwarded from the network card 192.168.1.10"
switch_config_help: "Read configuration file"
switch_stop_about: "Stop background service"
switch_route_about: "View route"
switch_list_about: "View device list"
switch_list_all_help: "View full information"
switch_status_about: "View current device information"
switch_install_about: "Install windows service"
switch_path_help: "Service installation path, it is recommended to use an empty directory"
switch_auto_help: "Service starts automatically at boot"
switch_uninstall_about: "Uninstall windows service"
switch_config_about: "Change Windows Service Configuration"
switch_use_admin_print: "Please run with administrator privileges"
switch_use_root_print: "Please run with root privileges"
switch_service_not_start_print: "service not started"
switch_start_successfully_print: "Start successfully"
switch_start_failed_print: "Startup failed"
switch_service_not_stopped_print: "service not stopped"
switch_stopped_print: "stopped"
switch_server_already_installed_print: "service is installed"
switch_repeated_start_print: "cannot be restarted repeatedly"
switch_token_not_found_print: "missing token"
switch_token_cannot_be_empty_print: "token cannot be empty"
switch_token_cannot_exceed_64_print: "token cannot exceed 64 characters"
switch_device_id_is_empty_print: "The device id cannot be empty and the length cannot be greater than 64 characters"
switch_in_ips_example_print: "in_ips Parameter error Example:--in_ip 192.168.10.0/24,10.26.0.3"
switch_out_ips_example_print: "out_ips Parameter error Example:--out_ip 192.168.10.0/24,192.168.0.5"
switch_relay_server_address_error: "Wrong relay server address"
switch_nat_test_server_address_error: "NAT detection service address error"
switch_press_any_key_to_exit: "Press any key to exit"
switch_virtual_ip: "virtual ip"
switch_virtual_gateway: "virtual gateway"
switch_please_enter_the_command: "Please enter the command (Usage: list,route,status,exit,help):"
+49
View File
@@ -0,0 +1,49 @@
switch_about: "一个虚拟网络工具,启动后会获取一个ip,相同token下的设备会组件虚拟局域网,之间可以用ip直接通信"
switch_usage: "switch-desktop.exe <命令>"
switch_start_about: "启动switch"
switch_token_help: "使用相同的token,就能组建一个局域网络,建议使用一个复杂一点的token,避免连到其他人的局域网中"
switch_name_help: "给设备一个名字,默认会使用系统版本信息"
switch_device_id_help: "设备唯一标识符,凭id分配ip,默认使用MAC地址"
switch_server_help: "注册和中继服务器地址,默认使用公共服务器"
switch_nat_test_server_help: "NAT探测服务器地址,使用逗号分隔"
switch_log_help: "记录日志,输出在 '${home}/.switch_desktop' 目录下,长时间使用时不建议开启"
switch_tap_help: "使用tap模式,默认会使用tun模式"
switch_in_ip_help: "配置点对网(IP代理)时使用,--in-ip 192.168.10.0/24,10.26.0.3,表示允许接收网段192.168.10.0/24的数据并转发到10.26.0.3"
switch_out_ip_help: "配置点对网时使用,--out-ip 192.168.10.0/24,192.168.1.10,表示允许目标为192.168.10.0/24的数据从网卡192.168.1.10转发出去"
switch_config_help: "读取配置文件"
switch_stop_about: "停止后台服务"
switch_route_about: "查看路由"
switch_list_about: "查看设备列表"
switch_list_all_help: "查看完整信息"
switch_status_about: "查看当前设备信息"
switch_install_about: "安装Windows服务"
switch_path_help: "服务安装路径,建议使用一个空目录"
switch_auto_help: "服务开机自启动"
switch_uninstall_about: "卸载Windows服务"
switch_config_about: "改变Windows服务配置"
switch_use_admin_print: "请使用管理员权限运行"
switch_use_root_print: "请使用root权限运行"
switch_service_not_start_print: "服务未启动"
switch_start_successfully_print: "启动成功"
switch_start_failed_print: "启动失败"
switch_service_not_stopped_print: "服务未停止"
switch_stopped_print: "已停止"
switch_server_already_installed_print: "服务已经安装"
switch_repeated_start_print: "不能重复启动"
switch_token_not_found_print: "缺少token"
switch_token_cannot_be_empty_print: "token不能为空"
switch_token_cannot_exceed_64_print: "token不能超过64个字符"
switch_device_id_is_empty_print: "设备id不能为空并且长度不能大于64字符"
switch_in_ips_example_print: "in_ips 参数错误 示例:--in_ip 192.168.10.0/24,10.26.0.3"
switch_out_ips_example_print: "out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5"
switch_relay_server_address_error: "中继服务器地址错误"
switch_nat_test_server_address_error: "NAT检测服务地址错误"
switch_press_any_key_to_exit: "按任意键退出"
switch_virtual_ip: "当前虚拟ip(virtual ip)"
switch_virtual_gateway: "虚拟网关(virtual gateway)"
switch_please_enter_the_command: "输入命令 (例如: list,route,status,exit,help):"
+1 -1
View File
@@ -182,7 +182,7 @@ fn command(cmd: &str, switch: &Switch) -> io::Result<String> {
"stopping".to_string()
}
_ => {
format!("command '{}' not fount. \n Try to enter: 'help'\n", cmd)
format!("command '{}' not found. \n Try to enter: 'help'\n", cmd)
}
};
Ok(out_str)
+128
View File
@@ -0,0 +1,128 @@
use clap::{Arg, ArgAction, Command};
use clap::builder::BoolishValueParser;
use crate::i18n::*;
fn common() -> Command {
Command::new("switch-desktop")
.about(switch_about())
// .version(switch_version())
.subcommand_required(true)
.arg_required_else_help(true)
// .author(switch_author())
.override_usage(switch_usage())
.subcommand(
Command::new("start")
.about(switch_start_about())
.arg(
Arg::new("token")
.long("token")
.help(switch_token_help())
.action(ArgAction::Set)
)
.arg(
Arg::new("name")
.long("name")
.help(switch_name_help())
.action(ArgAction::Set)
)
.arg(
Arg::new("device_id")
.long("device-id")
.help(switch_device_id_help())
.action(ArgAction::Set)
).arg(
Arg::new("server")
.long("server")
.help(switch_server_help())
.action(ArgAction::Set)
).arg(
Arg::new("nat_test_server")
.long("nat-test-server")
.help(switch_nat_test_server_help())
.action(ArgAction::Set)
).arg(
Arg::new("log")
.long("log")
.help(switch_log_help())
.action(ArgAction::SetTrue)
.value_parser(BoolishValueParser::new()),
).arg(
Arg::new("tap")
.long("tap")
.help(switch_tap_help())
.action(ArgAction::SetTrue),
).arg(
Arg::new("in_ip")
.long("in-ip")
.help(switch_in_ip_help())
.action(ArgAction::Append)
.num_args(1..),
).arg(
Arg::new("out_ip")
.long("out-ip")
.help(switch_out_ip_help())
.action(ArgAction::Append)
).arg(
Arg::new("config")
.long("config")
.help(switch_config_help())
.action(ArgAction::Set)
)
,
).subcommand(
Command::new("stop")
.about(switch_stop_about()))
.subcommand(
Command::new("route")
.about(switch_route_about()))
.subcommand(Command::new("list")
.about(switch_list_about()).arg(
Arg::new("all")
.long("all")
.short('a')
.help(switch_list_all_help())
.action(ArgAction::SetTrue)
.value_parser(BoolishValueParser::new()), ))
.subcommand(Command::new("status")
.about(switch_status_about()))
}
pub fn check() -> bool {
#[cfg(windows)]
let cmd = common().subcommand(Command::new("install")
.about(switch_install_about())
.arg(
Arg::new("path")
.long("path")
.help(switch_path_help())
.action(ArgAction::Set)
.num_args(1..))
.arg(
Arg::new("auto")
.long("auto")
.help(switch_auto_help())
.action(ArgAction::SetTrue)
.value_parser(BoolishValueParser::new()), ))
.subcommand(Command::new("uninstall")
.about(switch_uninstall_about()))
.subcommand(Command::new("config")
.about(switch_config_about())
.arg(
Arg::new("auto")
.long("auto")
.help(switch_auto_help())
.action(ArgAction::SetTrue)
.value_parser(BoolishValueParser::new()), ));
#[cfg(any(unix))]
let cmd = common();
match cmd.try_get_matches() {
Ok(_) => {
true
}
Err(e) => {
println!("{}", e);
false
}
}
}
+24 -22
View File
@@ -8,7 +8,7 @@ use lazy_static::lazy_static;
use parking_lot::Mutex;
use serde::{Deserialize, Serialize};
use crate::StartArgs;
use crate::{i18n, StartArgs};
pub mod log_config;
lazy_static! {
@@ -25,7 +25,7 @@ pub fn set_win_server_home(home: PathBuf) {
let _ = SWITCH_HOME_PATH.lock().insert(home);
}
#[derive(Clone,Debug)]
#[derive(Clone, Debug)]
pub struct StartConfig {
pub tap: bool,
pub name: String,
@@ -101,14 +101,14 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
println!("use tun");
}
if start_args.token.is_none() {
return Err("找不到token(Token not found)".to_string());
return Err(i18n::switch_token_not_found_print());
}
let token = start_args.token.unwrap();
if token.is_empty() {
return Err("token不能为空(Token cannot be empty)".to_string());
return Err(i18n::switch_token_cannot_be_empty_print());
}
if token.len() > 64 {
return Err("token不能超过64字符(Token cannot exceed 64 characters)".to_string());
return Err(i18n::switch_token_cannot_exceed_64_print());
}
println!("token:{:?}", token);
let name = start_args.name.unwrap_or_else(|| {
@@ -129,7 +129,7 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, 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());
return Err(i18n::switch_device_id_is_empty_print());
}
println!("device_id:{:?}", device_id);
let in_ips = start_args.in_ip.unwrap_or_else(|| {
@@ -142,13 +142,13 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
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());
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("out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5".to_string());
return Err(i18n::switch_out_ips_example_print());
};
@@ -159,11 +159,11 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
if let Some(addr) = server.next() {
addr
} else {
return Err("中继服务器地址错误( Relay server address error)".to_string());
return Err(i18n::switch_relay_server_address_error());
}
}
Err(e) => {
return Err(format!("中继服务器地址错误( Relay server address error) :{:?}", e));
return Err(format!("{} :{:?}",i18n::switch_relay_server_address_error(), e));
}
};
println!("中继服务器:{:?}", server);
@@ -172,7 +172,7 @@ pub fn default_config(start_args: StartArgs) -> Result<StartConfig, 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());
return Err(i18n::switch_nat_test_server_address_error());
}
println!("NAT探测服务器:{:?}", nat_test_server);
let base_config = StartConfig {
@@ -211,10 +211,10 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
}
let token = args_config.token;
if token.is_empty() {
return Err("token不能为空(Token cannot be empty)".to_string());
return Err(i18n::switch_token_cannot_be_empty_print());
}
if token.len() > 64 {
return Err("token不能超过64字符(Token cannot exceed 64 characters)".to_string());
return Err(i18n::switch_token_cannot_exceed_64_print());
}
println!("token:{:?}", token);
let name = args_config.name;
@@ -235,7 +235,7 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, 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());
return Err(i18n::switch_device_id_is_empty_print());
}
println!("device_id:{:?}", device_id);
let in_ips = args_config.in_ips;
@@ -244,13 +244,13 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
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());
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("out_ips 参数错误 示例:--out_ip 192.168.10.0/24,192.168.0.5".to_string());
return Err(i18n::switch_out_ips_example_print());
};
let server = match {
if !args_config.server.is_empty() {
@@ -264,11 +264,11 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
if let Some(addr) = server.next() {
addr
} else {
return Err("中继服务器地址错误( Relay server address error)".to_string());
return Err(i18n::switch_relay_server_address_error());
}
}
Err(e) => {
return Err(format!("中继服务器地址错误( Relay server address error) :{:?}", e));
return Err(format!("{}:{:?}",i18n::switch_relay_server_address_error(), e));
}
};
println!("中继服务器:{:?}", server);
@@ -279,7 +279,7 @@ pub fn read_config_file(config_path: PathBuf) -> Result<StartConfig, String> {
}.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());
return Err(i18n::switch_nat_test_server_address_error());
}
println!("NAT探测服务器:{:?}", nat_test_server);
let base_config = StartConfig {
@@ -332,6 +332,7 @@ pub struct ArgsConfig {
#[serde(default = "default_false")]
pub log: bool,
}
#[cfg(windows)]
impl ArgsConfig {
pub fn new(start_config: StartConfig) -> ArgsConfig {
@@ -343,7 +344,7 @@ impl ArgsConfig {
}).collect::<Vec<String>>();
ArgsConfig {
tap: start_config.tap,
version: "1.0.5".to_string(),
version: "1.0.6".to_string(),
token: start_config.token.to_string(),
name: start_config.name.to_string(),
server: start_config.server.to_string(),
@@ -357,6 +358,7 @@ impl ArgsConfig {
}
}
}
#[cfg(windows)]
fn subnet_mask_to_integer(subnet_mask: u32) -> u8 {
let mut mask_bits = subnet_mask;
@@ -373,7 +375,7 @@ fn default_false() -> bool {
}
fn default_version() -> String {
"1.0".to_string()
"1.0.6".to_string()
}
fn default_str() -> String {
@@ -446,7 +448,7 @@ pub fn read_command_port() -> io::Result<u16> {
if let Some(p) = config.command_port {
Ok(p)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not fount config"))
Err(io::Error::new(io::ErrorKind::Other, "not found config"))
}
}
+211
View File
@@ -0,0 +1,211 @@
#[cfg(target_os = "windows")]
fn get_default_language() -> Option<String> {
use std::process::Command;
use std::str;
let output = Command::new("powershell")
.arg("-Command")
.arg("[System.Globalization.CultureInfo]::CurrentCulture.Name")
.output()
.ok()?;
let language_code = str::from_utf8(&output.stdout)
.ok()?
.trim()
.to_string();
Some(language_code)
}
pub fn init() {
#[cfg(target_os = "windows")]
{
if let Some(l) = get_default_language() {
rust_i18n::set_locale(&l);
}
}
}
pub fn switch_about() -> String {
rust_i18n::t!("switch_about")
}
pub fn switch_usage() -> String {
rust_i18n::t!("switch_usage")
}
pub fn switch_start_about() -> String {
rust_i18n::t!("switch_start_about")
}
pub fn switch_token_help() -> String {
rust_i18n::t!("switch_token_help")
}
pub fn switch_name_help() -> String {
rust_i18n::t!("switch_name_help")
}
pub fn switch_device_id_help() -> String {
rust_i18n::t!("switch_device_id_help")
}
pub fn switch_server_help() -> String {
rust_i18n::t!("switch_server_help")
}
pub fn switch_nat_test_server_help() -> String {
rust_i18n::t!("switch_nat_test_server_help")
}
pub fn switch_log_help() -> String {
rust_i18n::t!("switch_log_help")
}
pub fn switch_tap_help() -> String {
rust_i18n::t!("switch_tap_help")
}
pub fn switch_in_ip_help() -> String {
rust_i18n::t!("switch_in_ip_help")
}
pub fn switch_out_ip_help() -> String {
rust_i18n::t!("switch_out_ip_help")
}
pub fn switch_config_help() -> String {
rust_i18n::t!("switch_config_help")
}
pub fn switch_stop_about() -> String {
rust_i18n::t!("switch_stop_about")
}
pub fn switch_route_about() -> String {
rust_i18n::t!("switch_route_about")
}
pub fn switch_list_about() -> String {
rust_i18n::t!("switch_list_about")
}
pub fn switch_list_all_help() -> String {
rust_i18n::t!("switch_list_all_help")
}
pub fn switch_status_about() -> String {
rust_i18n::t!("switch_status_about")
}
#[cfg(windows)]
pub fn switch_install_about() -> String {
rust_i18n::t!("switch_install_about")
}
#[cfg(windows)]
pub fn switch_path_help() -> String {
rust_i18n::t!("switch_path_help")
}
#[cfg(windows)]
pub fn switch_auto_help() -> String {
rust_i18n::t!("switch_auto_help")
}
#[cfg(windows)]
pub fn switch_uninstall_about() -> String {
rust_i18n::t!("switch_uninstall_about")
}
#[cfg(windows)]
pub fn switch_config_about() -> String {
rust_i18n::t!("switch_config_about")
}
#[cfg(windows)]
pub fn switch_use_root_print() -> String {
rust_i18n::t!("switch_use_admin_print")
}
#[cfg(unix)]
pub fn switch_use_root_print() -> String {
rust_i18n::t!("switch_use_root_print")
}
#[cfg(windows)]
pub fn switch_service_not_start_print() -> String {
rust_i18n::t!("switch_service_not_start_print")
}
pub fn switch_start_successfully_print() -> String {
rust_i18n::t!("switch_start_successfully_print")
}
#[cfg(windows)]
pub fn switch_start_failed_print() -> String {
rust_i18n::t!("switch_start_failed_print")
}
#[cfg(windows)]
pub fn switch_service_not_stopped_print() -> String {
rust_i18n::t!("switch_service_not_stopped_print")
}
#[cfg(windows)]
pub fn switch_server_already_installed_print() -> String {
rust_i18n::t!("switch_server_already_installed_print")
}
pub fn switch_repeated_start_print() -> String {
rust_i18n::t!("switch_repeated_start_print")
}
pub fn switch_stopped_print() -> String {
rust_i18n::t!("switch_stopped_print")
}
pub fn switch_token_not_found_print() -> String {
rust_i18n::t!("switch_token_not_found_print")
}
pub fn switch_token_cannot_be_empty_print() -> String {
rust_i18n::t!("switch_token_cannot_be_empty_print")
}
pub fn switch_token_cannot_exceed_64_print() -> String {
rust_i18n::t!("switch_token_cannot_exceed_64_print")
}
pub fn switch_device_id_is_empty_print() -> String {
rust_i18n::t!("switch_device_id_is_empty_print")
}
pub fn switch_in_ips_example_print() -> String {
rust_i18n::t!("switch_in_ips_example_print")
}
pub fn switch_out_ips_example_print() -> String {
rust_i18n::t!("switch_out_ips_example_print")
}
pub fn switch_relay_server_address_error() -> String {
rust_i18n::t!("switch_relay_server_address_error")
}
pub fn switch_nat_test_server_address_error() -> String {
rust_i18n::t!("switch_nat_test_server_address_error")
}
pub fn switch_press_any_key_to_exit() -> String {
rust_i18n::t!("switch_press_any_key_to_exit")
}
pub fn switch_virtual_ip() -> String {
rust_i18n::t!("switch_virtual_ip")
}
pub fn switch_virtual_gateway() -> String {
rust_i18n::t!("switch_virtual_gateway")
}
pub fn switch_please_enter_the_command() -> String {
rust_i18n::t!("switch_please_enter_the_command")
}
+22 -20
View File
@@ -11,10 +11,11 @@ mod command;
mod config;
#[cfg(target_os = "windows")]
mod windows;
#[cfg(any(unix))]
mod unix;
mod console_out;
mod command_args;
mod i18n;
#[derive(Parser, Debug)]
#[command(
@@ -60,7 +61,7 @@ enum Commands {
Status,
}
#[derive(Parser, Debug,Default)]
#[derive(Parser, Debug, Default)]
pub struct StartArgs {
/// 不超过64个字符
/// 相同token的设备之间才能通信。
@@ -101,15 +102,15 @@ pub struct StartArgs {
/// 配置点对网时使用,--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>>,
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>>,
out_ip: Option<Vec<String>>,
/// 读取配置文件 --config config_file_path
/// Read configuration file
#[arg(long)]
config:Option<String>,
config: Option<String>,
}
#[cfg(target_os = "windows")]
@@ -134,10 +135,14 @@ pub struct ConfigArgs {
auto: bool,
}
#[macro_use]
extern crate rust_i18n;
i18n!("locales", fallback = "en");
#[cfg(windows)]
#[tokio::main]
async fn main() {
fn main() {
i18n::init();
let args: Vec<_> = std::env::args().collect();
if args.len() == 3 && args[1] == windows::SERVICE_FLAG {
//以服务的方式启动
@@ -145,13 +150,16 @@ async fn main() {
windows::service::start();
return;
} else {
if !command_args::check() {
return;
}
let args = BaseArgs::parse();
if let Commands::Start(start_args) = &args.command {
if start_args.log {
let _ = log_init();
}
}
windows::main0(args).await;
windows::main0(args);
}
}
@@ -177,27 +185,21 @@ async fn main() {
pub fn console_listen(switch: &Switch) {
use console::Term;
let term = Term::stdout();
println!("{}", style("启动成功 started").green());
println!("{}", style(i18n::switch_start_successfully_print()).green());
let current_device = switch.current_device();
println!(
"当前虚拟ip(virtual ip): {:?}",
style(current_device.virtual_ip()).green()
);
println!(
"虚拟网关(virtual gateway): {:?}",
style(current_device.virtual_gateway()).green()
);
println!("{}: {:?}", i18n::switch_virtual_ip(), style(current_device.virtual_ip()).green());
println!("{}: {:?}", i18n::switch_virtual_gateway(), style(current_device.virtual_gateway()).green());
loop {
println!(
"{}",
style("Please enter the command (Usage: list,status,exit,help):").color256(102)
style(i18n::switch_please_enter_the_command()).color256(102)
);
match term.read_line() {
Ok(cmd) => {
#[cfg(unix)]
if cmd.is_empty() {
use libc::{STDIN_FILENO, isatty};
if !unsafe { isatty(STDIN_FILENO) != 0 }{
if !unsafe { isatty(STDIN_FILENO) != 0 } {
return;
}
}
@@ -252,7 +254,7 @@ fn command(cmd: &str, switch: &Switch) -> Result<(), ()> {
return Err(());
}
_ => {
println!("command '{}' not fount. ", style(cmd).red());
println!("command '{}' not found. ", style(cmd).red());
println!("Try to enter: '{}'", style("help").green());
}
}
+37 -25
View File
@@ -14,7 +14,7 @@ use windows_service::service_manager::{ServiceManager, ServiceManagerAccess};
use switch::core::{Config, Switch};
use crate::{BaseArgs, Commands, config};
use crate::{BaseArgs, Commands, config, i18n};
use crate::command::{command, CommandEnum};
pub mod service;
@@ -28,7 +28,7 @@ fn admin_check() -> bool {
if !windows_admin_check::is_app_elevated() {
println!(
"{}",
style("请使用管理员权限运行(Please run with administrator privileges)").red()
style(i18n::switch_use_root_print()).red()
);
true
} else {
@@ -42,7 +42,7 @@ fn not_started() -> bool {
if state == ServiceState::Running {
return false;
} else {
println!("服务未启动")
println!("{}",i18n::switch_service_not_start_print())
}
}
Err(e) => {
@@ -52,7 +52,7 @@ fn not_started() -> bool {
return true;
}
pub async fn main0(base_args: BaseArgs) {
pub fn main0(base_args: BaseArgs) {
match base_args.command {
Commands::Start(args) => {
if admin_check() {
@@ -92,15 +92,15 @@ pub async fn main0(base_args: BaseArgs) {
Ok(_) => {
//需要检查启动状态
thread::sleep(Duration::from_secs(2));
println!("{}", style("启动成功(Start successfully)").green());
println!("{}", style(i18n::switch_start_successfully_print()).green());
}
Err(e) => {
log::error!("{:?}", e);
println!("{}:{}", style("启动失败").red(),e);
println!("{}:{}", style(i18n::switch_start_failed_print()).red(), e);
}
}
} else {
println!("服务未停止(Service not stopped)");
println!("{}",i18n::switch_service_not_stopped_print());
}
}
Err(e) => {
@@ -130,18 +130,20 @@ pub async fn main0(base_args: BaseArgs) {
}
};
if lock.try_lock_exclusive().is_err() {
println!("{}", style("文件被重复打开").red());
println!("{}", style(i18n::switch_repeated_start_print()).red());
return;
}
match Switch::start(config).await {
Ok(switch) => {
crate::console_listen(&switch);
tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap().block_on(async move {
match Switch::start(config).await {
Ok(switch) => {
crate::console_listen(&switch);
}
Err(e) => {
log::error!("{:?}", e);
println!("启动switch失败:{:?}", e);
}
}
Err(e) => {
log::error!("{:?}", e);
println!("启动switch失败:{:?}", e);
}
}
});
lock.unlock().unwrap();
return;
}
@@ -163,11 +165,11 @@ pub async fn main0(base_args: BaseArgs) {
}
match stop() {
Ok(_) => {
println!("{}", style("停止成功(Stopped successfully)").green())
println!("{}", style(i18n::switch_stopped_print()).green())
}
Err(e) => {
log::error!("{:?}", e);
println!("停止失败:{}",e);
println!("停止失败:{}", e);
}
}
pause();
@@ -176,6 +178,10 @@ pub async fn main0(base_args: BaseArgs) {
if admin_check() {
return;
}
if service_state().is_ok() {
println!("{}",i18n::switch_server_already_installed_print());
return;
}
let path: PathBuf = args.path.into();
if !path.exists() {
std::fs::create_dir_all(&path).unwrap();
@@ -185,7 +191,7 @@ pub async fn main0(base_args: BaseArgs) {
} else {
if let Err(e) = install(path, args.auto) {
log::error!("{:?}", e);
println!("安装失败:{}",e);
println!("安装失败:{}", e);
} else {
println!("{}", style("安装成功(Installation succeeded)").green())
}
@@ -196,18 +202,24 @@ pub async fn main0(base_args: BaseArgs) {
if admin_check() {
return;
}
if service_state().is_err() {
println!("服务未安装");
}
if let Err(e) = uninstall() {
log::error!("{:?}", e);
println!("卸载失败:{}",e);
println!("卸载失败:{}", e);
} else {
println!("{}", style("卸载成功(Uninstall succeeded)").green())
}
pause();
}
Commands::Config(args) => {
if service_state().is_err() {
println!("服务未安装");
}
if let Err(e) = change(args.auto) {
log::error!("{:?}", e);
println!("配置失败:{}",e);
println!("配置失败:{}", e);
} else {
println!("{}", style("配置成功(Config succeeded)").green())
}
@@ -241,7 +253,7 @@ pub async fn main0(base_args: BaseArgs) {
fn pause() {
println!(
"{}",
style("按任意键退出(Press any key to exit)...").green()
style(i18n::switch_press_any_key_to_exit()).green()
);
use console::Term;
let term = Term::stdout();
@@ -249,7 +261,7 @@ fn pause() {
}
fn install(mut path: PathBuf, auto: bool) -> Result<(), Error> {
if !path.is_absolute(){
if !path.is_absolute() {
path = path.canonicalize().unwrap();
}
let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE;
@@ -259,7 +271,7 @@ fn install(mut path: PathBuf, auto: bool) -> Result<(), Error> {
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 e.kind() == io::ErrorKind::NotFound {
println!("Not fount 'wintun.dll'. Please put 'wintun.dll' in the current directory");
println!("'wintun.dll' not found. Please put 'wintun.dll' in the current directory");
std::process::exit(0);
} else {
panic!("{:?}", e)
@@ -318,7 +330,7 @@ fn change(auto: bool) -> Result<(), Error> {
PathBuf::from(executable_path)
};
let home_path = split.next().unwrap().trim();
let launch_arguments = vec![OsString::from(SERVICE_FLAG),OsString::from(home_path)];
let launch_arguments = vec![OsString::from(SERVICE_FLAG), OsString::from(home_path)];
let service_info = ServiceInfo {
name: OsString::from(SERVICE_NAME),
display_name: config.display_name,
-1
View File
@@ -96,7 +96,6 @@ fn auto_config_path() -> io::Result<PathBuf> {
fn save_auto_config(start_config: config::StartConfig) -> io::Result<()> {
let mut file = std::fs::File::create(auto_config_path()?)?;
log::error!("auto_config_path()? {:?}",auto_config_path()?);
let config = config::ArgsConfig::new(start_config);
match serde_yaml::to_string(&config) {
Ok(yaml) => {