This commit is contained in:
lubeilin
2023-03-13 22:11:52 +08:00
parent 5b2c2435d5
commit 6f7992ea9f
46 changed files with 760 additions and 2124 deletions
+2 -2
View File
@@ -23,8 +23,8 @@ crossbeam = "0.8.2"
lazy_static = "1.4.0" lazy_static = "1.4.0"
parking_lot = "0.12.1" parking_lot = "0.12.1"
#parity-tokio-ipc = "0.9.0" fd-lock = "3.0.10"
#futures = "0.3"
os_info = "3.5.1" os_info = "3.5.1"
[target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies] [target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies]
sudo = "0.6.0" sudo = "0.6.0"
+1
View File
@@ -64,6 +64,7 @@ impl CommandClient {
} }
} }
} }
#[cfg(any(unix))]
pub fn stop(&self) -> io::Result<String> { pub fn stop(&self) -> io::Result<String> {
self.udp.send(b"stop")?; self.udp.send(b"stop")?;
let mut buf = [0; 10240]; let mut buf = [0; 10240];
+56
View File
@@ -1,3 +1,59 @@
use std::io;
use console::style;
use crate::console_out;
pub mod client; pub mod client;
pub mod server; pub mod server;
pub mod entity; pub mod entity;
pub enum CommandEnum {
Route,
List,
ListAll,
Status,
#[cfg(any(unix))]
Stop,
}
pub fn command(cmd: CommandEnum) {
if let Err(e) = command_(cmd) {
println!("{}:{:?}", style("连接后台服务错误(Connection background service error)").red(), e);
}
}
fn command_(cmd: CommandEnum) -> io::Result<()> {
match client::CommandClient::new() {
Ok(command_client) => {
match cmd {
CommandEnum::Route => {
let list = command_client.route()?;
console_out::console_route_table(list);
}
CommandEnum::List => {
let list = command_client.list()?;
console_out::console_device_list(list);
}
CommandEnum::ListAll => {
let list = command_client.list()?;
console_out::console_device_list_all(list);
}
CommandEnum::Status => {
let status = command_client.status()?;
console_out::console_status(status);
}
#[cfg(any(unix))]
CommandEnum::Stop => {
command_client.stop()?;
}
}
}
Err(e) => {
log::error!("{:?}",e);
println!(
"{}:{:?}",
style("连接后台服务错误(Connection background service error)").red(), e
);
}
};
Ok(())
}
-1
View File
@@ -2,7 +2,6 @@ use std::io;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket}; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
use std::sync::Arc; use std::sync::Arc;
use console::style;
use switch::core::Switch; use switch::core::Switch;
use crate::command::entity::{DeviceItem, RouteItem, Status}; use crate::command::entity::{DeviceItem, RouteItem, Status};
+14 -28
View File
@@ -1,33 +1,19 @@
use std::io; use std::io;
use std::path::PathBuf; use crate::config::SWITCH_HOME_PATH;
#[cfg(target_os = "windows")]
pub fn log_init_service(home: PathBuf) -> io::Result<()> { pub fn log_service_init() -> io::Result<()> {
if !home.exists() { log_init_("switch-service.log")
std::fs::create_dir(&home)?;
}
let logfile = log4rs::append::file::FileAppender::builder()
// Pattern: https://docs.rs/log4rs/*/log4rs/encode/pattern/index.html
.encoder(Box::new(log4rs::encode::pattern::PatternEncoder::new(
"{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}\n",
)))
.build(home.join("switch-service.log"))?;
match log4rs::Config::builder()
.appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile)))
.build(
log4rs::config::Root::builder()
.appender("logfile")
.build(log::LevelFilter::Info),
) {
Ok(config) => {
let _ = log4rs::init_config(config);
}
Err(_) => {}
}
Ok(())
} }
pub fn log_init() -> io::Result<()> { pub fn log_init() -> io::Result<()> {
let home = dirs::home_dir().unwrap().join(".switch"); log_init_("switch.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"));
};
if !home.exists() { if !home.exists() {
std::fs::create_dir(&home)?; std::fs::create_dir(&home)?;
} }
@@ -39,7 +25,7 @@ pub fn log_init() -> io::Result<()> {
.encoder(Box::new(log4rs::encode::pattern::PatternEncoder::new( .encoder(Box::new(log4rs::encode::pattern::PatternEncoder::new(
"{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}\n", "{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}\n",
))) )))
.build(home.join("switch.log"))?; .build(home.join(file_name))?;
match log4rs::Config::builder() match log4rs::Config::builder()
.appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile))) .appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile)))
.appender( .appender(
+58 -14
View File
@@ -1,4 +1,4 @@
use std::fs::File; use std::fs::{File, OpenOptions};
use std::io; use std::io;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::net::{SocketAddr, ToSocketAddrs}; use std::net::{SocketAddr, ToSocketAddrs};
@@ -7,11 +7,12 @@ use std::path::PathBuf;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use parking_lot::Mutex; use parking_lot::Mutex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{BaseArgs, StartArgs};
use crate::StartArgs;
pub mod log_config; pub mod log_config;
pub struct BaseConfig { pub struct StartConfig {
pub name: String, pub name: String,
pub token: String, pub token: String,
pub server: SocketAddr, pub server: SocketAddr,
@@ -19,7 +20,7 @@ pub struct BaseConfig {
pub device_id: String, pub device_id: String,
} }
pub fn default_config(start_args: StartArgs) -> Result<BaseConfig, String> { pub fn default_config(start_args: StartArgs) -> Result<StartConfig, String> {
let args_config = read_config(); let args_config = read_config();
if args_config.is_none() && start_args.token.is_none() { if args_config.is_none() && start_args.token.is_none() {
return Err("找不到token(Token not found)".to_string()); return Err("找不到token(Token not found)".to_string());
@@ -33,10 +34,11 @@ pub fn default_config(start_args: StartArgs) -> Result<BaseConfig, String> {
} }
let name = start_args.name.unwrap_or_else(|| { let name = start_args.name.unwrap_or_else(|| {
if let Some(c) = &args_config { if let Some(c) = &args_config {
c.name.clone() if !c.name.is_empty() {
} else { return c.name.clone();
os_info::get().to_string() }
} }
os_info::get().to_string()
}); });
let name = name.trim(); let name = name.trim();
let name = if name.len() > 64 { let name = if name.len() > 64 {
@@ -65,7 +67,7 @@ pub fn default_config(start_args: StartArgs) -> Result<BaseConfig, String> {
return c.server.clone(); return c.server.clone();
} }
} }
"nat1.wherewego.top:29875".to_string() "nat1.wherewego.top:29871".to_string()
}).to_socket_addrs() { }).to_socket_addrs() {
Ok(mut server) => { Ok(mut server) => {
if let Some(addr) = server.next() { if let Some(addr) = server.next() {
@@ -90,7 +92,7 @@ pub fn default_config(start_args: StartArgs) -> Result<BaseConfig, String> {
if nat_test_server.is_empty() { if nat_test_server.is_empty() {
return Err("NAT检测服务地址错误(NAT detection service address error)".to_string()); return Err("NAT检测服务地址错误(NAT detection service address error)".to_string());
} }
let base_config = BaseConfig { let base_config = StartConfig {
name, name,
token, token,
server, server,
@@ -102,7 +104,7 @@ pub fn default_config(start_args: StartArgs) -> Result<BaseConfig, String> {
lazy_static! { lazy_static! {
static ref CONFIG: Mutex<Option<ArgsConfig>> = Mutex::new(None); static ref CONFIG: Mutex<Option<ArgsConfig>> = Mutex::new(None);
static ref SWITCH_HOME_PATH: Mutex<Option<PathBuf>> = Mutex::new(None); pub static ref SWITCH_HOME_PATH: Mutex<Option<PathBuf>> = Mutex::new(None);
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
@@ -120,6 +122,8 @@ pub struct ArgsConfig {
pub nat_test_server: Vec<String>, pub nat_test_server: Vec<String>,
#[serde(default = "default_str")] #[serde(default = "default_str")]
pub device_id: String, pub device_id: String,
#[serde(default = "default_pid")]
pub pid: u32,
} }
fn default_version() -> String { fn default_version() -> String {
@@ -134,6 +138,10 @@ fn default_resource_vec() -> Vec<String> {
vec![] vec![]
} }
fn default_pid() -> u32 {
0
}
impl ArgsConfig { impl ArgsConfig {
pub fn new(token: String, name: String, server: String, nat_test_server: Vec<String>, device_id: String) -> Self { pub fn new(token: String, name: String, server: String, nat_test_server: Vec<String>, device_id: String) -> Self {
Self { Self {
@@ -144,21 +152,49 @@ impl ArgsConfig {
server, server,
nat_test_server, nat_test_server,
device_id, device_id,
pid: 0,
} }
} }
} }
use fd_lock::RwLock;
pub fn lock_config() -> io::Result<RwLock<File>> {
let config_path = SWITCH_HOME_PATH.lock().clone().unwrap().join("config");
Ok(RwLock::new(File::open(config_path)?))
}
pub fn save_config(config: ArgsConfig) -> io::Result<()> { pub fn save_config(config: ArgsConfig) -> io::Result<()> {
let config_path = dirs::home_dir().unwrap().join(".switch").join("config"); let config_path = SWITCH_HOME_PATH.lock().clone().unwrap().join("config");
save_config_(config, config_path) save_config_(config, config_path)
} }
fn save_config_(config: ArgsConfig, config_path: PathBuf) -> io::Result<()> { fn save_config_(config: ArgsConfig, config_path: PathBuf) -> io::Result<()> {
let mut config_lock = CONFIG.lock();
config_lock.take();
let str = serde_yaml::to_string(&config).unwrap(); let str = serde_yaml::to_string(&config).unwrap();
let mut file = File::create(config_path)?; let mut file = File::create(config_path)?;
file.write_all(str.as_bytes()) file.write_all(str.as_bytes())
} }
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"))
}
#[cfg(any(unix))]
pub fn read_pid() -> io::Result<u32> {
let home = SWITCH_HOME_PATH.lock().clone().unwrap();
let config = read_config_(home)?;
Ok(config.pid)
}
pub fn update_command_port(port: u16) -> io::Result<()> { pub fn update_command_port(port: u16) -> io::Result<()> {
let home_lock = SWITCH_HOME_PATH.lock(); let home_lock = SWITCH_HOME_PATH.lock();
if let Some(home) = home_lock.clone() { if let Some(home) = home_lock.clone() {
@@ -173,9 +209,13 @@ pub fn update_command_port(port: u16) -> io::Result<()> {
} }
pub fn read_command_port() -> io::Result<u16> { pub fn read_command_port() -> io::Result<u16> {
let home = dirs::home_dir().unwrap().join(".switch"); let home = SWITCH_HOME_PATH.lock().clone().unwrap();
let config = read_config_(home)?; let config = read_config_(home)?;
Ok(config.command_port.unwrap()) if let Some(p) = config.command_port {
Ok(p)
} else {
Err(io::Error::new(io::ErrorKind::Other, "not fount config"))
}
} }
pub fn read_config() -> Option<ArgsConfig> { pub fn read_config() -> Option<ArgsConfig> {
@@ -206,7 +246,11 @@ pub fn set_home(home: PathBuf) {
fn read_config_(home: PathBuf) -> io::Result<ArgsConfig> { fn read_config_(home: PathBuf) -> io::Result<ArgsConfig> {
let config_path = home.join("config"); let config_path = home.join("config");
let mut file = File::open(config_path)?; let mut file = if config_path.exists() {
File::open(config_path)?
} else {
OpenOptions::new().read(true).write(true).truncate(false).create(true).open(config_path)?
};
let mut str = String::new(); let mut str = String::new();
file.read_to_string(&mut str)?; file.read_to_string(&mut str)?;
match serde_yaml::from_str::<ArgsConfig>(&str) { match serde_yaml::from_str::<ArgsConfig>(&str) {
-3
View File
@@ -1,8 +1,5 @@
use std::net::Ipv4Addr;
use console::style; use console::style;
use switch::Route;
use crate::command::entity::{DeviceItem, RouteItem, Status}; use crate::command::entity::{DeviceItem, RouteItem, Status};
pub mod table; pub mod table;
+10 -7
View File
@@ -1,8 +1,4 @@
const NODE: &str = "+"; use console::style;
const EDGE: &str = "-";
const HIGH: &str = "|";
const SPACE: &str = " ";
const EMPTY: &str = "";
pub fn println_table(table: Vec<Vec<String>>) { pub fn println_table(table: Vec<Vec<String>>) {
if table.is_empty() { if table.is_empty() {
@@ -11,16 +7,23 @@ pub fn println_table(table: Vec<Vec<String>>) {
let mut width_list = vec![0; table[0].len()]; let mut width_list = vec![0; table[0].len()];
for in_list in table.iter() { for in_list in table.iter() {
for (index, item) in in_list.iter().enumerate() { for (index, item) in in_list.iter().enumerate() {
let width = console::measure_text_width(item)+6; let width = console::measure_text_width(item) + 6;
if width_list[index] < width { if width_list[index] < width {
width_list[index] = width; width_list[index] = width;
} }
} }
} }
let mut head = true;
for in_list in table { for in_list in table {
for (index, item) in in_list.iter().enumerate() { for (index, item) in in_list.iter().enumerate() {
print!("{item:width$}", item = item, width = width_list[index]); if head {
print!("{item:width$}", item = item, width = width_list[index]);
} else {
let str = format!("{item:width$}", item = item, width = width_list[index]);
print!("{}", style(str).green());
}
} }
head = false;
println!() println!()
} }
} }
+34 -110
View File
@@ -1,19 +1,18 @@
use std::io;
use std::net::{SocketAddr, ToSocketAddrs};
use std::path::PathBuf;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use console::style; use console::style;
use switch::core::{Config, Switch};
use switch::handle::PeerDeviceStatus;
use crate::config::log_config::{log_init, log_init_service};
use switch::core::Switch;
use crate::config::log_config::log_init;
#[cfg(target_os = "windows")]
use crate::config::log_config::log_service_init;
mod command; mod command;
mod config; mod config;
#[cfg(windows)] #[cfg(target_os = "windows")]
mod windows; mod windows;
#[cfg(any(unix))]
mod unix; mod unix;
mod console_out; mod console_out;
@@ -24,70 +23,6 @@ version,
about = "一个虚拟网络工具,启动后会获取一个ip,相同token下的设备之间可以用ip直接通信" about = "一个虚拟网络工具,启动后会获取一个ip,相同token下的设备之间可以用ip直接通信"
)] )]
pub struct BaseArgs { pub struct BaseArgs {
// /// 不超过64个字符
// /// 相同token的设备之间才能通信。
// /// 建议使用uuid保证唯一性。
// /// No more than 64 characters
// /// Only devices with the same token can communicate with each other.
// /// It is recommended to use uuid to ensure uniqueness
// #[arg(long)]
// token: Option<String>,
// /// 给设备一个名称,为空时默认用系统版本信息
// /// Give the device a name. If it is blank, the system version information will be used by default
// #[arg(long)]
// name: Option<String>,
// /// 设备唯一标识,为空时默认使用MAC地址,不超过64个字符
// /// Unique identification of the device. If it is blank, the MAC address is used by default. No more than 64 characters
// #[arg(long)]
// device_id: Option<String>,
// /// 注册和中继服务器地址
// /// Register and relay server address
// #[arg(long)]
// server: Option<String>,
// /// NAT检测服务地址,使用逗号分隔
// /// NAT detection service address. Use comma to separate
// #[arg(long)]
// nat_test_server: Option<String>,
// /// 开机自启动
// /// Software automatically start up at boot.
// #[cfg(windows)]
// #[arg(long)]
// auto: bool,
// #[arg(long)]
// start: bool,
//
// // /// 启动,启动时可以附加参数 --token,如果没有token,则会读取配置文件中上一次使用的token
// // /// 安装服务后,会以服务的方式在后台启动,此时可以关闭命令行窗口
// // /// When starting, you can attach the parameter -- token. If there is no token, the last token used in the configuration file will be read. After installing the service, it will be started in the background as a service. At this time, you can close the command line window
// // #[arg(subcommand)]
// // start111: Option<StartArgs>,
// #[arg(long)]
// /// 停止,启动服务后,使用 --stop停止服务
// /// Stop. After starting the service, use -- stop to stop the service
// stop: bool,
// /// 启动服务后,使用 --list 查看设备列表
// /// After starting the service, use -- list to view the device list
// #[arg(long)]
// list: bool,
// /// 启动服务后,使用 --status 查看设备状态
// /// After starting the service, use -- status to view the device status
// #[arg(long)]
// status: bool,
// /// 启动服务后,使用 --route 查看所有路由
// /// After starting the service, use -- route to View all routes
// #[arg(long)]
// route: bool,
//
// /// 安装服务,安装后可以后台运行,需要指定安装路径
// /// The installation service can run in the background after installation, and the installation path needs to be specified
// #[cfg(windows)]
// #[arg(long)]
// install: Option<String>,
// /// 卸载服务
// /// Uninstall service
// #[cfg(windows)]
// #[arg(long)]
// uninstall: bool,
#[clap(subcommand)] #[clap(subcommand)]
command: Commands, command: Commands,
@@ -101,14 +36,14 @@ enum Commands {
Stop, Stop,
/// 安装服务 /// 安装服务
/// Install service /// Install service
#[cfg(windows)] #[cfg(target_os = "windows")]
Install(InstallArgs), Install(InstallArgs),
/// 卸载服务 /// 卸载服务
/// Uninstall service /// Uninstall service
#[cfg(windows)] #[cfg(target_os = "windows")]
Uninstall, Uninstall,
/// 配置 /// 配置
#[cfg(windows)] #[cfg(target_os = "windows")]
Config(ConfigArgs), Config(ConfigArgs),
/// 查看路由 /// 查看路由
/// View route /// View route
@@ -151,8 +86,16 @@ pub struct StartArgs {
/// NAT detection service address. Use comma to separate /// NAT detection service address. Use comma to separate
#[arg(long)] #[arg(long)]
nat_test_server: Option<String>, nat_test_server: Option<String>,
/// 命令服务,开启后可以在其他进程使用 route、list等命令查看信息
/// 程序使用后台运行时需要增加此参数
/// Command service. After it is enabled, you can use route, list and other commands in other processes to view information.
/// This parameter needs to be added when the program is running in the background
#[cfg(any(unix))]
#[arg(long)]
command_server: bool,
} }
#[cfg(target_os = "windows")]
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
pub struct InstallArgs { pub struct InstallArgs {
/// 安装路径 /// 安装路径
@@ -165,16 +108,13 @@ pub struct InstallArgs {
auto: bool, auto: bool,
} }
#[cfg(target_os = "windows")]
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
pub struct ConfigArgs { pub struct ConfigArgs {
/// 服务开机自启动 /// 服务开机自启动
/// Autostart on system startup /// Autostart on system startup
#[arg(long)] #[arg(long)]
auto: bool, auto: bool,
/// 取消服务开机自启动
/// started manually
#[arg(long)]
not_auto: bool,
} }
@@ -183,9 +123,9 @@ fn main() {
let args: Vec<_> = std::env::args().collect(); let args: Vec<_> = std::env::args().collect();
if args.len() == 3 && args[1] == windows::SERVICE_FLAG { if args.len() == 3 && args[1] == windows::SERVICE_FLAG {
//以服务的方式启动 //以服务的方式启动
let _ = log_init_service(PathBuf::from(&args[2])); config::set_home(std::path::PathBuf::from(&args[2]));
config::set_home(PathBuf::from(&args[2])); let _ = log_service_init();
log::info!("config {:?}", PathBuf::from(&args[2])); log::info!("config {:?}", std::path::PathBuf::from(&args[2]));
log::info!("config {:?}", config::read_config()); log::info!("config {:?}", config::read_config());
windows::service::start(); windows::service::start();
return; return;
@@ -200,34 +140,14 @@ fn main() {
#[cfg(any(target_os = "linux", target_os = "macos"))] #[cfg(any(target_os = "linux", target_os = "macos"))]
fn main() { fn main() {
let home = dirs::home_dir().unwrap().join(".switch");
config::set_home(home);
let _ = log_init(); let _ = log_init();
let args = Args::parse(); let args = BaseArgs::parse();
if sudo::RunningAs::Root != sudo::check() { unix::main0(args);
println!(
"{}",
style("需要使用root权限执行(Need to execute with root permission)...").red()
);
sudo::escalate_if_needed().unwrap();
}
println!("{}", style("starting...").green());
start(args.token, args.name);
} }
pub fn start(token: String, name: String, server_address: SocketAddr, nat_test_server: Vec<SocketAddr>, device_id: String) { pub fn console_listen(switch: &Switch) {
let config = Config::new(
token,
device_id,
name,
server_address,
nat_test_server,
);
let switch = match Switch::start(config) {
Ok(switch) => switch,
Err(e) => {
log::error!("{:?}", e);
return;
}
};
use console::Term; use console::Term;
let term = Term::stdout(); let term = Term::stdout();
println!("{}", style("started").green()); println!("{}", style("started").green());
@@ -247,6 +167,10 @@ pub fn start(token: String, name: String, server_address: SocketAddr, nat_test_s
); );
match term.read_line() { match term.read_line() {
Ok(cmd) => { Ok(cmd) => {
if cmd.is_empty() {
log::warn!("非正常返回");
return;
}
if command(cmd.trim(), &switch).is_err() { if command(cmd.trim(), &switch).is_err() {
println!("{}", style("stopping").red()); println!("{}", style("stopping").red());
if let Err(e) = switch.stop() { if let Err(e) = switch.stop() {
@@ -256,17 +180,17 @@ pub fn start(token: String, name: String, server_address: SocketAddr, nat_test_s
} }
} }
Err(e) => { Err(e) => {
println!("read_line:{:?}", e); log::error!("read_line:{:?}", e);
println!("{}", style("stopping...").red()); println!("{}", style("stopping...").red());
if let Err(e) = switch.stop() { if let Err(e) = switch.stop() {
println!("stop:{:?}", e); log::error!("stop:{:?}", e);
} }
std::thread::sleep(std::time::Duration::from_secs(1));
break; break;
} }
} }
} }
println!("{}", style("stopped").red()); println!("{}", style("stopped").red());
std::process::exit(1);
} }
+139
View File
@@ -0,0 +1,139 @@
use std::sync::Arc;
use console::style;
use switch::core::{Config, Switch};
use crate::{BaseArgs, Commands, config};
use crate::command::{command, CommandEnum};
pub fn main0(base_args: BaseArgs) {
match base_args.command {
Commands::Start(args) => {
let open_command_server = args.command_server;
match config::default_config(args) {
Ok(start_config) => {
if sudo::RunningAs::Root != sudo::check() {
println!(
"{}",
style("需要使用root权限执行(Need to execute with root permission)...").red()
);
sudo::escalate_if_needed().unwrap();
}
let config = Config::new(
start_config.token.clone(),
start_config.device_id.clone(),
start_config.name.clone(),
start_config.server,
start_config.nat_test_server.clone(),
);
let nat_test_server = start_config.nat_test_server.iter().map(|v| v.to_string()).collect::<Vec<String>>();
let args_config = config::ArgsConfig::new(
start_config.token.clone(),
start_config.name.clone(),
start_config.server.to_string(),
nat_test_server,
start_config.device_id.clone(),
);
let mut lock = match config::lock_config() {
Ok(lock) => {
lock
}
Err(e) => {
log::error!("{:?}",e);
return;
}
};
let lock_guard = match lock.try_write() {
Ok(lock) => {
lock
}
Err(_) => {
println!("{}", style("文件被重复打开").red());
return;
}
};
if let Err(e) = config::save_config(args_config) {
log::error!("{:?}",e);
return;
}
let switch = match Switch::start(config) {
Ok(switch) => {
switch
}
Err(e) => {
log::error!("{:?}", e);
return;
}
};
let switch = Arc::new(switch);
let command_server = crate::command::server::CommandServer::new();
if open_command_server {
if let Err(e) = config::update_pid(std::process::id()) {
log::error!("{:?}", e);
}
let switch1 = switch.clone();
let handle = std::thread::spawn(move || {
if let Err(e) = command_server.start(switch1) {
log::error!("{:?}", e);
}
});
crate::console_listen(&switch);
if let Err(e) = handle.join() {
log::error!("后台任务异常{:?}",e);
} else {
log::info!("后台任务结束");
}
} else {
crate::console_listen(&switch);
log::info!("前台任务结束");
}
drop(lock_guard)
}
Err(e) => {
log::error!("{:?}", e);
}
}
}
Commands::Stop => {
if sudo::RunningAs::Root != sudo::check() {
println!(
"{}",
style("需要使用root权限执行(Need to execute with root permission)...").red()
);
sudo::escalate_if_needed().unwrap();
}
command(CommandEnum::Stop);
if let Ok(pid) = config::read_pid() {
if pid != 0 {
let kill_cmd = format!("kill {}", pid);
let kill_out = std::process::Command::new("sh")
.arg("-c")
.arg(&kill_cmd)
.output()
.expect("sh exec error!");
if !kill_out.status.success() {
println!("cmd:{:?},err:{:?}", kill_cmd, kill_out);
return;
}
}
}
println!("stopped")
}
Commands::Route => {
command(CommandEnum::Route);
}
Commands::List { all } => {
if all {
command(CommandEnum::ListAll);
} else {
command(CommandEnum::List);
}
}
Commands::Status => {
command(CommandEnum::Status);
}
}
}
+101 -60
View File
@@ -2,7 +2,6 @@ use std::ffi::OsString;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
use std::{io, thread}; use std::{io, thread};
use std::net::ToSocketAddrs;
use console::style; use console::style;
@@ -11,9 +10,10 @@ use windows_service::service::{
}; };
use windows_service::service_manager::{ServiceManager, ServiceManagerAccess}; use windows_service::service_manager::{ServiceManager, ServiceManagerAccess};
use windows_service::Error; use windows_service::Error;
use switch::core::{Config, Switch};
use crate::{BaseArgs, Commands, config, console_out}; use crate::{BaseArgs, Commands, config};
use crate::config::BaseConfig; use crate::command::{command, CommandEnum};
pub mod service; pub mod service;
mod windows_admin_check; mod windows_admin_check;
@@ -22,46 +22,6 @@ pub const SERVICE_FLAG: &'static str = "start_switch_service_v1_";
pub const SERVICE_NAME: &'static str = "switch-service-v1"; pub const SERVICE_NAME: &'static str = "switch-service-v1";
pub const SERVICE_TYPE: ServiceType = ServiceType::OWN_PROCESS; pub const SERVICE_TYPE: ServiceType = ServiceType::OWN_PROCESS;
fn command(cmd: &str) {
if let Err(e) = command_(cmd) {
println!("{}:{:?}", style("连接服务错误(Connection service error)").red(), e);
}
}
fn command_(cmd: &str) -> io::Result<()> {
match crate::command::client::CommandClient::new() {
Ok(command_client) => {
match cmd {
"route" => {
let list = command_client.route()?;
console_out::console_route_table(list);
}
"list" => {
let list = command_client.list()?;
console_out::console_device_list(list);
}
"list-all" => {
let list = command_client.list()?;
console_out::console_device_list_all(list);
}
"status" => {
let status = command_client.status()?;
console_out::console_status(status);
}
_ => {}
}
}
Err(e) => {
log::error!("{:?}",e);
println!(
"{}:{:?}",
style("连接服务错误(Connection service error)").red(), e
);
}
};
Ok(())
}
fn admin_check() -> bool { fn admin_check() -> bool {
if !windows_admin_check::is_app_elevated() { if !windows_admin_check::is_app_elevated() {
println!( println!(
@@ -97,22 +57,24 @@ pub fn main0(base_args: BaseArgs) {
return; return;
} }
match config::default_config(args) { match config::default_config(args) {
Ok(base_config) => { Ok(start_config) => {
match service_state() { match service_state() {
Ok(state) => { Ok(state) => {
if state == ServiceState::Stopped { if state == ServiceState::Stopped {
config::save_config(config::ArgsConfig::new( if let Err(e) = config::save_config(config::ArgsConfig::new(
base_config.token.clone(), start_config.token.clone(),
base_config.name.clone(), start_config.name.clone(),
base_config.server.to_string(), start_config.server.to_string(),
base_config.nat_test_server.iter().map(|v| v.to_string()).collect::<Vec<String>>(), start_config.nat_test_server.iter().map(|v| v.to_string()).collect::<Vec<String>>(),
base_config.device_id.clone(), start_config.device_id.clone(),
)) )) {
.unwrap(); log::error!("{:?}",e);
return;
}
match start() { match start() {
Ok(_) => { Ok(_) => {
//需要检查启动状态 //需要检查启动状态
std::thread::sleep(std::time::Duration::from_secs(2)); thread::sleep(Duration::from_secs(2));
println!("{}", style("启动成功(Start successfully)").green()) println!("{}", style("启动成功(Start successfully)").green())
} }
Err(e) => { Err(e) => {
@@ -133,7 +95,38 @@ pub fn main0(base_args: BaseArgs) {
"{}", "{}",
style("服务未安装,在当前进程启动(The service is not installed and started in the current process)").red() style("服务未安装,在当前进程启动(The service is not installed and started in the current process)").red()
); );
crate::start(base_config.token, base_config.name, base_config.server, base_config.nat_test_server, base_config.device_id); let config = Config::new(
start_config.token,
start_config.device_id,
start_config.name,
start_config.server,
start_config.nat_test_server,
);
let mut lock = match config::lock_config() {
Ok(lock) => lock,
Err(e) => {
log::error!("{:?}",e);
return;
}
};
let lock_guard = match lock.try_write() {
Ok(lock) => {
lock
}
Err(_) => {
println!("{}", style("程序文件被重复打开").red());
return;
}
};
match Switch::start(config) {
Ok(switch) => {
crate::console_listen(&switch);
}
Err(e) => {
log::error!("{:?}", e);
}
}
drop(lock_guard);
return; return;
} }
} }
@@ -154,6 +147,9 @@ pub fn main0(base_args: BaseArgs) {
if not_started() { if not_started() {
return; return;
} }
if admin_check() {
return;
}
match stop() { match stop() {
Ok(_) => { Ok(_) => {
println!("{}", style("停止成功(Stopped successfully)").green()) println!("{}", style("停止成功(Stopped successfully)").green())
@@ -165,6 +161,9 @@ pub fn main0(base_args: BaseArgs) {
pause(); pause();
} }
Commands::Install(args) => { Commands::Install(args) => {
if admin_check() {
return;
}
let path: PathBuf = args.path.into(); let path: PathBuf = args.path.into();
if !path.exists() { if !path.exists() {
std::fs::create_dir_all(&path).unwrap(); std::fs::create_dir_all(&path).unwrap();
@@ -181,6 +180,9 @@ pub fn main0(base_args: BaseArgs) {
pause(); pause();
} }
Commands::Uninstall => { Commands::Uninstall => {
if admin_check() {
return;
}
if let Err(e) = uninstall() { if let Err(e) = uninstall() {
log::error!("{:?}", e); log::error!("{:?}", e);
} else { } else {
@@ -188,28 +190,35 @@ pub fn main0(base_args: BaseArgs) {
} }
pause(); pause();
} }
Commands::Config(args) => {} Commands::Config(args) => {
if let Err(e) = change(args.auto) {
log::error!("{:?}", e);
} else {
println!("{}", style("配置成功(Config succeeded)").green())
}
pause();
}
Commands::Route => { Commands::Route => {
if not_started() { if not_started() {
return; return;
} }
command("route"); command(CommandEnum::Route);
} }
Commands::List { all } => { Commands::List { all } => {
if not_started() { if not_started() {
return; return;
} }
if all { if all {
command("list-all"); command(CommandEnum::ListAll);
} else { } else {
command("list"); command(CommandEnum::List);
} }
} }
Commands::Status => { Commands::Status => {
if not_started() { if not_started() {
return; return;
} }
command("status"); command(CommandEnum::Status);
} }
} }
} }
@@ -265,6 +274,39 @@ fn install(path: PathBuf, auto: bool) -> Result<(), Error> {
Ok(()) Ok(())
} }
fn change(auto: bool) -> Result<(), Error> {
let manager_access = ServiceManagerAccess::CONNECT;
let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;
let service_access = ServiceAccess::QUERY_CONFIG | ServiceAccess::CHANGE_CONFIG;
let service = service_manager.open_service(SERVICE_NAME, service_access)?;
let config = service.query_config()?;
let start_type = if auto {
ServiceStartType::AutoStart
} else {
ServiceStartType::OnDemand
};
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(),
));
let service_info = ServiceInfo {
name: OsString::from(SERVICE_NAME),
display_name: config.display_name,
service_type: ServiceType::OWN_PROCESS,
start_type,
error_control: config.error_control,
executable_path: config.executable_path,
launch_arguments,
dependencies: config.dependencies,
account_name: None, // run as System
account_password: None,
};
service.change_config(&service_info)?;
Ok(())
}
fn uninstall() -> Result<(), Error> { fn uninstall() -> Result<(), Error> {
let manager_access = ServiceManagerAccess::CONNECT; let manager_access = ServiceManagerAccess::CONNECT;
let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?; let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;
@@ -278,7 +320,6 @@ fn uninstall() -> Result<(), Error> {
// Wait for service to stop // Wait for service to stop
thread::sleep(Duration::from_secs(1)); thread::sleep(Duration::from_secs(1));
} }
service.delete()?; service.delete()?;
Ok(()) Ok(())
} }
+22 -11
View File
@@ -2,16 +2,20 @@
// extern crate windows_service; // extern crate windows_service;
use std::ffi::OsString; use std::ffi::OsString;
use std::net::ToSocketAddrs;
use std::sync::Arc; use std::sync::Arc;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use std::net::ToSocketAddrs;
use windows_service::{define_windows_service, service_control_handler, service_dispatcher};
use windows_service::service::{ use windows_service::service::{
ServiceControl, ServiceControlAccept, ServiceExitCode, ServiceState, ServiceStatus, ServiceControl, ServiceControlAccept, ServiceExitCode, ServiceState, ServiceStatus,
}; };
use windows_service::service_control_handler::ServiceControlHandlerResult; use windows_service::service_control_handler::ServiceControlHandlerResult;
use windows_service::{define_windows_service, service_control_handler, service_dispatcher};
use switch::core::{Config, Switch}; use switch::core::{Config, Switch};
use crate::config;
use crate::windows::config::read_config; use crate::windows::config::read_config;
define_windows_service!(ffi_service_main, switch_service_main); define_windows_service!(ffi_service_main, switch_service_main);
@@ -19,7 +23,7 @@ pub fn switch_service_main(_arguments: Vec<OsString>) {
thread::spawn(|| match service_main() { thread::spawn(|| match service_main() {
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
log::warn!("{:?}", e); log::error!("{:?}", e);
} }
}); });
} }
@@ -58,10 +62,15 @@ fn service_main() -> windows_service::Result<()> {
wait_hint: Duration::default(), wait_hint: Duration::default(),
process_id: None, process_id: None,
})?; })?;
if let Ok(switch) = start_switch() { match start_switch() {
parker.park(); Ok(switch) => {
if let Err(e) = switch.stop() { parker.park();
log::warn!("switch stop:{:?}",e) if let Err(e) = switch.stop() {
log::warn!("switch stop:{:?}",e)
}
}
Err(e) => {
log::error!("{:?}",e);
} }
} }
status_handle.set_service_status(ServiceStatus { status_handle.set_service_status(ServiceStatus {
@@ -79,7 +88,7 @@ fn start_switch() -> switch::Result<Arc<Switch>> {
if let Some(config) = read_config() { if let Some(config) = read_config() {
let device_id = config.device_id; let device_id = config.device_id;
if device_id.trim().is_empty() { if device_id.trim().is_empty() {
return Err(switch::error::Error::Stop("MAC address error".to_string())); return Err(switch::error::Error::Stop("Device id error".to_string()));
} }
let server_address = if let Some(server_address) = config.server let server_address = if let Some(server_address) = config.server
.to_socket_addrs()? .to_socket_addrs()?
@@ -88,11 +97,10 @@ fn start_switch() -> switch::Result<Arc<Switch>> {
} else { } else {
return Err(switch::error::Error::Stop("server address error".to_string())); return Err(switch::error::Error::Stop("server address error".to_string()));
}; };
let mut nat_test_server = config.nat_test_server.iter() let nat_test_server = config.nat_test_server.iter()
.flat_map(|a| a.to_socket_addrs()) .flat_map(|a| a.to_socket_addrs())
.flatten() .flatten()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
;
if nat_test_server.is_empty() { if nat_test_server.is_empty() {
return Err(switch::error::Error::Stop("nat test server address error".to_string())); return Err(switch::error::Error::Stop("nat test server address error".to_string()));
} }
@@ -108,8 +116,11 @@ fn start_switch() -> switch::Result<Arc<Switch>> {
let command_server = crate::command::server::CommandServer::new(); let command_server = crate::command::server::CommandServer::new();
let switch1 = switch.clone(); let switch1 = switch.clone();
thread::spawn(move || { thread::spawn(move || {
if let Err(e) = config::update_pid(std::process::id()) {
log::error!("{:?}", e);
}
if let Err(e) = command_server.start(switch1) { if let Err(e) = command_server.start(switch1) {
log::warn!("{:?}", e); log::error!("{:?}", e);
} }
}); });
Ok(switch) Ok(switch)
+2 -2
View File
@@ -7,7 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
packet = { path = "./packet" } packet = { path = "./packet" }
nat_traversal = { path = "./p2p_channel" } p2p_channel = { path = "./p2p_channel" }
bytes = "1.3.0" bytes = "1.3.0"
log = "0.4.17" log = "0.4.17"
libc = "0.2.137" libc = "0.2.137"
@@ -26,7 +26,7 @@ chrono = "0.4.23"
#lazy_static = "1.4.0" #lazy_static = "1.4.0"
#moka = "0.9.6" #moka = "0.9.6"
protobuf = "3.2.0" protobuf = "3.2.0"
local-ip-address = "0.5.2" local-ip-address = "0.4.9"
#mio = {version = "0.8.6",features = ["os-poll", "net"]} #mio = {version = "0.8.6",features = ["os-poll", "net"]}
#tokio = { version = "1.24.1", features = ["full"] } #tokio = { version = "1.24.1", features = ["full"] }
+1 -21
View File
@@ -15,31 +15,11 @@ libc = "0.2"
thiserror = "1" thiserror = "1"
[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "android"))'.dependencies] [target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "android"))'.dependencies]
tokio = { version = "1", features = ["net", "macros"], optional = true }
tokio-util = { version = "0.6", features = ["codec"], optional = true }
bytes = { version = "1", optional = true } bytes = { version = "1", optional = true }
byteorder = { version = "1", optional = true } byteorder = { version = "1", optional = true }
# This is only for the `ready` macro.
futures-core = { version = "0.3", optional = true }
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies] [target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
ioctl = { version = "0.6", package = "ioctl-sys" } ioctl = { version = "0.6", package = "ioctl-sys" }
[dev-dependencies]
packet = "0.1"
futures = "0.3"
[features]
async = ["tokio", "tokio-util", "bytes", "byteorder", "futures-core"]
[[example]]
name = "read-async"
required-features = [ "async", "tokio/rt-multi-thread" ]
[[example]]
name = "read-async-codec"
required-features = [ "async", "tokio/rt-multi-thread" ]
[[example]]
name = "ping-tun"
required-features = [ "async", "tokio/rt-multi-thread" ]
-106
View File
@@ -1,106 +0,0 @@
TUN interfaces [![Crates.io](https://img.shields.io/crates/v/tun.svg)](https://crates.io/crates/tun) ![tun](https://docs.rs/tun/badge.svg) ![WTFPL](http://img.shields.io/badge/license-WTFPL-blue.svg)
==============
This crate allows the creation and usage of TUN interfaces, the aim is to make this cross-platform.
Usage
-----
First, add the following to your `Cargo.toml`:
```toml
[dependencies]
tun = "0.5"
```
Next, add this to your crate root:
```rust
extern crate tun;
```
If you want to use the TUN interface with mio/tokio, you need to enable the `async` feature:
```toml
[dependencies]
tun = { version = "0.5", features = ["async"] }
```
Example
-------
The following example creates and configures a TUN interface and starts reading
packets from it.
```rust
use std::io::Read;
extern crate tun;
fn main() {
let mut config = tun::Configuration::default();
config.address((10, 0, 0, 1))
.netmask((255, 255, 255, 0))
.up();
#[cfg(target_os = "linux")]
config.platform(|config| {
config.packet_information(true);
});
let mut dev = tun::create(&config).unwrap();
let mut buf = [0; 4096];
loop {
let amount = dev.read(&mut buf).unwrap();
println!("{:?}", &buf[0 .. amount]);
}
}
```
Platforms
=========
Not every platform is supported.
Linux
-----
You will need the `tun` module to be loaded and root is required to create
interfaces.
macOS
-----
It just werks, but you have to set up routing manually.
iOS
----
You can pass the file descriptor of the TUN device to `rust-tun` to create the interface.
Here is an example to create the TUN device on iOS and pass the `fd` to `rust-tun`:
```swift
// Swift
class PacketTunnelProvider: NEPacketTunnelProvider {
override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
let tunnelNetworkSettings = createTunnelSettings() // Configure TUN address, DNS, mtu, routing...
setTunnelNetworkSettings(tunnelNetworkSettings) { [weak self] error in
let tunFd = self?.packetFlow.value(forKeyPath: "socket.fileDescriptor") as! Int32
DispatchQueue.global(qos: .default).async {
start_tun(tunFd)
}
completionHandler(nil)
}
}
}
```
```rust
#[no_mangle]
pub extern "C" fn start_tun(fd: std::os::raw::c_int) {
let mut rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
let mut cfg = tun::Configuration::default();
cfg.raw_fd(fd);
let mut tun = tun::create_as_async(&cfg).unwrap();
let mut framed = tun.into_framed();
while let Some(packet) = framed.next().await {
...
}
});
}
```
-78
View File
@@ -1,78 +0,0 @@
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
use futures::{SinkExt, StreamExt};
use packet::{builder::Builder, icmp, ip, Packet};
use tun::{self, Configuration, TunPacket};
#[tokio::main]
async fn main() {
let mut config = Configuration::default();
config
.address((10, 0, 0, 1))
.netmask((255, 255, 255, 0))
.up();
#[cfg(target_os = "linux")]
config.platform(|config| {
config.packet_information(true);
});
let dev = tun::create_as_async(&config).unwrap();
let mut framed = dev.into_framed();
while let Some(packet) = framed.next().await {
match packet {
Ok(pkt) => match ip::Packet::new(pkt.get_bytes()) {
Ok(ip::Packet::V4(pkt)) => match icmp::Packet::new(pkt.payload()) {
Ok(icmp) => match icmp.echo() {
Ok(icmp) => {
let reply = ip::v4::Builder::default()
.id(0x42)
.unwrap()
.ttl(64)
.unwrap()
.source(pkt.destination())
.unwrap()
.destination(pkt.source())
.unwrap()
.icmp()
.unwrap()
.echo()
.unwrap()
.reply()
.unwrap()
.identifier(icmp.identifier())
.unwrap()
.sequence(icmp.sequence())
.unwrap()
.payload(icmp.payload())
.unwrap()
.build()
.unwrap();
framed.send(TunPacket::new(reply)).await.unwrap();
}
_ => {}
},
_ => {}
},
Err(err) => println!("Received an invalid packet: {:?}", err),
_ => {}
},
Err(err) => panic!("Error: {:?}", err),
}
}
}
@@ -1,61 +0,0 @@
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
use bytes::BytesMut;
use futures::StreamExt;
use packet::{ip::Packet, Error};
use tokio_util::codec::{Decoder, FramedRead};
pub struct IPPacketCodec;
impl Decoder for IPPacketCodec {
type Item = Packet<BytesMut>;
type Error = Error;
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
if buf.is_empty() {
return Ok(None);
}
let buf = buf.split_to(buf.len());
Ok(match Packet::no_payload(buf) {
Ok(pkt) => Some(pkt),
Err(err) => {
println!("error {:?}", err);
None
}
})
}
}
#[tokio::main]
async fn main() {
let mut config = tun::Configuration::default();
config
.address((10, 0, 0, 1))
.netmask((255, 255, 255, 0))
.up();
let dev = tun::create_as_async(&config).unwrap();
let mut stream = FramedRead::new(dev, IPPacketCodec);
while let Some(packet) = stream.next().await {
match packet {
Ok(pkt) => println!("pkt: {:#?}", pkt),
Err(err) => panic!("Error: {:?}", err),
}
}
}
-42
View File
@@ -1,42 +0,0 @@
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
use futures::StreamExt;
use packet::ip::Packet;
#[tokio::main]
async fn main() {
let mut config = tun::Configuration::default();
config
.address((10, 0, 0, 1))
.netmask((255, 255, 255, 0))
.up();
#[cfg(target_os = "linux")]
config.platform(|config| {
config.packet_information(true);
});
let dev = tun::create_as_async(&config).unwrap();
let mut stream = dev.into_framed();
while let Some(packet) = stream.next().await {
match packet {
Ok(pkt) => println!("pkt: {:#?}", Packet::unchecked(pkt.get_bytes())),
Err(err) => panic!("Error: {:?}", err),
}
}
}
-37
View File
@@ -1,37 +0,0 @@
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
use std::io::Read;
fn main() {
let mut config = tun::Configuration::default();
config
.address((10, 0, 0, 1))
.netmask((255, 255, 255, 0))
.up();
#[cfg(target_os = "linux")]
config.platform(|config| {
config.packet_information(true);
});
let mut dev = tun::create(&config).unwrap();
let mut buf = [0; 4096];
loop {
let amount = dev.read(&mut buf).unwrap();
println!("{:?}", &buf[0..amount]);
}
}
-149
View File
@@ -1,149 +0,0 @@
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
use std::io;
use byteorder::{NativeEndian, NetworkEndian, WriteBytesExt};
use bytes::{BufMut, Bytes, BytesMut};
use tokio_util::codec::{Decoder, Encoder};
/// A packet protocol IP version
#[derive(Debug)]
enum PacketProtocol {
IPv4,
IPv6,
Other(u8),
}
// Note: the protocol in the packet information header is platform dependent.
impl PacketProtocol {
#[cfg(any(target_os = "linux", target_os = "android"))]
fn into_pi_field(&self) -> Result<u16, io::Error> {
match self {
PacketProtocol::IPv4 => Ok(libc::ETH_P_IP as u16),
PacketProtocol::IPv6 => Ok(libc::ETH_P_IPV6 as u16),
PacketProtocol::Other(_) => Err(io::Error::new(
io::ErrorKind::Other,
"neither an IPv4 or IPv6 packet",
)),
}
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
fn into_pi_field(&self) -> Result<u16, io::Error> {
match self {
PacketProtocol::IPv4 => Ok(libc::PF_INET as u16),
PacketProtocol::IPv6 => Ok(libc::PF_INET6 as u16),
PacketProtocol::Other(_) => Err(io::Error::new(
io::ErrorKind::Other,
"neither an IPv4 or IPv6 packet",
)),
}
}
}
/// A Tun Packet to be sent or received on the TUN interface.
#[derive(Debug)]
pub struct TunPacket(PacketProtocol, Bytes);
/// Infer the protocol based on the first nibble in the packet buffer.
fn infer_proto(buf: &[u8]) -> PacketProtocol {
match buf[0] >> 4 {
4 => PacketProtocol::IPv4,
6 => PacketProtocol::IPv6,
p => PacketProtocol::Other(p),
}
}
impl TunPacket {
/// Create a new `TunPacket` based on a byte slice.
pub fn new(bytes: Vec<u8>) -> TunPacket {
let proto = infer_proto(&bytes);
TunPacket(proto, Bytes::from(bytes))
}
/// Return this packet's bytes.
pub fn get_bytes(&self) -> &[u8] {
&self.1
}
pub fn into_bytes(self) -> Bytes {
self.1
}
}
/// A TunPacket Encoder/Decoder.
pub struct TunPacketCodec(bool, i32);
impl TunPacketCodec {
/// Create a new `TunPacketCodec` specifying whether the underlying
/// tunnel Device has enabled the packet information header.
pub fn new(pi: bool, mtu: i32) -> TunPacketCodec {
TunPacketCodec(pi, mtu)
}
}
impl Decoder for TunPacketCodec {
type Item = TunPacket;
type Error = io::Error;
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
if buf.is_empty() {
return Ok(None);
}
let mut pkt = buf.split_to(buf.len());
// reserve enough space for the next packet
if self.0 {
buf.reserve(self.1 as usize + 4);
} else {
buf.reserve(self.1 as usize);
}
// if the packet information is enabled we have to ignore the first 4 bytes
if self.0 {
let _ = pkt.split_to(4);
}
let proto = infer_proto(pkt.as_ref());
Ok(Some(TunPacket(proto, pkt.freeze())))
}
}
impl Encoder<TunPacket> for TunPacketCodec {
type Error = io::Error;
fn encode(&mut self, item: TunPacket, dst: &mut BytesMut) -> Result<(), Self::Error> {
dst.reserve(item.get_bytes().len() + 4);
match item {
TunPacket(proto, bytes) if self.0 => {
// build the packet information header comprising of 2 u16
// fields: flags and protocol.
let mut buf = Vec::<u8>::with_capacity(4);
// flags is always 0
buf.write_u16::<NativeEndian>(0).unwrap();
// write the protocol as network byte order
buf.write_u16::<NetworkEndian>(proto.into_pi_field()?)
.unwrap();
dst.put_slice(&buf);
dst.put(bytes);
}
TunPacket(_, bytes) => dst.put(bytes),
}
Ok(())
}
}
-201
View File
@@ -1,201 +0,0 @@
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
use std::io;
use std::io::{IoSlice, Read, Write};
use core::pin::Pin;
use core::task::{Context, Poll};
use futures_core::ready;
use tokio::io::unix::AsyncFd;
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tokio_util::codec::Framed;
use crate::device::Device as D;
use crate::platform::{Device, Queue};
use crate::r#async::codec::*;
/// An async TUN device wrapper around a TUN device.
pub struct AsyncDevice {
inner: AsyncFd<Device>,
}
impl AsyncDevice {
/// Create a new `AsyncDevice` wrapping around a `Device`.
pub fn new(device: Device) -> io::Result<AsyncDevice> {
device.set_nonblock()?;
Ok(AsyncDevice {
inner: AsyncFd::new(device)?,
})
}
/// Returns a shared reference to the underlying Device object
pub fn get_ref(&self) -> &Device {
self.inner.get_ref()
}
/// Returns a mutable reference to the underlying Device object
pub fn get_mut(&mut self) -> &mut Device {
self.inner.get_mut()
}
/// Consumes this AsyncDevice and return a Framed object (unified Stream and Sink interface)
pub fn into_framed(mut self) -> Framed<Self, TunPacketCodec> {
let pi = self.get_mut().has_packet_information();
let codec = TunPacketCodec::new(pi, self.inner.get_ref().mtu().unwrap_or(1504));
Framed::new(self, codec)
}
}
impl AsyncRead for AsyncDevice {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf,
) -> Poll<io::Result<()>> {
loop {
let mut guard = ready!(self.inner.poll_read_ready_mut(cx))?;
let rbuf = buf.initialize_unfilled();
match guard.try_io(|inner| inner.get_mut().read(rbuf)) {
Ok(res) => return Poll::Ready(res.map(|n| buf.advance(n))),
Err(_wb) => continue,
}
}
}
}
impl AsyncWrite for AsyncDevice {
fn poll_write(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
loop {
let mut guard = ready!(self.inner.poll_write_ready_mut(cx))?;
match guard.try_io(|inner| inner.get_mut().write(buf)) {
Ok(res) => return Poll::Ready(res),
Err(_wb) => continue,
}
}
}
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
loop {
let mut guard = ready!(self.inner.poll_write_ready_mut(cx))?;
match guard.try_io(|inner| inner.get_mut().flush()) {
Ok(res) => return Poll::Ready(res),
Err(_wb) => continue,
}
}
}
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}
fn poll_write_vectored(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[IoSlice<'_>],
) -> Poll<Result<usize, io::Error>> {
loop {
let mut guard = ready!(self.inner.poll_write_ready_mut(cx))?;
match guard.try_io(|inner| inner.get_mut().write_vectored(bufs)) {
Ok(res) => return Poll::Ready(res),
Err(_wb) => continue,
}
}
}
fn is_write_vectored(&self) -> bool {
true
}
}
/// An async TUN device queue wrapper around a TUN device queue.
pub struct AsyncQueue {
inner: AsyncFd<Queue>,
}
impl AsyncQueue {
/// Create a new `AsyncQueue` wrapping around a `Queue`.
pub fn new(queue: Queue) -> io::Result<AsyncQueue> {
queue.set_nonblock()?;
Ok(AsyncQueue {
inner: AsyncFd::new(queue)?,
})
}
/// Returns a shared reference to the underlying Queue object
pub fn get_ref(&self) -> &Queue {
self.inner.get_ref()
}
/// Returns a mutable reference to the underlying Queue object
pub fn get_mut(&mut self) -> &mut Queue {
self.inner.get_mut()
}
/// Consumes this AsyncQueue and return a Framed object (unified Stream and Sink interface)
pub fn into_framed(mut self) -> Framed<Self, TunPacketCodec> {
let pi = self.get_mut().has_packet_information();
let codec = TunPacketCodec::new(pi, 1504);
Framed::new(self, codec)
}
}
impl AsyncRead for AsyncQueue {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf,
) -> Poll<io::Result<()>> {
loop {
let mut guard = ready!(self.inner.poll_read_ready_mut(cx))?;
let rbuf = buf.initialize_unfilled();
match guard.try_io(|inner| inner.get_mut().read(rbuf)) {
Ok(res) => return Poll::Ready(res.map(|n| buf.advance(n))),
Err(_wb) => continue,
}
}
}
}
impl AsyncWrite for AsyncQueue {
fn poll_write(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
loop {
let mut guard = ready!(self.inner.poll_write_ready_mut(cx))?;
match guard.try_io(|inner| inner.get_mut().write(buf)) {
Ok(res) => return Poll::Ready(res),
Err(_wb) => continue,
}
}
}
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
loop {
let mut guard = ready!(self.inner.poll_write_ready_mut(cx))?;
match guard.try_io(|inner| inner.get_mut().flush()) {
Ok(res) => return Poll::Ready(res),
Err(_wb) => continue,
}
}
}
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}
}
-32
View File
@@ -1,32 +0,0 @@
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
//! Async specific modules.
use crate::error;
use crate::configuration::Configuration;
use crate::platform::create;
mod device;
pub use self::device::{AsyncDevice, AsyncQueue};
mod codec;
pub use self::codec::{TunPacket, TunPacketCodec};
/// Create a TUN device with the given name.
pub fn create_as_async(configuration: &Configuration) -> Result<AsyncDevice, error::Error> {
let device = create(&configuration)?;
AsyncDevice::new(device).map_err(|err| err.into())
}
+3 -4
View File
@@ -12,15 +12,14 @@
// //
// 0. You just DO WHAT THE FUCK YOU WANT TO. // 0. You just DO WHAT THE FUCK YOU WANT TO.
use std::io::{Read, Write};
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use crate::configuration::Configuration; use crate::configuration::Configuration;
use crate::error::*; use crate::error::*;
/// A TUN device. /// A TUN device.
pub trait Device: Read + Write { pub trait Device {
type Queue: Read + Write; type Queue ;
/// Reconfigure the device. /// Reconfigure the device.
fn configure(&mut self, config: &Configuration) -> Result<()> { fn configure(&mut self, config: &Configuration) -> Result<()> {
@@ -91,5 +90,5 @@ pub trait Device: Read + Write {
fn set_mtu(&mut self, value: i32) -> Result<()>; fn set_mtu(&mut self, value: i32) -> Result<()>;
/// Get a device queue. /// Get a device queue.
fn queue(&mut self, index: usize) -> Option<&mut Self::Queue>; fn queue(&self, index: usize) -> Option<&Self::Queue>;
} }
-21
View File
@@ -27,27 +27,6 @@ pub use crate::configuration::{Configuration, Layer};
pub mod platform; pub mod platform;
pub use crate::platform::create; pub use crate::platform::create;
#[cfg(all(
feature = "async",
any(
target_os = "linux",
target_os = "macos",
target_os = "ios",
target_os = "android"
)
))]
pub mod r#async;
#[cfg(all(
feature = "async",
any(
target_os = "linux",
target_os = "macos",
target_os = "ios",
target_os = "android"
)
))]
pub use r#async::*;
pub fn configure() -> Configuration { pub fn configure() -> Configuration {
Configuration::default() Configuration::default()
} }
@@ -1,214 +0,0 @@
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
#![allow(unused_variables)]
use std::io::{self, Read, Write};
use std::net::Ipv4Addr;
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
use std::sync::Arc;
use crate::configuration::Configuration;
use crate::device::Device as D;
use crate::error::*;
use crate::platform::posix::{self, Fd};
/// A TUN device for Android.
pub struct Device {
queue: Queue,
}
impl Device {
/// Create a new `Device` for the given `Configuration`.
pub fn new(config: &Configuration) -> Result<Self> {
let fd = match config.raw_fd {
Some(raw_fd) => raw_fd,
_ => return Err(Error::InvalidConfig),
};
let device = {
let tun = Fd::new(fd).map_err(|_| io::Error::last_os_error())?;
Device {
queue: Queue { tun: tun },
}
};
Ok(device)
}
/// Split the interface into a `Reader` and `Writer`.
pub fn split(self) -> (posix::Reader, posix::Writer) {
let fd = Arc::new(self.queue.tun);
(posix::Reader(fd.clone()), posix::Writer(fd.clone()))
}
/// Return whether the device has packet information
pub fn has_packet_information(&self) -> bool {
self.queue.has_packet_information()
}
/// Set non-blocking mode
pub fn set_nonblock(&self) -> io::Result<()> {
self.queue.set_nonblock()
}
}
impl Read for Device {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.queue.tun.read(buf)
}
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
self.queue.tun.read_vectored(bufs)
}
}
impl Write for Device {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.queue.tun.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.queue.tun.flush()
}
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
self.queue.tun.write_vectored(bufs)
}
}
impl D for Device {
type Queue = Queue;
fn name(&self) -> &str {
return "";
}
fn set_name(&mut self, value: &str) -> Result<()> {
Err(Error::NotImplemented)
}
fn enabled(&mut self, value: bool) -> Result<()> {
Ok(())
}
fn address(&self) -> Result<Ipv4Addr> {
Err(Error::NotImplemented)
}
fn set_address(&mut self, value: Ipv4Addr) -> Result<()> {
Ok(())
}
fn destination(&self) -> Result<Ipv4Addr> {
Err(Error::NotImplemented)
}
fn set_destination(&mut self, value: Ipv4Addr) -> Result<()> {
Ok(())
}
fn broadcast(&self) -> Result<Ipv4Addr> {
Err(Error::NotImplemented)
}
fn set_broadcast(&mut self, value: Ipv4Addr) -> Result<()> {
Ok(())
}
fn netmask(&self) -> Result<Ipv4Addr> {
Err(Error::NotImplemented)
}
fn set_netmask(&mut self, value: Ipv4Addr) -> Result<()> {
Ok(())
}
fn mtu(&self) -> Result<i32> {
Err(Error::NotImplemented)
}
fn set_mtu(&mut self, value: i32) -> Result<()> {
Ok(())
}
fn queue(&mut self, index: usize) -> Option<&mut Self::Queue> {
if index > 0 {
return None;
}
Some(&mut self.queue)
}
}
impl AsRawFd for Device {
fn as_raw_fd(&self) -> RawFd {
self.queue.as_raw_fd()
}
}
impl IntoRawFd for Device {
fn into_raw_fd(self) -> RawFd {
self.queue.into_raw_fd()
}
}
pub struct Queue {
tun: Fd,
}
impl Queue {
pub fn has_packet_information(&self) -> bool {
// on Android this is always the case
false
}
pub fn set_nonblock(&self) -> io::Result<()> {
self.tun.set_nonblock()
}
}
impl AsRawFd for Queue {
fn as_raw_fd(&self) -> RawFd {
self.tun.as_raw_fd()
}
}
impl IntoRawFd for Queue {
fn into_raw_fd(self) -> RawFd {
self.tun.into_raw_fd()
}
}
impl Read for Queue {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.tun.read(buf)
}
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
self.tun.read_vectored(bufs)
}
}
impl Write for Queue {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.tun.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.tun.flush()
}
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
self.tun.write_vectored(bufs)
}
}
@@ -1,30 +0,0 @@
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
//! Android specific functionality.
mod device;
pub use self::device::{Device, Queue};
use crate::configuration::Configuration as C;
use crate::error::*;
/// Android-only interface configuration.
#[derive(Copy, Clone, Default, Debug)]
pub struct Configuration {}
/// Create a TUN device with the given name.
pub fn create(configuration: &C) -> Result<Device> {
Device::new(&configuration)
}
-214
View File
@@ -1,214 +0,0 @@
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
#![allow(unused_variables)]
use std::io::{self, Read, Write};
use std::net::Ipv4Addr;
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
use std::sync::Arc;
use crate::configuration::Configuration;
use crate::device::Device as D;
use crate::error::*;
use crate::platform::posix::{self, Fd};
/// A TUN device for iOS.
pub struct Device {
queue: Queue,
}
impl Device {
/// Create a new `Device` for the given `Configuration`.
pub fn new(config: &Configuration) -> Result<Self> {
let fd = match config.raw_fd {
Some(raw_fd) => raw_fd,
_ => return Err(Error::InvalidConfig),
};
let mut device = unsafe {
let tun = Fd::new(fd).map_err(|_| io::Error::last_os_error())?;
Device {
queue: Queue { tun: tun },
}
};
Ok(device)
}
/// Split the interface into a `Reader` and `Writer`.
pub fn split(self) -> (posix::Reader, posix::Writer) {
let fd = Arc::new(self.queue.tun);
(posix::Reader(fd.clone()), posix::Writer(fd.clone()))
}
/// Return whether the device has packet information
pub fn has_packet_information(&self) -> bool {
self.queue.has_packet_information()
}
/// Set non-blocking mode
pub fn set_nonblock(&self) -> io::Result<()> {
self.queue.set_nonblock()
}
}
impl Read for Device {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.queue.tun.read(buf)
}
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
self.queue.tun.read_vectored(bufs)
}
}
impl Write for Device {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.queue.tun.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.queue.tun.flush()
}
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
self.queue.tun.write_vectored(bufs)
}
}
impl D for Device {
type Queue = Queue;
fn name(&self) -> &str {
return "";
}
fn set_name(&mut self, value: &str) -> Result<()> {
Err(Error::NotImplemented)
}
fn enabled(&mut self, value: bool) -> Result<()> {
Ok(())
}
fn address(&self) -> Result<Ipv4Addr> {
Err(Error::NotImplemented)
}
fn set_address(&mut self, value: Ipv4Addr) -> Result<()> {
Ok(())
}
fn destination(&self) -> Result<Ipv4Addr> {
Err(Error::NotImplemented)
}
fn set_destination(&mut self, value: Ipv4Addr) -> Result<()> {
Ok(())
}
fn broadcast(&self) -> Result<Ipv4Addr> {
Err(Error::NotImplemented)
}
fn set_broadcast(&mut self, value: Ipv4Addr) -> Result<()> {
Ok(())
}
fn netmask(&self) -> Result<Ipv4Addr> {
Err(Error::NotImplemented)
}
fn set_netmask(&mut self, value: Ipv4Addr) -> Result<()> {
Ok(())
}
fn mtu(&self) -> Result<i32> {
Err(Error::NotImplemented)
}
fn set_mtu(&mut self, value: i32) -> Result<()> {
Ok(())
}
fn queue(&mut self, index: usize) -> Option<&mut Self::Queue> {
if index > 0 {
return None;
}
Some(&mut self.queue)
}
}
impl AsRawFd for Device {
fn as_raw_fd(&self) -> RawFd {
self.queue.as_raw_fd()
}
}
impl IntoRawFd for Device {
fn into_raw_fd(self) -> RawFd {
self.queue.into_raw_fd()
}
}
pub struct Queue {
tun: Fd,
}
impl Queue {
pub fn has_packet_information(&self) -> bool {
// on ios this is always the case
true
}
pub fn set_nonblock(&self) -> io::Result<()> {
self.tun.set_nonblock()
}
}
impl AsRawFd for Queue {
fn as_raw_fd(&self) -> RawFd {
self.tun.as_raw_fd()
}
}
impl IntoRawFd for Queue {
fn into_raw_fd(self) -> RawFd {
self.tun.into_raw_fd()
}
}
impl Read for Queue {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.tun.read(buf)
}
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
self.tun.read_vectored(bufs)
}
}
impl Write for Queue {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.tun.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.tun.flush()
}
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
self.tun.write_vectored(bufs)
}
}
-30
View File
@@ -1,30 +0,0 @@
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// Version 2, December 2004
//
// Copyleft (ↄ) meh. <[email protected]> | http://meh.schizofreni.co
//
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
//
// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
//
// 0. You just DO WHAT THE FUCK YOU WANT TO.
//! iOS specific functionality.
mod device;
pub use self::device::{Device, Queue};
use crate::configuration::Configuration as C;
use crate::error::*;
/// iOS-only interface configuration.
#[derive(Copy, Clone, Default, Debug)]
pub struct Configuration {}
/// Create a TUN device with the given name.
pub fn create(configuration: &C) -> Result<Device> {
Device::new(&configuration)
}
+47 -120
View File
@@ -13,10 +13,10 @@
// 0. You just DO WHAT THE FUCK YOU WANT TO. // 0. You just DO WHAT THE FUCK YOU WANT TO.
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::io::{self, Read, Write}; use std::io;
use std::mem; use std::mem;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd}; use std::os::unix::io::AsRawFd;
use std::ptr; use std::ptr;
use std::sync::Arc; use std::sync::Arc;
use std::vec::Vec; use std::vec::Vec;
@@ -77,10 +77,10 @@ impl Device {
req.ifru.flags = device_type req.ifru.flags = device_type
| if config.platform.packet_information { | if config.platform.packet_information {
0 0
} else { } else {
IFF_NO_PI IFF_NO_PI
} }
| if queues_num > 1 { IFF_MULTI_QUEUE } else { 0 }; | if queues_num > 1 { IFF_MULTI_QUEUE } else { 0 };
for _ in 0..queues_num { for _ in 0..queues_num {
@@ -92,7 +92,7 @@ impl Device {
} }
queues.push(Queue { queues.push(Queue {
tun, tun: Arc::new(tun),
pi_enabled: config.platform.packet_information, pi_enabled: config.platform.packet_information,
}); });
} }
@@ -126,45 +126,40 @@ impl Device {
req req
} }
/// Make the device persistent. // /// Make the device persistent.
pub fn persist(&mut self) -> Result<()> { // pub fn persist(&mut self) -> Result<()> {
unsafe { // unsafe {
if tunsetpersist(self.as_raw_fd(), &1) < 0 { // if tunsetpersist(self.as_raw_fd(), &1) < 0 {
Err(io::Error::last_os_error().into()) // Err(io::Error::last_os_error().into())
} else { // } else {
Ok(()) // Ok(())
} // }
} // }
} // }
/// Set the owner of the device. // /// Set the owner of the device.
pub fn user(&mut self, value: i32) -> Result<()> { // pub fn user(&mut self, value: i32) -> Result<()> {
unsafe { // unsafe {
if tunsetowner(self.as_raw_fd(), &value) < 0 { // if tunsetowner(self.as_raw_fd(), &value) < 0 {
Err(io::Error::last_os_error().into()) // Err(io::Error::last_os_error().into())
} else { // } else {
Ok(()) // Ok(())
} // }
} // }
} // }
//
/// Set the group of the device. // /// Set the group of the device.
pub fn group(&mut self, value: i32) -> Result<()> { // pub fn group(&mut self, value: i32) -> Result<()> {
unsafe { // unsafe {
if tunsetgroup(self.as_raw_fd(), &value) < 0 { // if tunsetgroup(self.as_raw_fd(), &value) < 0 {
Err(io::Error::last_os_error().into()) // Err(io::Error::last_os_error().into())
} else { // } else {
Ok(()) // Ok(())
} // }
} // }
} // }
pub fn split(mut self) -> (posix::Reader, posix::Writer) {
let queue = self.queues.swap_remove(0);
let fd = Arc::new(queue.tun);
(posix::Reader(fd.clone()), posix::Writer(fd.clone()))
}
/// Return whether the device has packet information /// Return whether the device has packet information
pub fn has_packet_information(&mut self) -> bool { pub fn has_packet_information(&self) -> bool {
self.queues[0].has_packet_information() self.queues[0].has_packet_information()
} }
@@ -174,30 +169,6 @@ impl Device {
} }
} }
impl Read for Device {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.queues[0].read(buf)
}
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
self.queues[0].read_vectored(bufs)
}
}
impl Write for Device {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.queues[0].write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.queues[0].flush()
}
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
self.queues[0].write_vectored(bufs)
}
}
impl D for Device { impl D for Device {
type Queue = Queue; type Queue = Queue;
@@ -377,73 +348,29 @@ impl D for Device {
} }
} }
fn queue(&mut self, index: usize) -> Option<&mut Self::Queue> { fn queue(&self, index: usize) -> Option<&Self::Queue> {
self.queues.get_mut(index) self.queues.get(index)
}
}
impl AsRawFd for Device {
fn as_raw_fd(&self) -> RawFd {
self.queues[0].as_raw_fd()
}
}
impl IntoRawFd for Device {
fn into_raw_fd(mut self) -> RawFd {
// It is Ok to swap the first queue with the last one, because the self will be dropped afterwards
let queue = self.queues.swap_remove(0);
queue.into_raw_fd()
} }
} }
pub struct Queue { pub struct Queue {
tun: Fd, tun: Arc<Fd>,
pi_enabled: bool, pi_enabled: bool,
} }
impl Queue { impl Queue {
pub fn has_packet_information(&mut self) -> bool { pub fn has_packet_information(&self) -> bool {
self.pi_enabled self.pi_enabled
} }
pub fn set_nonblock(&self) -> io::Result<()> { pub fn set_nonblock(&self) -> io::Result<()> {
self.tun.set_nonblock() self.tun.set_nonblock()
} }
} pub fn reader(&self) -> posix::Reader {
posix::Reader(self.tun.clone())
impl Read for Queue {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.tun.read(buf)
} }
pub fn writer(&self) -> posix::Writer {
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> { posix::Writer(self.tun.clone())
self.tun.read_vectored(bufs)
}
}
impl Write for Queue {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.tun.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.tun.flush()
}
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
self.tun.write_vectored(bufs)
}
}
impl AsRawFd for Queue {
fn as_raw_fd(&self) -> RawFd {
self.tun.as_raw_fd()
}
}
impl IntoRawFd for Queue {
fn into_raw_fd(self) -> RawFd {
self.tun.into_raw_fd()
} }
} }
+85 -78
View File
@@ -14,15 +14,15 @@
#![allow(unused_variables)] #![allow(unused_variables)]
use std::ffi::CStr; use std::ffi::CStr;
use std::io::{self, Read, Write}; use std::io;
use std::mem; use std::mem;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd}; use std::os::unix::io::AsRawFd;
use std::ptr; use std::ptr;
use std::sync::Arc; use std::sync::Arc;
use libc; use libc;
use libc::{c_char, c_uint, c_void, sockaddr, socklen_t, AF_INET, SOCK_DGRAM}; use libc::{AF_INET, c_char, c_uint, c_void, SOCK_DGRAM, sockaddr, socklen_t};
use crate::configuration::{Configuration, Layer}; use crate::configuration::{Configuration, Layer};
use crate::device::Device as D; use crate::device::Device as D;
@@ -121,7 +121,7 @@ impl Device {
name: CStr::from_ptr(name.as_ptr() as *const c_char) name: CStr::from_ptr(name.as_ptr() as *const c_char)
.to_string_lossy() .to_string_lossy()
.into(), .into(),
queue: Queue { tun: tun }, queue: Queue { tun: Arc::new(tun) },
ctl: ctl, ctl: ctl,
} }
}; };
@@ -165,11 +165,11 @@ impl Device {
} }
} }
/// Split the interface into a `Reader` and `Writer`. // /// Split the interface into a `Reader` and `Writer`.
pub fn split(self) -> (posix::Reader, posix::Writer) { // pub fn split(self) -> (posix::Reader, posix::Writer) {
let fd = Arc::new(self.queue.tun); // let fd = Arc::new(self.queue.tun);
(posix::Reader(fd.clone()), posix::Writer(fd.clone())) // (posix::Reader(fd.clone()), posix::Writer(fd.clone()))
} // }
/// Return whether the device has packet information /// Return whether the device has packet information
pub fn has_packet_information(&self) -> bool { pub fn has_packet_information(&self) -> bool {
@@ -182,29 +182,29 @@ impl Device {
} }
} }
impl Read for Device { // impl Read for Device {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { // fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.queue.tun.read(buf) // self.queue.tun.read(buf)
} // }
//
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> { // fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
self.queue.tun.read_vectored(bufs) // self.queue.tun.read_vectored(bufs)
} // }
} // }
//
impl Write for Device { // impl Write for Device {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { // fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.queue.tun.write(buf) // self.queue.tun.write(buf)
} // }
//
fn flush(&mut self) -> io::Result<()> { // fn flush(&mut self) -> io::Result<()> {
self.queue.tun.flush() // self.queue.tun.flush()
} // }
//
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> { // fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
self.queue.tun.write_vectored(bufs) // self.queue.tun.write_vectored(bufs)
} // }
} // }
impl D for Device { impl D for Device {
type Queue = Queue; type Queue = Queue;
@@ -365,29 +365,29 @@ impl D for Device {
} }
} }
fn queue(&mut self, index: usize) -> Option<&mut Self::Queue> { fn queue(&self, index: usize) -> Option<&Self::Queue> {
if index > 0 { if index > 0 {
return None; return None;
} }
Some(&mut self.queue) Some(&self.queue)
} }
} }
impl AsRawFd for Device { // impl AsRawFd for Device {
fn as_raw_fd(&self) -> RawFd { // fn as_raw_fd(&self) -> RawFd {
self.queue.as_raw_fd() // self.queue.as_raw_fd()
} // }
} // }
//
impl IntoRawFd for Device { // impl IntoRawFd for Device {
fn into_raw_fd(self) -> RawFd { // fn into_raw_fd(self) -> RawFd {
self.queue.into_raw_fd() // self.queue.into_raw_fd()
} // }
} // }
pub struct Queue { pub struct Queue {
tun: Fd, tun: Arc<Fd>,
} }
impl Queue { impl Queue {
@@ -399,40 +399,47 @@ impl Queue {
pub fn set_nonblock(&self) -> io::Result<()> { pub fn set_nonblock(&self) -> io::Result<()> {
self.tun.set_nonblock() self.tun.set_nonblock()
} }
}
impl AsRawFd for Queue { pub fn reader(&self) -> posix::Reader {
fn as_raw_fd(&self) -> RawFd { posix::Reader(self.tun.clone())
self.tun.as_raw_fd() }
pub fn writer(&self) -> posix::Writer {
posix::Writer(self.tun.clone())
} }
} }
impl IntoRawFd for Queue { // impl AsRawFd for Queue {
fn into_raw_fd(self) -> RawFd { // fn as_raw_fd(&self) -> RawFd {
self.tun.into_raw_fd() // self.tun.as_raw_fd()
} // }
} // }
//
// impl IntoRawFd for Queue {
// fn into_raw_fd(self) -> RawFd {
// self.tun.into_raw_fd()
// }
// }
impl Read for Queue { // impl Read for Queue {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { // fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.tun.read(buf) // self.tun.read(buf)
} // }
//
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> { // fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
self.tun.read_vectored(bufs) // self.tun.read_vectored(bufs)
} // }
} // }
//
impl Write for Queue { // impl Write for Queue {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { // fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.tun.write(buf) // self.tun.write(buf)
} // }
//
fn flush(&mut self) -> io::Result<()> { // fn flush(&mut self) -> io::Result<()> {
self.tun.flush() // self.tun.flush()
} // }
//
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> { // fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
self.tun.write_vectored(bufs) // self.tun.write_vectored(bufs)
} // }
} // }
+32 -17
View File
@@ -12,22 +12,24 @@
// //
// 0. You just DO WHAT THE FUCK YOU WANT TO. // 0. You just DO WHAT THE FUCK YOU WANT TO.
use std::io::{self, Read, Write}; use std::io;
use std::mem; use std::mem;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd,RawFd};
use std::sync::Arc; use std::sync::Arc;
use crate::platform::posix::Fd; use crate::platform::posix::Fd;
use libc; use libc;
/// Read-only end for a file descriptor. /// Read-only end for a file descriptor.
#[derive(Clone)]
pub struct Reader(pub(crate) Arc<Fd>); pub struct Reader(pub(crate) Arc<Fd>);
/// Write-only end for a file descriptor. /// Write-only end for a file descriptor.
#[derive(Clone)]
pub struct Writer(pub(crate) Arc<Fd>); pub struct Writer(pub(crate) Arc<Fd>);
impl Read for Reader { impl Reader {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
unsafe { unsafe {
let amount = libc::read(self.0.as_raw_fd(), buf.as_mut_ptr() as *mut _, buf.len()); let amount = libc::read(self.0.as_raw_fd(), buf.as_mut_ptr() as *mut _, buf.len());
@@ -39,7 +41,7 @@ impl Read for Reader {
} }
} }
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> { pub fn read_vectored(&self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
unsafe { unsafe {
let mut msg: libc::msghdr = mem::zeroed(); let mut msg: libc::msghdr = mem::zeroed();
// msg.msg_name: NULL // msg.msg_name: NULL
@@ -57,8 +59,8 @@ impl Read for Reader {
} }
} }
impl Write for Writer { impl Writer {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
unsafe { unsafe {
let amount = libc::write(self.0.as_raw_fd(), buf.as_ptr() as *const _, buf.len()); let amount = libc::write(self.0.as_raw_fd(), buf.as_ptr() as *const _, buf.len());
@@ -70,11 +72,8 @@ impl Write for Writer {
} }
} }
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> { pub fn write_vectored(&self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
unsafe { unsafe {
let mut msg: libc::msghdr = mem::zeroed(); let mut msg: libc::msghdr = mem::zeroed();
// msg.msg_name = NULL // msg.msg_name = NULL
@@ -90,6 +89,22 @@ impl Write for Writer {
Ok(n as usize) Ok(n as usize)
} }
} }
pub fn write_all(&self, mut buf: &[u8]) -> io::Result<()> {
while !buf.is_empty() {
match self.write(buf) {
Ok(0) => {
return Err(io::Error::new(
io::ErrorKind::WriteZero,
"failed to write whole buffer",
));
}
Ok(n) => buf = &buf[n..],
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
} }
impl AsRawFd for Reader { impl AsRawFd for Reader {
@@ -97,9 +112,9 @@ impl AsRawFd for Reader {
self.0.as_raw_fd() self.0.as_raw_fd()
} }
} }
//
impl AsRawFd for Writer { // impl AsRawFd for Writer {
fn as_raw_fd(&self) -> RawFd { // fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd() // self.0.as_raw_fd()
} // }
} // }
+5 -5
View File
@@ -4,9 +4,9 @@ use std::sync::Arc;
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use crossbeam_skiplist::SkipMap; use crossbeam_skiplist::SkipMap;
use parking_lot::Mutex; use parking_lot::Mutex;
use nat_traversal::boot::Boot; use p2p_channel::boot::Boot;
use nat_traversal::channel::{Channel, Route, RouteKey}; use p2p_channel::channel::{Channel, Route, RouteKey};
use nat_traversal::punch::NatInfo; use p2p_channel::punch::NatInfo;
use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, recv_handler, registration_handler, tun_handler}; use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, recv_handler, registration_handler, tun_handler};
use crate::nat::NatTest; use crate::nat::NatTest;
use crate::tun_device; use crate::tun_device;
@@ -28,7 +28,7 @@ pub struct Switch {
impl Switch { impl Switch {
pub fn start(config: Config) -> crate::Result<Switch> { pub fn start(config: Config) -> crate::Result<Switch> {
let (mut channel, punch, idle) = Boot::new::<Ipv4Addr>(100, 9000, 0)?; let (mut channel, punch, idle) = Boot::new::<Ipv4Addr>(80, 15000, 0)?;
let response = registration_handler::registration(&mut channel, config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone())?; let response = registration_handler::registration(&mut channel, config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone())?;
let register = Arc::new(registration_handler::Register::new(channel.sender()?, config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone())); let register = Arc::new(registration_handler::Register::new(channel.sender()?, config.server_address, config.token.clone(), config.device_id.clone(), config.name.clone()));
let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> = Arc::new(Mutex::new((0, Vec::new()))); let device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>> = Arc::new(Mutex::new((0, Vec::new())));
@@ -109,7 +109,7 @@ impl Switch {
self.nat_channel.route_to_id(route_key) self.nat_channel.route_to_id(route_key)
} }
pub fn route_table(&self) -> Vec<(Ipv4Addr, Route)> { pub fn route_table(&self) -> Vec<(Ipv4Addr, Route)> {
self.nat_channel.route_list() self.nat_channel.route_table()
} }
pub fn stop(&self) -> io::Result<()> { pub fn stop(&self) -> io::Result<()> {
self.tun_reader.close(); self.tun_reader.close();
+13 -9
View File
@@ -7,10 +7,10 @@ use chrono::Local;
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use parking_lot::Mutex; use parking_lot::Mutex;
use rand::prelude::SliceRandom; use rand::prelude::SliceRandom;
use nat_traversal::channel::Route;
use nat_traversal::channel::sender::Sender; use p2p_channel::channel::Route;
use nat_traversal::idle::Idle; use p2p_channel::channel::sender::Sender;
use p2p_channel::idle::Idle;
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo}; use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, Version}; use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, Version};
@@ -26,9 +26,11 @@ pub fn start_idle(idle: Idle<Ipv4Addr>, sender: Sender<Ipv4Addr>) {
fn start_idle_(idle: Idle<Ipv4Addr>, sender: Sender<Ipv4Addr>) -> io::Result<()> { fn start_idle_(idle: Idle<Ipv4Addr>, sender: Sender<Ipv4Addr>) -> io::Result<()> {
loop { loop {
let (idle_status, peer_ip, route) = idle.next_idle()?; let (idle_status, peer_ips, route) = idle.next_idle()?;
log::warn!("peer_ip:{:?},route:{:?},idle_status:{:?}",peer_ip,route,idle_status); log::warn!("peer_ip:{:?},route:{:?},idle_status:{:?}",peer_ips,route,idle_status);
sender.remove_route(&peer_ip); for peer_ip in peer_ips {
sender.remove_route(&peer_ip);
}
} }
} }
@@ -68,7 +70,7 @@ fn start_heartbeat_(sender: Sender<Ipv4Addr>, device_list: Arc<Mutex<(u16, Vec<P
let _ = sender.send_to_addr(net_packet.buffer(), current_device.connect_server); let _ = sender.send_to_addr(net_packet.buffer(), current_device.connect_server);
//再随机发送到其他地址,看有没有客户端符合转发条件 //再随机发送到其他地址,看有没有客户端符合转发条件
let route_list = route_list.get_or_insert_with(|| { let route_list = route_list.get_or_insert_with(|| {
let mut l = sender.route_list(); let mut l = sender.route_table();
l.shuffle(&mut rand::thread_rng()); l.shuffle(&mut rand::thread_rng());
l l
}); });
@@ -84,21 +86,23 @@ fn start_heartbeat_(sender: Sender<Ipv4Addr>, device_list: Arc<Mutex<(u16, Vec<P
} }
} }
} }
thread::sleep(Duration::from_millis(1));
} }
net_packet.set_destination(current_device.virtual_gateway()); net_packet.set_destination(current_device.virtual_gateway());
if let Err(e) = sender.send_to_addr(net_packet.buffer(), current_device.connect_server) { if let Err(e) = sender.send_to_addr(net_packet.buffer(), current_device.connect_server) {
log::warn!("connect_server:{:?},e:{:?}",current_device.connect_server,e); log::warn!("connect_server:{:?},e:{:?}",current_device.connect_server,e);
} }
} else { } else {
for (peer_ip, route) in sender.route_list().iter() { for (peer_ip, route) in sender.route_table().iter() {
net_packet.set_destination(*peer_ip); net_packet.set_destination(*peer_ip);
if let Err(e) = sender.send_to_route(net_packet.buffer(), &route.route_key()) { if let Err(e) = sender.send_to_route(net_packet.buffer(), &route.route_key()) {
log::warn!("peer_ip:{:?},route:{:?},e:{:?}",peer_ip,route,e); log::warn!("peer_ip:{:?},route:{:?},e:{:?}",peer_ip,route,e);
} }
thread::sleep(Duration::from_millis(1));
} }
} }
count += 1; count += 1;
thread::sleep(Duration::from_secs(5)); thread::sleep(Duration::from_millis(5000));
} }
} }
+2 -2
View File
@@ -6,8 +6,8 @@ use crossbeam::atomic::AtomicCell;
use parking_lot::Mutex; use parking_lot::Mutex;
use protobuf::Message; use protobuf::Message;
use rand::prelude::SliceRandom; use rand::prelude::SliceRandom;
use nat_traversal::channel::sender::Sender; use p2p_channel::channel::sender::Sender;
use nat_traversal::punch::{NatInfo, NatType, Punch}; use p2p_channel::punch::{NatInfo, NatType, Punch};
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo}; use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
use crate::nat::NatTest; use crate::nat::NatTest;
use crate::proto::message::{PunchInfo, PunchNatType}; use crate::proto::message::{PunchInfo, PunchNatType};
+4 -4
View File
@@ -8,8 +8,8 @@ use crossbeam_skiplist::SkipMap;
use parking_lot::Mutex; use parking_lot::Mutex;
use protobuf::Message; use protobuf::Message;
use nat_traversal::channel::{Channel, Route, RouteKey}; use p2p_channel::channel::{Channel, Route, RouteKey};
use nat_traversal::punch::NatInfo; use p2p_channel::punch::NatInfo;
use packet::icmp::{icmp, Kind}; use packet::icmp::{icmp, Kind};
use packet::ip::ipv4; use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet; use packet::ip::ipv4::packet::IpV4Packet;
@@ -221,7 +221,7 @@ impl RecvHandler {
}) })
.collect(); .collect();
let mut dev = self.device_list.lock(); let mut dev = self.device_list.lock();
if dev.0 < device_list_t.epoch as u16 || device_list_t.epoch as u16 - dev.0 > u16::MAX >> 2 { if dev.0 != device_list_t.epoch as u16 {
dev.0 = device_list_t.epoch as u16; dev.0 = device_list_t.epoch as u16;
dev.1 = ip_list; dev.1 = ip_list;
} }
@@ -357,7 +357,7 @@ impl RecvHandler {
net_packet.set_source(current_device.virtual_ip()); net_packet.set_source(current_device.virtual_ip());
net_packet.set_destination(source); net_packet.set_destination(source);
net_packet.set_payload(&bytes); net_packet.set_payload(&bytes);
if !peer_nat_info.local_ip.is_unspecified() { if !peer_nat_info.local_ip.is_unspecified() && peer_nat_info.local_port != 0 {
let mut packet = NetPacket::new([0u8; 12])?; let mut packet = NetPacket::new([0u8; 12])?;
packet.set_version(Version::V1); packet.set_version(Version::V1);
packet.first_set_ttl(1); packet.first_set_ttl(1);
+2 -2
View File
@@ -5,8 +5,8 @@ use std::time::Duration;
use chrono::Local; use chrono::Local;
use protobuf::Message; use protobuf::Message;
use nat_traversal::channel::Channel; use p2p_channel::channel::Channel;
use nat_traversal::channel::sender::Sender; use p2p_channel::channel::sender::Sender;
use crate::error::*; use crate::error::*;
use crate::proto::message::{RegistrationRequest, RegistrationResponse}; use crate::proto::message::{RegistrationRequest, RegistrationResponse};
+26 -3
View File
@@ -4,7 +4,7 @@ use std::net::Ipv4Addr;
use std::sync::Arc; use std::sync::Arc;
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use nat_traversal::channel::sender::Sender; use p2p_channel::channel::sender::Sender;
use packet::icmp::icmp::IcmpPacket; use packet::icmp::icmp::IcmpPacket;
use packet::icmp::Kind; use packet::icmp::Kind;
use packet::ip::ipv4; use packet::ip::ipv4;
@@ -59,8 +59,8 @@ fn handle(sender: &Sender<Ipv4Addr>, data: &mut [u8], tun_writer: &TunWriter, cu
net_packet.set_destination(dest_ip); net_packet.set_destination(dest_ip);
net_packet.set_payload(ipv4_packet.buffer); net_packet.set_payload(ipv4_packet.buffer);
//优先发到直连到地址 //优先发到直连到地址
if sender.send_to_id(&net_packet.buffer()[..(4 + 8 + data_len)], &dest_ip).is_err() { if sender.send_to_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip).is_err() {
sender.send_to_addr(&net_packet.buffer()[..(4 + 8 + data_len)], current_device.connect_server)?; sender.send_to_addr(&net_packet.buffer()[..(12 + data_len)], current_device.connect_server)?;
} }
return Ok(()); return Ok(());
} }
@@ -76,6 +76,7 @@ pub fn start(sender: Sender<Ipv4Addr>,
}); });
} }
#[cfg(target_os = "windows")]
fn start_(sender: Sender<Ipv4Addr>, fn start_(sender: Sender<Ipv4Addr>,
tun_reader: TunReader, tun_reader: TunReader,
tun_writer: TunWriter, tun_writer: TunWriter,
@@ -95,3 +96,25 @@ fn start_(sender: Sender<Ipv4Addr>,
} }
} }
} }
#[cfg(any(target_os = "linux",target_os = "macos"))]
fn start_(sender: Sender<Ipv4Addr>,
tun_reader: TunReader,
tun_writer: TunWriter,
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, ) -> io::Result<()> {
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Ipv4Turn);
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into());
net_packet.set_ttl(MAX_TTL);
let mut buf = [0; 4096];
loop {
let data = tun_reader.read(&mut buf)?;
match handle(&sender, data, &tun_writer, current_device.load(), &mut net_packet) {
Ok(_) => {}
Err(e) => {
log::warn!("{:?}", e)
}
}
}
}
+2 -356
View File
@@ -1,25 +1,7 @@
use crate::error::Error; use crate::error::Error;
// use std::io;
// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket}; pub use p2p_channel::channel::{Route, RouteKey};
// use std::sync::atomic::Ordering;
// use std::sync::Arc;
// use std::time::Duration;
//
// use crossbeam::atomic::AtomicCell;
// use crossbeam::sync::WaitGroup;
// use parking_lot::Mutex;
// use tokio::sync::watch;
//
// use error::*;
//
// use crate::handle::registration_handler::CONNECTION_STATUS;
// use crate::handle::{
// ApplicationStatus, ConnectStatus, CurrentDeviceInfo, NatInfo, PeerDeviceInfo, Route, RouteType,
// DEVICE_LIST, DIRECT_ROUTE_TABLE, NAT_INFO, SERVER_RT,
// };
// use crate::nat::channel::NatChannel;
pub use nat_traversal::channel::{Route, RouteKey};
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
@@ -30,339 +12,3 @@ pub mod proto;
pub mod protocol; pub mod protocol;
pub mod tun_device; pub mod tun_device;
pub mod core; pub mod core;
//
// #[derive(Clone, Debug)]
// pub struct Config<F> {
// pub token: String,
// pub mac_address: String,
// pub name: String,
// pub server_address: SocketAddr,
// pub nat_test_server: Vec<SocketAddr>,
// pub abnormal_call: F,
// }
//
// impl<F> Config<F> {
// pub fn new(
// token: String,
// mac_address: String,
// name: Option<String>,
// server_address: SocketAddr,
// nat_test_server: Vec<SocketAddr>,
// abnormal_call: F,
// ) -> Result<Self>
// where
// F: FnOnce() + Send + 'static,
// {
// if token.is_empty() || token.len() > 64 {
// return Err(Error::Stop("token invalid".to_string()));
// }
// if mac_address.len() != 12 + 5 {
// return Err(Error::Stop("mac_address invalid".to_string()));
// }
// if let Some(name) = name {
// if name.is_empty() || name.len() > 64 {
// return Err(Error::Stop("name invalid".to_string()));
// }
// Ok(Self {
// token,
// mac_address,
// name,
// server_address,
// nat_test_server,
// abnormal_call,
// })
// } else {
// let info = os_info::get();
// let name = if info.version() != &os_info::Version::Unknown {
// format!("{} {}", info.os_type(), info.version())
// } else {
// format!("{}", info.os_type())
// };
// Ok(Self {
// token,
// mac_address,
// name,
// server_address,
// nat_test_server,
// abnormal_call,
// })
// }
// }
// }
//
// pub struct Switch {
// current_device: CurrentDeviceInfo,
// status_sender: Arc<Mutex<watch::Sender<ApplicationStatus>>>,
// wait_group: WaitGroup,
// runtime: Option<tokio::runtime::Runtime>,
// }
//
// impl Switch {
// pub fn start<F>(config: Config<F>) -> Result<Self>
// where
// F: FnOnce() + Send + 'static,
// {
// let runtime = tokio::runtime::Builder::new_multi_thread()
// .enable_all()
// .build()
// .unwrap();
// todo!()
// // return match runtime.block_on(Switch::start_(config)) {
// // Ok(mut switch) => {
// // switch.runtime = Some(runtime);
// // Ok(switch)
// // }
// // Err(e) => Err(e),
// // };
// }
// pub fn stop(self) {
// Self::call_stop(self.status_sender);
// self.wait_group.wait();
// }
// pub fn stop_async(&self) {
// Self::call_stop(self.status_sender.clone());
// }
// pub fn current_device(&self) -> &CurrentDeviceInfo {
// &self.current_device
// }
// pub fn nat_info(&self) -> Option<NatInfo> {
// NAT_INFO.lock().clone()
// }
// pub fn server_rt(&self) -> i64 {
// SERVER_RT.load(Ordering::Relaxed)
// }
// pub fn connection_status(&self) -> ConnectStatus {
// CONNECTION_STATUS.load()
// }
// pub fn device_list(&self) -> Vec<PeerDeviceInfo> {
// let device_list_lock = DEVICE_LIST.lock();
// let (_epoch, device_list) = device_list_lock.clone();
// drop(device_list_lock);
// device_list
// }
// pub fn route(&self, ip: &Ipv4Addr) -> Route {
// if let Some(route_ref) = DIRECT_ROUTE_TABLE.get(ip) {
// route_ref.value().clone()
// } else {
// let mut route = Route::new(self.current_device.connect_server);
// route.route_type = RouteType::ServerRelay;
// route.rt = self.server_rt() * 2;
// route.recv_time = -1;
// route
// }
// }
// }
//
// impl Switch {
// fn call_stop(status_sender: Arc<Mutex<watch::Sender<ApplicationStatus>>>) -> bool {
// let lock = status_sender.lock();
// let status = lock.send_replace(ApplicationStatus::Stopping);
// return status == ApplicationStatus::Starting;
// }
// // pub async fn start_<F>(config: Config<F>) -> Result<Self>
// // where
// // F: FnOnce() + Send + 'static,
// // {
// // // let server_address = "nat1.wherewego.top:29876"
// // // let server_address = "nat1.wherewego.top:29875".to_socket_addrs().unwrap().next().unwrap();
// // let server_address = config.server_address;
// // let nat_channel = NatChannel::new(server_address,100,).await?;
// // //注册
// // let response = handle::registration_handler::registration(
// // &udp,
// // server_address,
// // config.token,
// // config.mac_address,
// // config.name,
// // )?;
// // {
// // let ip_list = response
// // .device_info_list
// // .into_iter()
// // .map(|info| {
// // PeerDeviceInfo::new(
// // Ipv4Addr::from(info.virtual_ip),
// // info.name,
// // info.device_status as u8,
// // )
// // })
// // .collect();
// // let mut dev = DEVICE_LIST.lock();
// // dev.0 = response.epoch;
// // dev.1 = ip_list;
// // }
// // let virtual_ip = Ipv4Addr::from(response.virtual_ip);
// // let virtual_gateway = Ipv4Addr::from(response.virtual_gateway);
// // let virtual_netmask = Ipv4Addr::from(response.virtual_netmask);
// // let (status_sender, status_receiver) = watch::channel(ApplicationStatus::Starting);
// // let current_device =
// // CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, server_address);
// // let wait_group = WaitGroup::new();
// // let status_sender = Arc::new(parking_lot::const_mutex(status_sender));
// // let call = Arc::new(AtomicCell::new(Some(config.abnormal_call)));
// // //心跳线程
// // {
// // let udp = udp.try_clone()?;
// // let wait_group1 = wait_group.clone();
// // let status_sender1 = status_sender.clone();
// // let call1 = call.clone();
// // handle::heartbeat_handler::start(
// // status_receiver.clone(),
// // udp,
// // current_device,
// // move || {
// // if Self::call_stop(status_sender1) {
// // if let Some(call) = call1.take() {
// // call();
// // }
// // }
// // drop(wait_group1);
// // },
// // )
// // .await;
// // }
// // //初始化nat数据
// // handle::init_nat_test_addr(config.nat_test_server);
// // handle::init_nat_info(response.public_ip, response.public_port as u16);
// // // tun服务
// // let (tun_writer, tun_reader) =
// // tun_device::create_tun(virtual_ip, virtual_netmask, virtual_gateway)?;
// // // 打洞数据通道
// // let (punch_sender, cone_receiver, req_symmetric_receiver, res_symmetric_receiver) =
// // handle::punch_handler::bounded();
// // //udp数据处理
// // {
// // // 低优先级的udp数据通道
// // let (sender, receiver) = tokio::sync::mpsc::channel(50);
// // let udp1 = udp.try_clone()?;
// // let wait_group1 = wait_group.clone();
// // let status_sender1 = status_sender.clone();
// // let call1 = call.clone();
// // handle::udp_recv_handler::udp_recv_start(
// // status_receiver.clone(),
// // udp1,
// // server_address,
// // sender,
// // tun_writer,
// // current_device,
// // move || {
// // if Self::call_stop(status_sender1) {
// // if let Some(call) = call1.take() {
// // call();
// // }
// // }
// // drop(wait_group1);
// // },
// // )
// // .await;
// // let udp1 = udp.try_clone()?;
// // let wait_group1 = wait_group.clone();
// // let status_sender1 = status_sender.clone();
// // let call1 = call.clone();
// // handle::udp_recv_handler::udp_other_recv_start(
// // status_receiver.clone(),
// // udp1,
// // receiver,
// // current_device,
// // punch_sender,
// // move || {
// // if Self::call_stop(status_sender1) {
// // if let Some(call) = call1.take() {
// // call();
// // }
// // }
// // drop(wait_group1);
// // },
// // )
// // .await;
// // }
// // //打洞处理
// // {
// // let udp1 = udp.try_clone()?;
// // let wait_group1 = wait_group.clone();
// // let status_sender1 = status_sender.clone();
// // let call1 = call.clone();
// // handle::punch_handler::cone_handler_start(
// // status_receiver.clone(),
// // cone_receiver,
// // udp1,
// // current_device,
// // move || {
// // if Self::call_stop(status_sender1) {
// // if let Some(call) = call1.take() {
// // call();
// // }
// // }
// // drop(wait_group1);
// // },
// // )
// // .await;
// // let udp1 = udp.try_clone()?;
// // let wait_group1 = wait_group.clone();
// // let status_sender1 = status_sender.clone();
// // let call1 = call.clone();
// // handle::punch_handler::req_symmetric_handler_start(
// // status_receiver.clone(),
// // req_symmetric_receiver,
// // udp1,
// // current_device,
// // move || {
// // if Self::call_stop(status_sender1) {
// // if let Some(call) = call1.take() {
// // call();
// // }
// // }
// // drop(wait_group1);
// // },
// // )
// // .await;
// // let udp1 = udp.try_clone()?;
// // let wait_group1 = wait_group.clone();
// // let status_sender1 = status_sender.clone();
// // let call1 = call.clone();
// // handle::punch_handler::res_symmetric_handler_start(
// // status_receiver.clone(),
// // res_symmetric_receiver,
// // udp1,
// // current_device,
// // move || {
// // if Self::call_stop(status_sender1) {
// // if let Some(call) = call1.take() {
// // call();
// // }
// // }
// // drop(wait_group1);
// // },
// // )
// // .await;
// // }
// // //tun数据处理
// // {
// // let wait_group1 = wait_group.clone();
// // let status_sender1 = status_sender.clone();
// // let call1 = call.clone();
// // handle::tun_handler::handler_start(
// // status_receiver.clone(),
// // udp,
// // tun_reader,
// // current_device,
// // move || {
// // if Self::call_stop(status_sender1) {
// // if let Some(call) = call1.take() {
// // call();
// // }
// // }
// // drop(wait_group1);
// // },
// // )
// // .await;
// // }
// // Ok(Switch {
// // current_device,
// // status_sender,
// // wait_group,
// // runtime: None,
// // })
// // }
// }
+1 -1
View File
@@ -2,7 +2,7 @@ use std::collections::HashSet;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket}; use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use std::time::Duration; use std::time::Duration;
use std::{io, thread}; use std::{io, thread};
use nat_traversal::punch::NatType; use p2p_channel::punch::NatType;
// #[derive(Debug, Copy, Clone, PartialEq)] // #[derive(Debug, Copy, Clone, PartialEq)]
+1 -1
View File
@@ -1,7 +1,7 @@
use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::Arc; use std::sync::Arc;
use parking_lot::Mutex; use parking_lot::Mutex;
use nat_traversal::punch::{NatInfo, NatType}; use p2p_channel::punch::{NatInfo, NatType};
use crate::proto::message::PunchNatType; use crate::proto::message::PunchNatType;
pub mod check; pub mod check;
+3 -2
View File
@@ -86,6 +86,7 @@ impl Into<u8> for Protocol {
} }
pub const MAX_TTL: u8 = 0b1111; pub const MAX_TTL: u8 = 0b1111;
pub const MAX_SOURCE: u8 = 0b11110000;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct NetPacket<B> { pub struct NetPacket<B> {
@@ -152,10 +153,10 @@ impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
self.buffer.as_mut()[3] = ttl << 4 | ttl; self.buffer.as_mut()[3] = ttl << 4 | ttl;
} }
pub fn set_ttl(&mut self, ttl: u8) { pub fn set_ttl(&mut self, ttl: u8) {
self.buffer.as_mut()[3] = MAX_TTL & ttl; self.buffer.as_mut()[3] = (self.buffer.as_mut()[3] & MAX_SOURCE) | (MAX_TTL & ttl);
} }
pub fn set_source_ttl(&mut self, source_ttl: u8) { pub fn set_source_ttl(&mut self, source_ttl: u8) {
self.buffer.as_mut()[3] = (source_ttl << 4) | self.buffer.as_ref()[3]; self.buffer.as_mut()[3] = (source_ttl << 4) | (MAX_TTL & self.buffer.as_ref()[3]);
} }
pub fn set_source(&mut self, source: Ipv4Addr) { pub fn set_source(&mut self, source: Ipv4Addr) {
self.buffer.as_mut()[4..8].copy_from_slice(&source.octets()); self.buffer.as_mut()[4..8].copy_from_slice(&source.octets());
+13 -7
View File
@@ -1,5 +1,8 @@
use crate::tun_device::{TunReader, TunWriter}; use crate::tun_device::{TunReader, TunWriter};
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::sync::Arc;
use tun::Device;
use parking_lot::Mutex;
pub fn create_tun( pub fn create_tun(
address: Ipv4Addr, address: Ipv4Addr,
@@ -13,17 +16,20 @@ pub fn create_tun(
.address(address) .address(address)
.netmask(netmask) .netmask(netmask)
.mtu(1420) .mtu(1420)
// .queues(2)
.up(); .up();
//
// config.platform(|config| {
// config.packet_information(true);
// });
config.platform(|config| { let dev = tun::create(&config).unwrap();
config.packet_information(true);
});
let mut dev = tun::create(&config).unwrap();
let packet_information = dev.has_packet_information(); let packet_information = dev.has_packet_information();
let (reader, writer) = dev.split(); let queue = dev.queue(0).unwrap();
let reader = queue.reader();
let writer = queue.writer();
Ok(( Ok((
TunWriter(writer, packet_information), TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
TunReader(reader, packet_information), TunReader(reader, packet_information),
)) ))
} }
+33 -30
View File
@@ -1,7 +1,9 @@
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::process::Command; use std::process::Command;
use std::io;
use tun::Device; use tun::Device;
use parking_lot::Mutex;
use std::sync::Arc;
use crate::tun_device::{TunReader, TunWriter}; use crate::tun_device::{TunReader, TunWriter};
@@ -20,33 +22,7 @@ pub fn create_tun(
.up(); .up();
let dev = tun::create(&config).unwrap(); let dev = tun::create(&config).unwrap();
let up_eth_str: String = format!("ifconfig {} {:?} {:?} up ", dev.name(), address, gateway); config_ip(dev.name(), address, netmask, gateway)?;
let route_add_str: String = format!(
"sudo route -n add -net {:?} -netmask {:?} {:?}",
address, netmask, gateway
);
let up_eth_out = Command::new("sh")
.arg("-c")
.arg(up_eth_str)
.output()
.expect("sh exec error!");
if !up_eth_out.status.success() {
return Err(crate::error::Error::Stop(format!(
"设置地址失败:{:?}",
up_eth_out
)));
}
let if_config_out = Command::new("sh")
.arg("-c")
.arg(route_add_str)
.output()
.expect("sh exec error!");
if !if_config_out.status.success() {
return Err(crate::error::Error::Stop(format!(
"设置路由失败:{:?}",
if_config_out
)));
}
// println!("{:?}", if_config_out); // println!("{:?}", if_config_out);
// let cmd_str: String = " ifconfig|grep flags=8051|awk -F ':' '{print $1}'|tail -1".to_string(); // let cmd_str: String = " ifconfig|grep flags=8051|awk -F ':' '{print $1}'|tail -1".to_string();
// //
@@ -60,9 +36,36 @@ pub fn create_tun(
// } // }
// println!("{:?}", cmd_str_out); // println!("{:?}", cmd_str_out);
let packet_information = dev.has_packet_information(); let packet_information = dev.has_packet_information();
let (reader, writer) = dev.split(); let queue = dev.queue(0).unwrap();
let reader = queue.reader();
let writer = queue.writer();
Ok(( Ok((
TunWriter(writer, packet_information), TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
TunReader(reader, packet_information), TunReader(reader, packet_information),
)) ))
} }
pub(crate) fn config_ip(name: &str, address: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
let up_eth_str: String = format!("ifconfig {} {:?} {:?} up ", name, address, gateway);
let route_add_str: String = format!(
"sudo route -n add -net {:?} -netmask {:?} {:?}",
address, netmask, gateway
);
let up_eth_out = Command::new("sh")
.arg("-c")
.arg(up_eth_str)
.output()
.expect("sh exec error!");
if !up_eth_out.status.success() {
return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: {:?}", up_eth_out)));
}
let if_config_out = Command::new("sh")
.arg("-c")
.arg(route_add_str)
.output()
.expect("sh exec error!");
if !if_config_out.status.success() {
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", if_config_out)));
}
Ok(())
}
+41 -4
View File
@@ -1,13 +1,21 @@
use std::io; use std::io;
use std::io::{Read, Write}; use std::sync::Arc;
use bytes::BufMut; use bytes::BufMut;
use tun::platform::posix::{Reader, Writer}; use tun::platform::posix::{Reader, Writer};
use std::net::Ipv4Addr;
use std::os::unix::io::AsRawFd;
#[cfg(any(target_os = "linux", target_os = "android"))]
use tun::platform::linux::Device;
#[cfg(any(target_os = "macos", target_os = "ios"))]
use tun::platform::macos::Device;
use parking_lot::Mutex;
#[derive(Clone)]
pub struct TunReader(pub(crate) Reader, pub(crate) bool); pub struct TunReader(pub(crate) Reader, pub(crate) bool);
impl TunReader { impl TunReader {
pub fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> io::Result<&mut [u8]> { pub fn read<'a>(&'a self, buf: &'a mut [u8]) -> io::Result<&mut [u8]> {
let len = self.0.read(buf)?; let len = self.0.read(buf)?;
if self.1 { if self.1 {
Ok(&mut buf[4..len]) Ok(&mut buf[4..len])
@@ -15,12 +23,22 @@ impl TunReader {
Ok(&mut buf[..len]) Ok(&mut buf[..len])
} }
} }
pub fn close(&self) {
unsafe {
let raw = self.0.as_raw_fd();
if raw >= 0 {
libc::close(raw);
}
}
}
} }
pub struct TunWriter(pub(crate) Writer, pub(crate) bool);
#[derive(Clone)]
pub struct TunWriter(pub(crate) Writer, pub(crate) bool, pub(crate) Arc<Mutex<Device>>);
impl TunWriter { impl TunWriter {
pub fn write(&mut self, packet: &[u8]) -> io::Result<()> { pub fn write(&self, packet: &[u8]) -> io::Result<()> {
if self.1 { if self.1 {
let mut buf = Vec::<u8>::with_capacity(4 + packet.len()); let mut buf = Vec::<u8>::with_capacity(4 + packet.len());
buf.put_u16(0); buf.put_u16(0);
@@ -34,4 +52,23 @@ impl TunWriter {
self.0.write_all(packet) self.0.write_all(packet)
} }
} }
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
let mut config = tun::Configuration::default();
use tun::Device;
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(1420)
// .queues(2)
.up();
let mut dev = self.2.lock();
if let Err(e) = dev.configure(&config) {
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
}
#[cfg(target_os = "macos")]
crate::tun_device::mac::config_ip(dev.name(), address, netmask, gateway);
return Ok(());
}
} }
+6 -4
View File
@@ -3,10 +3,11 @@ use std::net::Ipv4Addr;
use std::sync::Arc; use std::sync::Arc;
use libloading::Library; use libloading::Library;
use parking_lot::Mutex;
use wintun::{Adapter, Packet, Session}; use wintun::{Adapter, Packet, Session};
#[derive(Clone)] #[derive(Clone)]
pub struct TunWriter(Arc<Session>, u32); pub struct TunWriter(Arc<Session>, Arc<Mutex<u32>>);
impl TunWriter { impl TunWriter {
pub fn write(&self, buf: &[u8]) -> io::Result<()> { pub fn write(&self, buf: &[u8]) -> io::Result<()> {
@@ -22,10 +23,11 @@ impl TunWriter {
} }
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr, pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
gateway: Ipv4Addr, old_netmask: Ipv4Addr, old_gateway: Ipv4Addr) -> io::Result<()> { gateway: Ipv4Addr, old_netmask: Ipv4Addr, old_gateway: Ipv4Addr) -> io::Result<()> {
if let Err(e) = delete_route(self.1, old_netmask, old_gateway) { let index = self.1.lock();
if let Err(e) = delete_route(*index, old_netmask, old_gateway) {
log::warn!("{:?}",e); log::warn!("{:?}",e);
} }
config_ip(self.1, address, netmask, gateway) config_ip(*index, address, netmask, gateway)
} }
} }
@@ -79,7 +81,7 @@ pub fn create_tun(
config_ip(index, address, netmask, gateway)?; config_ip(index, address, netmask, gateway)?;
let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap()); let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap());
let reader_session = session.clone(); let reader_session = session.clone();
Ok((TunWriter(session.clone(), index), TunReader(reader_session))) Ok((TunWriter(session.clone(), Arc::new(Mutex::new(index))), TunReader(reader_session)))
} }
fn config_ip(index: u32, address: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> { fn config_ip(index: u32, address: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {