增加国际化输出
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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):"
|
||||
@@ -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):"
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user