From 9820c56be62a0dccdcb6790df144db309fdeae70 Mon Sep 17 00:00:00 2001 From: lubeilin <1791778603@qq.com> Date: Sun, 15 Jan 2023 19:15:41 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=A2=9E=E5=8A=A0=E8=AE=BE=E5=A4=87=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=E5=92=8C=E7=8A=B6=E6=80=81=202.=E6=B5=8B=E8=AF=95wind?= =?UTF-8?q?ows=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- switch-desktop/Cargo.toml | 3 +- switch-desktop/src/main.rs | 73 ++++-- switch-desktop/src/windows/mod.rs | 144 +++++++++++ switch-desktop/src/windows/service.rs | 13 + switch-jni/src/lib.rs | 96 ++++--- switch/Cargo.toml | 2 +- switch/proto/message.proto | 11 +- switch/src/handle/heartbeat_handler.rs | 2 +- switch/src/handle/mod.rs | 45 +++- switch/src/handle/punch_handler.rs | 21 +- switch/src/handle/registration_handler.rs | 55 ++-- switch/src/handle/tun_handler.rs | 12 +- switch/src/handle/udp_recv_handler.rs | 28 +- switch/src/lib.rs | 152 ++++++++--- switch/src/proto/message.rs | 296 ++++++++++++++++++---- 15 files changed, 767 insertions(+), 186 deletions(-) create mode 100644 switch-desktop/src/windows/mod.rs create mode 100644 switch-desktop/src/windows/service.rs diff --git a/switch-desktop/Cargo.toml b/switch-desktop/Cargo.toml index c35fa77..b98a8a3 100644 --- a/switch-desktop/Cargo.toml +++ b/switch-desktop/Cargo.toml @@ -14,10 +14,11 @@ dirs = "4.0.0" log = "0.4.17" log4rs = "1.2.0" tokio = { version = "1.24.1", features = ["full"] } - +chrono = "0.4.23" [target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies] sudo = "0.6.0" [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] } runas = "0.2.1" +windows-service = "0.5.0" diff --git a/switch-desktop/src/main.rs b/switch-desktop/src/main.rs index b52589e..fa1065c 100644 --- a/switch-desktop/src/main.rs +++ b/switch-desktop/src/main.rs @@ -1,17 +1,19 @@ use clap::Parser; use console::style; -use switch::handle::RouteType; use switch::*; +use switch::handle::{PeerDeviceStatus, RouteType}; #[cfg(windows)] mod windows_admin_check; +#[cfg(windows)] +mod windows; #[derive(Parser, Debug)] #[command( - author = "Lu Beilin", - version, - about = "一个虚拟网络工具,启动后会获取一个ip,相同token下的设备之间可以用ip直接通信" +author = "Lu Beilin", +version, +about = "一个虚拟网络工具,启动后会获取一个ip,相同token下的设备之间可以用ip直接通信" )] struct Args { /// 32位字符 @@ -20,8 +22,11 @@ struct Args { /// 32-bit characters. /// Only devices with the same token can communicate with each other. /// It is recommended to use uuid to ensure uniqueness - #[arg(short, long)] + #[arg(long)] token: String, + /// 给设备一个名称,为空时默认用系统版本信息 + #[arg(long)] + name: Option, } fn log_init() { @@ -29,6 +34,7 @@ fn log_init() { if !home.exists() { std::fs::create_dir(&home).expect(" Failed to create '.switch' directory"); } + let stderr = log4rs::append::console::ConsoleAppender::builder().target(log4rs::append::console::Target::Stderr).build(); 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( @@ -38,9 +44,15 @@ fn log_init() { .unwrap(); let config = log4rs::Config::builder() .appender(log4rs::config::Appender::builder().build("logfile", Box::new(logfile))) + .appender( + log4rs::config::Appender::builder() + .filter(Box::new(log4rs::filter::threshold::ThresholdFilter::new(log::LevelFilter::Error))) + .build("stderr", Box::new(stderr)), + ) .build( log4rs::config::Root::builder() .appender("logfile") + .appender("stderr") .build(log::LevelFilter::Info), ) .unwrap(); @@ -75,7 +87,23 @@ fn main() { } println!("{}", style("starting...").green()); let mac_address = mac_address::get_mac_address().unwrap().unwrap().to_string(); - let switch = Switch::start(Config::new(args.token, mac_address)).unwrap(); + let switch = match Config::new(args.token, mac_address, args.name, || {}) { + Ok(config) => { + match Switch::start(config) { + Ok(switch) => { + switch + } + Err(e) => { + log::error!("{:?}",e); + return; + } + } + } + Err(e) => { + log::error!("{:?}",e); + return; + } + }; use console::Term; let term = Term::stdout(); println!("{}", style("started").green()); @@ -122,22 +150,27 @@ fn command(cmd: &str, switch: &Switch) -> Result<(), ()> { println!("No other devices found"); return Ok(()); } - for ip in device_list { - let route = switch.route(&ip); - if route.route_type == RouteType::P2P { - let str = if route.rt >= 0 { - format!("{}(p2p delay:{}ms)", ip, route.rt) + for peer_device_info in device_list { + let route = switch.route(&peer_device_info.virtual_ip); + if peer_device_info.status == PeerDeviceStatus::Online { + if route.route_type == RouteType::P2P { + let str = if route.rt >= 0 { + format!("[{}] {}(p2p delay:{}ms)", peer_device_info.name, peer_device_info.virtual_ip, route.rt) + } else { + format!("[{}] {}(p2p)", peer_device_info.name, peer_device_info.virtual_ip) + }; + println!("{}", style(str).green()); } else { - format!("{}(p2p)", ip) - }; - println!("{}", style(str).green()); + let str = if server_rt >= 0 { + format!("[{}] {}(relay delay:{}ms)", peer_device_info.name, peer_device_info.virtual_ip, server_rt * 2) + } else { + format!("[{}] {}(relay)", peer_device_info.name, peer_device_info.virtual_ip) + }; + println!("{}", style(str).blue()); + } } else { - let str = if server_rt >= 0 { - format!("{}(relay delay:{}ms)", ip, server_rt * 2) - } else { - format!("{}(relay)", ip) - }; - println!("{}", style(str).blue()); + let str = format!("[{}] {}(Offline)", peer_device_info.name, peer_device_info.virtual_ip); + println!("{}", style(str).red()); } } } diff --git a/switch-desktop/src/windows/mod.rs b/switch-desktop/src/windows/mod.rs new file mode 100644 index 0000000..9971b97 --- /dev/null +++ b/switch-desktop/src/windows/mod.rs @@ -0,0 +1,144 @@ +use clap::Parser; +use console::style; + +pub mod service; + +#[derive(Parser, Debug)] +#[command( +author = "Lu Beilin", +version, +about = "一个虚拟网络工具,启动后会获取一个ip,相同token下的设备之间可以用ip直接通信" +)] +struct Args { + /// 32位字符 + /// 相同token的设备之间才能通信。 + /// 建议使用uuid保证唯一性。 + /// 32-bit characters. + /// Only devices with the same token can communicate with each other. + /// It is recommended to use uuid to ensure uniqueness + #[arg(long)] + token: String, + /// 给设备一个名称,为空时默认用系统版本信息 + #[arg(long)] + name: Option, + /// 安装服务,安装后可以后台运行 + #[arg(long)] + install: bool, + /// 卸载服务 + #[arg(long)] + uninstall: bool, + /// 启动,启动时可以附加参数 --token,如果没有token,则会读取配置文件中上一次使用的token + /// 安装服务后,会以服务的方式在后台启动,此时可以关闭命令行窗口 + #[arg(long)] + start: bool, + #[arg(long)] + /// 停止,安装服务后,使用--stop停止服务 + stop: bool, + +} + +const SERVICE_FLAG: &'static str = "start_switch_service_"; +const SERVICE_NAME: &'static str = "switch-service"; + +pub fn main0() { + let args: Vec<_> = std::env::args().collect(); + if args.len() == 2 && args[1] == SERVICE_FLAG { + //以服务的方式启动 + service::start(); + } + let args = Args::parse(); + if args.install { + if let Err(e) = install() { + log::error!("{:?}",e); + }else{ + println!("{}",style("安装成功").green()) + } + pause(); + return; + } + if args.uninstall { + if let Err(e) = uninstall() { + log::error!("{:?}",e); + }else{ + println!("{}",style("卸载成功").green()) + } + pause(); + return; + } + if args.start { + if let Err(e) = start() { + log::error!("{:?}",e); + // 在当前进程启动 + } + pause(); + } +} + +fn pause() { + println!("按任意键退出..."); + std::io::stdin().read_u8().unwrap(); +} + + +fn install() -> Result<(), windows_service::Error> { + use std::ffi::OsString; + use windows_service::{ + service::{ServiceAccess, ServiceErrorControl, ServiceInfo, ServiceStartType, ServiceType}, + service_manager::{ServiceManager, ServiceManagerAccess}, + }; + + let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE; + let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?; + let service_binary_path = std::env::current_exe().unwrap(); + let service_info = ServiceInfo { + name: OsString::from(SERVICE_NAME), + display_name: OsString::from("switch service"), + service_type: ServiceType::OWN_PROCESS, + start_type: ServiceStartType::OnDemand, + error_control: ServiceErrorControl::Normal, + executable_path: service_binary_path.into(), + launch_arguments: vec![OsString::from(SERVICE_FLAG); 1], + dependencies: vec![], + account_name: None, // run as System + account_password: None, + }; + let service = service_manager.create_service(&service_info, ServiceAccess::CHANGE_CONFIG)?; + service.set_description("A VPN")?; + Ok(()) +} + +fn uninstall() -> Result<(), windows_service::Error> { + use std::{thread, time::Duration}; + use windows_service::{ + service::{ServiceAccess, ServiceState}, + service_manager::{ServiceManager, ServiceManagerAccess}, + }; + + let manager_access = ServiceManagerAccess::CONNECT; + let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?; + + let service_access = ServiceAccess::QUERY_STATUS | ServiceAccess::STOP | ServiceAccess::DELETE; + let service = service_manager.open_service(SERVICE_NAME, service_access)?; + + let service_status = service.query_status()?; + if service_status.current_state != ServiceState::Stopped { + service.stop()?; + // Wait for service to stop + thread::sleep(Duration::from_secs(1)); + } + + service.delete()?; + Ok(()) +} + +fn start() -> Result<(), windows_service::Error> { + use std::env; + use windows_service::{ + service::ServiceAccess, + service_manager::{ServiceManager, ServiceManagerAccess}, + }; + let manager_access = ServiceManagerAccess::CONNECT; + let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?; + let service = service_manager.open_service(SERVICE_NAME, ServiceAccess::START)?; + service.start(&[]) +} \ No newline at end of file diff --git a/switch-desktop/src/windows/service.rs b/switch-desktop/src/windows/service.rs new file mode 100644 index 0000000..d21b4a7 --- /dev/null +++ b/switch-desktop/src/windows/service.rs @@ -0,0 +1,13 @@ +// #[macro_use] +// extern crate windows_service; + +use std::ffi::OsString; +use windows_service::{define_windows_service, service_dispatcher}; + +define_windows_service!(ffi_service_main, switch_service_main); +pub fn switch_service_main(arguments: Vec) { + +} +pub fn start(){ + service_dispatcher::start("switch-service",ffi_service_main).unwrap(); +} \ No newline at end of file diff --git a/switch-jni/src/lib.rs b/switch-jni/src/lib.rs index cfbcda9..ba430f2 100644 --- a/switch-jni/src/lib.rs +++ b/switch-jni/src/lib.rs @@ -1,19 +1,34 @@ use std::net::{IpAddr, Ipv4Addr}; - use jni::errors::Error; -use jni::objects::{JClass, JObject, JString, JValue}; -use jni::sys::{jbyte, jint, jintArray, jlong, jobject, jsize}; use jni::JNIEnv; +use jni::objects::{JClass, JObject, JString, JValue}; +use jni::sys::{jbyte, jint, jintArray, jlong, jobject, jobjectArray, jsize}; -use switch::handle::{CurrentDeviceInfo, Route}; use switch::{Config, Switch}; +use switch::handle::{CurrentDeviceInfo, PeerDeviceInfo, Route}; -fn to_string(env: &JNIEnv, config: JObject, name: &str) -> Result, Error> { +fn to_string_not_null(env: &JNIEnv, config: JObject, name: &str) -> Result { let value = env.get_field(config, name, "Ljava/lang/String;")?.l()?; if value.is_null() { env.throw_new("Ljava/lang/NullPointerException", &name) .expect("throw"); + return Err(Error::NullPtr(name)); + } + let value = env.get_string(JString::from(value))?; + match value.to_str() { + Ok(value) => Ok(value.to_string()), + Err(_) => { + env.throw_new("Ljava/lang/RuntimeException", "not utf-8") + .expect("throw"); + return Err(Error::JavaException); + } + } +} + +fn to_string(env: &JNIEnv, config: JObject, name: &str) -> Result, Error> { + let value = env.get_field(config, name, "Ljava/lang/String;")?.l()?; + if value.is_null() { return Ok(None); } let value = env.get_string(JString::from(value))?; @@ -22,26 +37,36 @@ fn to_string(env: &JNIEnv, config: JObject, name: &str) -> Result Err(_) => { env.throw_new("Ljava/lang/RuntimeException", "not utf-8") .expect("throw"); - Ok(None) + return Err(Error::JavaException); } } } fn start(env: &JNIEnv, config: JObject) -> Result, Error> { - if let Some(token) = to_string(&env, config, "token")? { - if let Some(mac_address) = to_string(&env, config, "macAddress")? { - match Switch::start(Config::new(token, mac_address)) { - Ok(switch) => { - return Ok(Some(switch)); - } - Err(e) => { - env.throw_new( - "Ljava/lang/RuntimeException", - format!("switch start failed {:?}", e), - ) - .expect("throw"); - } - } + let token = to_string_not_null(&env, config, "token")?; + let mac_address = to_string_not_null(&env, config, "macAddress")?; + let name = to_string(&env, config, "name")?; + let config = match Config::new(token, mac_address, name,||{}) { + Ok(config) => { config } + Err(e) => { + env.throw_new( + "Ljava/lang/RuntimeException", + format!("switch start failed {:?}", e), + ) + .expect("throw"); + return Ok(None); + } + }; + match Switch::start(config) { + Ok(switch) => { + return Ok(Some(switch)); + } + Err(e) => { + env.throw_new( + "Ljava/lang/RuntimeException", + format!("switch start failed {:?}", e), + ) + .expect("throw"); } } Ok(None) @@ -93,7 +118,7 @@ pub unsafe extern "C" fn Java_org_switches_jni_Switch_deviceList0( env: JNIEnv, _class: JClass, raw_switch: jlong, -) -> jintArray { +) -> jobjectArray { let switch = raw_switch as *mut Switch; match device_list(&env, (&*switch).device_list()) { Ok(arr) => arr, @@ -149,19 +174,28 @@ fn route(env: &JNIEnv, route: Route) -> Result { Ok(route.into_raw()) } -fn device_list(env: &JNIEnv, device_list: Vec) -> Result { +fn device_list(env: &JNIEnv, device_list: Vec) -> Result { if device_list.is_empty() { return Ok(std::ptr::null_mut()); } - let arr = env.new_int_array(device_list.len() as jsize)?; - let devices: Vec = device_list - .iter() - .map(|ip| { - let ip: u32 = (*ip).into(); - ip as jint - }) - .collect(); - env.set_int_array_region(arr, 0, &devices)?; + let arr = env.new_object_array(device_list.len() as jsize, + "org/switches/jni/PeerDeviceInfo", + JObject::null())?; + let mut index = 0; + for peer_info in device_list { + let virtual_ip: u32 = peer_info.virtual_ip.into(); + let name = peer_info.name; + let status = peer_info.status.into(); + let info = env.new_object( + "org/switches/jni/PeerDeviceInfo", + "(BLjava/lang/String;J)V", + &[JValue::Int(virtual_ip as jint), + JValue::Object(env.new_string(name)?.into()), + JValue::Byte(status as jbyte)], + )?; + env.set_object_array_element(arr, index, info)?; + index += 1; + } Ok(arr) } diff --git a/switch/Cargo.toml b/switch/Cargo.toml index 8c7b252..7d0273c 100644 --- a/switch/Cargo.toml +++ b/switch/Cargo.toml @@ -24,7 +24,7 @@ chrono = "0.4.23" lazy_static = "1.4.0" moka = "0.9.6" protobuf = "3.2.0" - +os_info = "3.5.1" tokio = { version = "1.24.1", features = ["full"] } [target.'cfg(any(unix))'.dependencies] tun = { path = "./rust-tun" } diff --git a/switch/proto/message.proto b/switch/proto/message.proto index 81cf1bd..b418202 100644 --- a/switch/proto/message.proto +++ b/switch/proto/message.proto @@ -2,6 +2,8 @@ syntax = "proto3"; message RegistrationRequest{ string token = 1; string mac_address = 2; + string name = 3; + bool is_fast = 4; } message RegistrationResponse{ @@ -9,14 +11,19 @@ message RegistrationResponse{ fixed32 virtual_gateway = 2; fixed32 virtual_netmask = 3; uint32 epoch = 4; - repeated fixed32 virtual_ip_list = 5; + repeated DeviceInfo device_info_list = 5; fixed32 public_ip = 6; uint32 public_port = 7; } +message DeviceInfo{ + string name = 1; + fixed32 virtual_ip = 2; + uint32 device_status = 3; +} message DeviceList{ uint32 epoch = 1; - repeated fixed32 virtual_ip_list = 2; + repeated DeviceInfo device_info_list = 2; } message Punch{ diff --git a/switch/src/handle/heartbeat_handler.rs b/switch/src/handle/heartbeat_handler.rs index 73e58b1..2d313cc 100644 --- a/switch/src/handle/heartbeat_handler.rs +++ b/switch/src/handle/heartbeat_handler.rs @@ -23,7 +23,7 @@ pub async fn start( match handle_loop(status_watch, udp, cur_info.connect_server).await { Ok(_) => {} Err(e) => { - log::error!("{:?}", e) + log::warn!("{:?}", e) } } stop_fn(); diff --git a/switch/src/handle/mod.rs b/switch/src/handle/mod.rs index 164cbf4..75740da 100644 --- a/switch/src/handle/mod.rs +++ b/switch/src/handle/mod.rs @@ -19,7 +19,7 @@ lazy_static! { /// 0. 机器纪元,每一次上线或者下线都会增1,由服务端维护,用于感知网络中机器变化 /// 服务端和客户端的不一致,则服务端会推送新的设备列表 /// 1. 网络中的虚拟ip列表 - pub static ref DEVICE_LIST:Mutex<(u32,Vec)> = const_mutex((0,Vec::new())); + pub static ref DEVICE_LIST:Mutex<(u32,Vec)> = const_mutex((0,Vec::new())); /// 服务器延迟 pub static ref SERVER_RT:AtomicI64 = AtomicI64::new(-1); /// id @@ -32,6 +32,49 @@ lazy_static! { /// 当前设备的nat信息 pub static ref NAT_INFO:Mutex> = const_mutex(None); } +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PeerDeviceInfo { + pub virtual_ip: Ipv4Addr, + pub name: String, + pub status: PeerDeviceStatus, +} + +impl PeerDeviceInfo { + pub fn new(virtual_ip: Ipv4Addr, + name: String, + status: u8, ) -> Self { + Self { + virtual_ip, + name, + status: PeerDeviceStatus::from(status), + } + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum PeerDeviceStatus { + Online, + Offline, +} + +impl Into for PeerDeviceStatus { + fn into(self) -> u8 { + match self { + PeerDeviceStatus::Online => 0, + PeerDeviceStatus::Offline => 1, + } + } +} + +impl From for PeerDeviceStatus { + fn from(value: u8) -> Self { + match value { + 0 => PeerDeviceStatus::Online, + _ => PeerDeviceStatus::Offline + } + } +} + #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ApplicationStatus { Starting, diff --git a/switch/src/handle/punch_handler.rs b/switch/src/handle/punch_handler.rs index a09b791..a0f110c 100644 --- a/switch/src/handle/punch_handler.rs +++ b/switch/src/handle/punch_handler.rs @@ -5,17 +5,17 @@ use std::time::Duration; use dashmap::DashMap; use lazy_static::lazy_static; use protobuf::Message; -use tokio::sync::mpsc::error::TrySendError; use tokio::sync::mpsc::{Receiver, Sender}; +use tokio::sync::mpsc::error::TrySendError; use tokio::sync::watch; +use crate::{CurrentDeviceInfo, DEVICE_LIST, handle::NAT_INFO, handle::NatInfo}; use crate::error::*; use crate::handle::{ApplicationStatus, DIRECT_ROUTE_TABLE}; use crate::proto::message::{NatType, Punch, Step}; +use crate::protocol::{control_packet, NetPacket, Protocol, turn_packet, Version}; use crate::protocol::control_packet::PunchRequestPacket; use crate::protocol::turn_packet::TurnPacket; -use crate::protocol::{control_packet, turn_packet, NetPacket, Protocol, Version}; -use crate::{handle::NatInfo, handle::NAT_INFO, CurrentDeviceInfo, DEVICE_LIST}; lazy_static! { pub static ref STEP_MAP: DashMap = DashMap::new(); @@ -193,7 +193,7 @@ pub async fn req_symmetric_handler_start( match handle_loop(status_watch, receiver, udp, cur_info).await { Ok(_) => {} Err(e) => { - log::error!("{:?}", e) + log::warn!("{:?}", e) } } stop_fn() @@ -224,7 +224,7 @@ pub async fn res_symmetric_handler_start( match res_symmetric_handle_loop(status_watch, receiver, udp, cur_info).await { Ok(_) => {} Err(e) => { - log::error!("{:?}", e) + log::warn!("{:?}", e) } } stop_fn() @@ -287,7 +287,7 @@ async fn res_symmetric_handle_loop( } } if let Err(e) = handle(&status_watch,&udp, list, packet.buffer()) { - log::error!("{:?}",e) + log::warn!("{:?}",e) } }else { return Err(Error::Stop("打洞线程通道关闭".to_string())); @@ -323,7 +323,7 @@ pub async fn cone_handler_start( match handle_loop(status_watch, receiver, udp, cur_info).await { Ok(_) => {} Err(e) => { - log::error!("{:?}", e) + log::warn!("{:?}", e) } } stop_fn(); @@ -363,7 +363,7 @@ async fn handle_loop( } } if let Err(e) = handle(&status_watch,&udp, list, packet.buffer()) { - log::error!("{:?}",e) + log::warn!("{:?}",e) } }else { return Err(Error::Stop("打洞线程通道关闭".to_string())); @@ -390,7 +390,7 @@ fn punch_request_handle(udp: &UdpSocket, cur_info: &CurrentDeviceInfo) -> Result drop(nat_info_lock); if let Some(nat_info) = nat_info { if let Err(e) = send_punch(&udp, &cur_info, nat_info) { - log::error!("发送打洞数据失败 {:?}", e) + log::warn!("发送打洞数据失败 {:?}", e) } Ok(()) } else { @@ -402,7 +402,8 @@ fn send_punch(udp: &UdpSocket, cur_info: &CurrentDeviceInfo, nat_info: NatInfo) let lock = DEVICE_LIST.lock(); let list = lock.1.clone(); drop(lock); - for ip in list { + for peer_info in list { + let ip = peer_info.virtual_ip; //只向ip比自己大的发起打洞,避免双方同时发起打洞浪费流量 if ip > cur_info.virtual_ip && !DIRECT_ROUTE_TABLE.contains_key(&ip) { let step = if let Some(step) = STEP_MAP.get(&ip) { diff --git a/switch/src/handle/registration_handler.rs b/switch/src/handle/registration_handler.rs index 0c3799d..3a7cf8f 100644 --- a/switch/src/handle/registration_handler.rs +++ b/switch/src/handle/registration_handler.rs @@ -11,10 +11,11 @@ use protobuf::Message; use crate::error::*; use crate::handle::ConnectStatus; use crate::proto::message::{RegistrationRequest, RegistrationResponse}; -use crate::protocol::{error_packet, service_packet, NetPacket, Protocol, Version}; +use crate::protocol::{error_packet, NetPacket, Protocol, service_packet, Version}; +use crate::protocol::error_packet::InErrorPacket; lazy_static::lazy_static! { - static ref REQUEST:RwLock> = parking_lot::const_rwlock(None); + static ref REQUEST:RwLock> = parking_lot::const_rwlock(None); static ref REGISTRATION_TIME:AtomicI64=AtomicI64::new(0); pub(crate) static ref CONNECTION_STATUS:AtomicCell = AtomicCell::new(ConnectStatus::Connecting); } @@ -25,9 +26,10 @@ pub fn registration( server_address: SocketAddr, token: String, mac_address: String, + name: String, ) -> Result { // todo 和服务器通信加密 - let request_packet = registration_request_packet(token.clone(), mac_address.clone())?; + let request_packet = registration_request_packet(token.clone(), mac_address.clone(), name.clone(), false)?; let buf = request_packet.buffer(); let mut counter = 0; let mut recv_buf = [0u8; 10240]; @@ -57,7 +59,7 @@ pub fn registration( service_packet::Protocol::RegistrationResponse => { let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?; - let _ = REQUEST.write().replace((token, mac_address)); + let _ = REQUEST.write().replace((token, mac_address, name)); udp.set_read_timeout(None)?; CONNECTION_STATUS.store(ConnectStatus::Connected); return Ok(response); @@ -66,22 +68,45 @@ pub fn registration( } } Protocol::Error => { - match error_packet::Protocol::from(net_packet.transport_protocol()) { - error_packet::Protocol::TokenError => { - return Err(Error::Stop("token错误".to_string())); + return match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload()) { + Ok(e) => { + match e { + InErrorPacket::TokenError => { + Err(Error::Stop("token错误".to_string())) + } + InErrorPacket::Disconnect => { + Err(Error::Stop("断开连接".to_string())) + } + InErrorPacket::OtherError(e) => { + match e.message() { + Ok(str) => { + Err(Error::Stop(str)) + } + Err(e) => { + Err(Error::Stop(format!("{:?}", e))) + } + } + } + } } - _ => {} - } + Err(e) => { + Err(Error::Stop(format!("{:?}", e))) + } + }; + } + _ => { + return Err(Error::Stop(format!("数据错误:{:?}", net_packet))); } - _ => {} } } } -fn registration_request_packet(token: String, mac_address: String) -> Result>> { +fn registration_request_packet(token: String, mac_address: String, name: String, is_fast: bool) -> Result>> { let mut request = RegistrationRequest::new(); request.token = token; request.mac_address = mac_address; + request.name = name; + request.is_fast = is_fast; let bytes = request.write_to_bytes()?; let buf = vec![0u8; 4 + bytes.len()]; let mut net_packet = NetPacket::new(buf)?; @@ -98,8 +123,8 @@ pub fn fast_registration(udp: &UdpSocket, server_address: SocketAddr) -> Result< let new = Local::now().timestamp_millis(); if new - last < 2000 || REGISTRATION_TIME - .compare_exchange(last, new, Ordering::Relaxed, Ordering::Relaxed) - .is_err() + .compare_exchange(last, new, Ordering::Relaxed, Ordering::Relaxed) + .is_err() { //短时间不重复注册 return Ok(()); @@ -108,8 +133,8 @@ pub fn fast_registration(udp: &UdpSocket, server_address: SocketAddr) -> Result< let lock = REQUEST.read(); let option = lock.clone(); drop(lock); - if let Some((token, mac_address)) = option { - let request_packet = registration_request_packet(token, mac_address)?; + if let Some((token, mac_address, name)) = option { + let request_packet = registration_request_packet(token, mac_address, name, true)?; udp.send_to(request_packet.buffer(), server_address)?; REGISTRATION_TIME.store(Local::now().timestamp_millis(), Ordering::Relaxed); return Ok(()); diff --git a/switch/src/handle/tun_handler.rs b/switch/src/handle/tun_handler.rs index d5b2e5e..002668a 100644 --- a/switch/src/handle/tun_handler.rs +++ b/switch/src/handle/tun_handler.rs @@ -10,12 +10,12 @@ use packet::icmp::Kind; use packet::ip::ipv4; use packet::ip::ipv4::packet::IpV4Packet; +use crate::ApplicationStatus; use crate::error::*; use crate::handle::{CurrentDeviceInfo, DIRECT_ROUTE_TABLE}; -use crate::protocol::turn_packet::TurnPacket; use crate::protocol::{NetPacket, Protocol, Version}; +use crate::protocol::turn_packet::TurnPacket; use crate::tun_device::TunReader; -use crate::ApplicationStatus; /// 是否在一个网段 fn check_dest(dest: Ipv4Addr, cur_info: &CurrentDeviceInfo) -> bool { @@ -114,7 +114,7 @@ pub async fn handler_start( }); thread::spawn(move || { if let Err(e) = handle_loop(udp, tun_reader, cur_info) { - log::error!("tun数据处理线程停止 {:?}", e); + log::warn!("tun数据处理线程停止 {:?}", e); } stop_fn(); }); @@ -132,7 +132,7 @@ fn handle_loop(udp: UdpSocket, tun_reader: TunReader, cur_info: CurrentDeviceInf match handle(&udp, data.bytes_mut(), &cur_info, &mut net_packet) { Ok(_) => {} Err(e) => { - println!("{:?}", e) + log::warn!("{:?}", e) } } } @@ -164,7 +164,7 @@ pub async fn handler_start( }); thread::spawn(move || { if let Err(e) = handle_loop(udp, tun_reader, cur_info) { - log::error!(" tun数据处理线程停止 {:?}", e); + log::warn!(" tun数据处理线程停止 {:?}", e); } stop_fn(); }); @@ -187,7 +187,7 @@ pub fn handle_loop( match handle(&udp, data, &cur_info, &mut net_packet) { Ok(_) => {} Err(e) => { - log::error!("{:?}", e) + log::warn!("{:?}", e) } } } diff --git a/switch/src/handle/udp_recv_handler.rs b/switch/src/handle/udp_recv_handler.rs index 3b3e891..10f2db2 100644 --- a/switch/src/handle/udp_recv_handler.rs +++ b/switch/src/handle/udp_recv_handler.rs @@ -23,7 +23,7 @@ use crate::protocol::error_packet::InErrorPacket; use crate::protocol::turn_packet::TurnPacket; use crate::protocol::{control_packet, service_packet, turn_packet, NetPacket, Protocol, Version}; use crate::tun_device::TunWriter; -use crate::{ApplicationStatus, CurrentDeviceInfo}; +use crate::{ApplicationStatus, CurrentDeviceInfo, PeerDeviceInfo}; const UDP_STOP_BUF: [u8; 1] = [0u8]; @@ -50,7 +50,7 @@ pub async fn udp_recv_start( thread::spawn(move || { if let Err(e) = recv_loop(udp, server_addr, other_sender, tun_writer, current_device) { - log::error!("udp数据处理线程停止 {:?}", e); + log::warn!("udp数据处理线程停止 {:?}", e); } stop_fn(); }); @@ -95,12 +95,12 @@ fn recv_loop( return Err(Error::Stop(str)); } Err(e) => { - log::error!("{:?}", e); + log::warn!("{:?}", e); } } } Err(e) => { - log::error!("{:?}", e); + log::warn!("{:?}", e); } }; } @@ -156,7 +156,7 @@ fn recv_handle( return Err(Error::Stop("子处理线程停止".to_string())); } Err(e) => { - log::error!("子线程处理 {:?}", e); + log::warn!("子线程处理 {:?}", e); } } } @@ -178,7 +178,7 @@ pub async fn udp_other_recv_start( match other_loop(status_watch, udp, receiver, current_device, sender).await { Ok(_) => {} Err(e) => { - log::error!("{:?}", e); + log::warn!("{:?}", e); } } stop_fn(); @@ -202,7 +202,7 @@ async fn other_loop( return Err(Error::Stop(str)); } Err(e) => { - log::error!("other_loop {:?}",e); + log::warn!("other_loop {:?}",e); } } } @@ -241,10 +241,10 @@ fn other_handle( } service_packet::Protocol::UpdateDeviceList => { let device_list = DeviceList::parse_from_bytes(net_packet.payload())?; - let ip_list: Vec = device_list - .virtual_ip_list - .iter() - .map(|ip| Ipv4Addr::from(*ip)) + let ip_list = device_list + .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(); if dev.0 < device_list.epoch || device_list.epoch - dev.0 > u32::MAX >> 2 { @@ -269,7 +269,7 @@ fn other_handle( } } InErrorPacket::OtherError(e) => { - log::error!("OtherError {:?}", e.message()); + log::warn!("OtherError {:?}", e.message()); } } } @@ -369,12 +369,10 @@ fn other_handle( } turn_packet::Protocol::UnKnow(_) => {} } - } else { - panic!("ip") } } Protocol::UnKnow(p) => { - log::error!("未知协议 {}", p); + log::warn!("未知协议 {}", p); } } Ok(()) diff --git a/switch/src/lib.rs b/switch/src/lib.rs index 78341a2..895f63e 100644 --- a/switch/src/lib.rs +++ b/switch/src/lib.rs @@ -1,17 +1,18 @@ +use std::borrow::Borrow; use std::io; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, ToSocketAddrs, UdpSocket}; -use std::sync::atomic::Ordering; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; +use crossbeam::atomic::AtomicCell; use crossbeam::sync::WaitGroup; +use parking_lot::Mutex; use tokio::sync::watch; use error::*; +use crate::handle::{ApplicationStatus, ConnectStatus, CurrentDeviceInfo, DEVICE_LIST, DIRECT_ROUTE_TABLE, PeerDeviceInfo, Route, RouteType, SERVER_RT}; use crate::handle::registration_handler::CONNECTION_STATUS; -use crate::handle::{ - ApplicationStatus, ConnectStatus, CurrentDeviceInfo, Route, RouteType, DEVICE_LIST, - DIRECT_ROUTE_TABLE, SERVER_RT, -}; pub mod error; pub mod handle; @@ -21,31 +22,54 @@ pub mod protocol; pub mod tun_device; #[derive(Clone, Debug)] -pub struct Config { +pub struct Config { pub token: String, pub mac_address: String, + pub name: String, + pub abnormal_call: F, } -impl Config { - pub fn new(token: String, mac_address: String) -> Self { - Self { token, mac_address } +impl Config { + pub fn new(token: String, mac_address: String, name: Option, abnormal_call: F) -> Result 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, 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, abnormal_call }) + } } } pub struct Switch { current_device: CurrentDeviceInfo, - status_sender: watch::Sender, + status_sender: Arc>>, wait_group: WaitGroup, runtime: Option, } impl Switch { - pub fn start(config: Config) -> Result { + pub fn start(config: Config) -> Result where + F: FnOnce() + Send + 'static { let runtime = tokio::runtime::Builder::new_multi_thread() .enable_all() .build() .unwrap(); - return match runtime.block_on(Switch::start_(config.token, config.mac_address)) { + return match runtime.block_on(Switch::start_(config)) { Ok(mut switch) => { switch.runtime = Some(runtime); Ok(switch) @@ -54,7 +78,7 @@ impl Switch { }; } pub fn stop(self) { - let _ = self.status_sender.send(ApplicationStatus::Stopping); + Self::call_stop(self.status_sender); self.wait_group.wait(); } pub fn current_device(&self) -> &CurrentDeviceInfo { @@ -66,7 +90,7 @@ impl Switch { pub fn connection_status(&self) -> ConnectStatus { CONNECTION_STATUS.load() } - pub fn device_list(&self) -> Vec { + pub fn device_list(&self) -> Vec { let device_list_lock = DEVICE_LIST.lock(); let (_epoch, device_list) = device_list_lock.clone(); drop(device_list_lock); @@ -86,8 +110,15 @@ impl Switch { } impl Switch { - pub async fn start_(token: String, mac_address: String) -> Result { - let server_address = "nat1.wherewego.top:29876" + fn call_stop(status_sender: Arc>>) -> bool { + let lock = status_sender.lock(); + let status = lock.send_replace(ApplicationStatus::Stopping); + return status == ApplicationStatus::Starting; + } + pub async fn start_(config: Config) -> Result where + F: FnOnce() + Send + 'static { + // let server_address = "nat1.wherewego.top:29876" + let server_address = "127.0.0.1:29876" .to_socket_addrs() .unwrap() .next() @@ -110,12 +141,12 @@ impl Switch { }; //注册 let response = - handle::registration_handler::registration(&udp, server_address, token, mac_address)?; + handle::registration_handler::registration(&udp, server_address, config.token, config.mac_address, config.name)?; { let ip_list = response - .virtual_ip_list - .iter() - .map(|ip| Ipv4Addr::from(*ip)) + .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; @@ -125,18 +156,27 @@ impl Switch { let virtual_gateway = Ipv4Addr::from(response.virtual_gateway); let virtual_netmask = Ipv4Addr::from(response.virtual_netmask); let (status_sender, status_receiver) = - tokio::sync::watch::channel(ApplicationStatus::Starting); + 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(); - handle::heartbeat_handler::start(status_receiver.clone(), udp, current_device, || { + 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; + .await; } //初始化nat数据 handle::init_nat_info(response.public_ip, response.public_port as u16); @@ -152,6 +192,8 @@ impl Switch { 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, @@ -159,77 +201,117 @@ impl Switch { sender, tun_writer, current_device, - || { + move || { + if Self::call_stop(status_sender1) { + if let Some(call) = call1.take() { + call(); + } + } drop(wait_group1); }, ) - .await; + .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; + .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; + .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; + .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; + .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; + .await; } Ok(Switch { current_device, diff --git a/switch/src/proto/message.rs b/switch/src/proto/message.rs index 07d986b..1f3a625 100644 --- a/switch/src/proto/message.rs +++ b/switch/src/proto/message.rs @@ -33,6 +33,10 @@ pub struct RegistrationRequest { pub token: ::std::string::String, // @@protoc_insertion_point(field:RegistrationRequest.mac_address) pub mac_address: ::std::string::String, + // @@protoc_insertion_point(field:RegistrationRequest.name) + pub name: ::std::string::String, + // @@protoc_insertion_point(field:RegistrationRequest.is_fast) + pub is_fast: bool, // special fields // @@protoc_insertion_point(special_field:RegistrationRequest.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -50,7 +54,7 @@ impl RegistrationRequest { } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(2); + let mut fields = ::std::vec::Vec::with_capacity(4); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( "token", @@ -62,6 +66,16 @@ impl RegistrationRequest { |m: &RegistrationRequest| { &m.mac_address }, |m: &mut RegistrationRequest| { &mut m.mac_address }, )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "name", + |m: &RegistrationRequest| { &m.name }, + |m: &mut RegistrationRequest| { &mut m.name }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "is_fast", + |m: &RegistrationRequest| { &m.is_fast }, + |m: &mut RegistrationRequest| { &mut m.is_fast }, + )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "RegistrationRequest", fields, @@ -86,6 +100,12 @@ impl ::protobuf::Message for RegistrationRequest { 18 => { self.mac_address = is.read_string()?; }, + 26 => { + self.name = is.read_string()?; + }, + 32 => { + self.is_fast = is.read_bool()?; + }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; }, @@ -104,6 +124,12 @@ impl ::protobuf::Message for RegistrationRequest { if !self.mac_address.is_empty() { my_size += ::protobuf::rt::string_size(2, &self.mac_address); } + if !self.name.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.name); + } + if self.is_fast != false { + my_size += 1 + 1; + } my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); self.special_fields.cached_size().set(my_size as u32); my_size @@ -116,6 +142,12 @@ impl ::protobuf::Message for RegistrationRequest { if !self.mac_address.is_empty() { os.write_string(2, &self.mac_address)?; } + if !self.name.is_empty() { + os.write_string(3, &self.name)?; + } + if self.is_fast != false { + os.write_bool(4, self.is_fast)?; + } os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) } @@ -135,6 +167,8 @@ impl ::protobuf::Message for RegistrationRequest { fn clear(&mut self) { self.token.clear(); self.mac_address.clear(); + self.name.clear(); + self.is_fast = false; self.special_fields.clear(); } @@ -142,6 +176,8 @@ impl ::protobuf::Message for RegistrationRequest { static instance: RegistrationRequest = RegistrationRequest { token: ::std::string::String::new(), mac_address: ::std::string::String::new(), + name: ::std::string::String::new(), + is_fast: false, special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -177,8 +213,8 @@ pub struct RegistrationResponse { pub virtual_netmask: u32, // @@protoc_insertion_point(field:RegistrationResponse.epoch) pub epoch: u32, - // @@protoc_insertion_point(field:RegistrationResponse.virtual_ip_list) - pub virtual_ip_list: ::std::vec::Vec, + // @@protoc_insertion_point(field:RegistrationResponse.device_info_list) + pub device_info_list: ::std::vec::Vec, // @@protoc_insertion_point(field:RegistrationResponse.public_ip) pub public_ip: u32, // @@protoc_insertion_point(field:RegistrationResponse.public_port) @@ -223,9 +259,9 @@ impl RegistrationResponse { |m: &mut RegistrationResponse| { &mut m.epoch }, )); fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>( - "virtual_ip_list", - |m: &RegistrationResponse| { &m.virtual_ip_list }, - |m: &mut RegistrationResponse| { &mut m.virtual_ip_list }, + "device_info_list", + |m: &RegistrationResponse| { &m.device_info_list }, + |m: &mut RegistrationResponse| { &mut m.device_info_list }, )); fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( "public_ip", @@ -268,10 +304,7 @@ impl ::protobuf::Message for RegistrationResponse { self.epoch = is.read_uint32()?; }, 42 => { - is.read_repeated_packed_fixed32_into(&mut self.virtual_ip_list)?; - }, - 45 => { - self.virtual_ip_list.push(is.read_fixed32()?); + self.device_info_list.push(is.read_message()?); }, 53 => { self.public_ip = is.read_fixed32()?; @@ -303,7 +336,10 @@ impl ::protobuf::Message for RegistrationResponse { if self.epoch != 0 { my_size += ::protobuf::rt::uint32_size(4, self.epoch); } - my_size += 5 * self.virtual_ip_list.len() as u64; + for value in &self.device_info_list { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len; + }; if self.public_ip != 0 { my_size += 1 + 4; } @@ -328,8 +364,8 @@ impl ::protobuf::Message for RegistrationResponse { if self.epoch != 0 { os.write_uint32(4, self.epoch)?; } - for v in &self.virtual_ip_list { - os.write_fixed32(5, *v)?; + for v in &self.device_info_list { + ::protobuf::rt::write_message_field_with_cached_size(5, v, os)?; }; if self.public_ip != 0 { os.write_fixed32(6, self.public_ip)?; @@ -358,7 +394,7 @@ impl ::protobuf::Message for RegistrationResponse { self.virtual_gateway = 0; self.virtual_netmask = 0; self.epoch = 0; - self.virtual_ip_list.clear(); + self.device_info_list.clear(); self.public_ip = 0; self.public_port = 0; self.special_fields.clear(); @@ -370,7 +406,7 @@ impl ::protobuf::Message for RegistrationResponse { virtual_gateway: 0, virtual_netmask: 0, epoch: 0, - virtual_ip_list: ::std::vec::Vec::new(), + device_info_list: ::std::vec::Vec::new(), public_ip: 0, public_port: 0, special_fields: ::protobuf::SpecialFields::new(), @@ -396,14 +432,172 @@ impl ::protobuf::reflect::ProtobufValue for RegistrationResponse { type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; } +#[derive(PartialEq,Clone,Default,Debug)] +// @@protoc_insertion_point(message:DeviceInfo) +pub struct DeviceInfo { + // message fields + // @@protoc_insertion_point(field:DeviceInfo.name) + pub name: ::std::string::String, + // @@protoc_insertion_point(field:DeviceInfo.virtual_ip) + pub virtual_ip: u32, + // @@protoc_insertion_point(field:DeviceInfo.device_status) + pub device_status: u32, + // special fields + // @@protoc_insertion_point(special_field:DeviceInfo.special_fields) + pub special_fields: ::protobuf::SpecialFields, +} + +impl<'a> ::std::default::Default for &'a DeviceInfo { + fn default() -> &'a DeviceInfo { + ::default_instance() + } +} + +impl DeviceInfo { + pub fn new() -> DeviceInfo { + ::std::default::Default::default() + } + + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { + let mut fields = ::std::vec::Vec::with_capacity(3); + let mut oneofs = ::std::vec::Vec::with_capacity(0); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "name", + |m: &DeviceInfo| { &m.name }, + |m: &mut DeviceInfo| { &mut m.name }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "virtual_ip", + |m: &DeviceInfo| { &m.virtual_ip }, + |m: &mut DeviceInfo| { &mut m.virtual_ip }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "device_status", + |m: &DeviceInfo| { &m.device_status }, + |m: &mut DeviceInfo| { &mut m.device_status }, + )); + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "DeviceInfo", + fields, + oneofs, + ) + } +} + +impl ::protobuf::Message for DeviceInfo { + const NAME: &'static str = "DeviceInfo"; + + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { + while let Some(tag) = is.read_raw_tag_or_eof()? { + match tag { + 10 => { + self.name = is.read_string()?; + }, + 21 => { + self.virtual_ip = is.read_fixed32()?; + }, + 24 => { + self.device_status = is.read_uint32()?; + }, + tag => { + ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u64 { + let mut my_size = 0; + if !self.name.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.name); + } + if self.virtual_ip != 0 { + my_size += 1 + 4; + } + if self.device_status != 0 { + my_size += ::protobuf::rt::uint32_size(3, self.device_status); + } + my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); + self.special_fields.cached_size().set(my_size as u32); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { + if !self.name.is_empty() { + os.write_string(1, &self.name)?; + } + if self.virtual_ip != 0 { + os.write_fixed32(2, self.virtual_ip)?; + } + if self.device_status != 0 { + os.write_uint32(3, self.device_status)?; + } + os.write_unknown_fields(self.special_fields.unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn special_fields(&self) -> &::protobuf::SpecialFields { + &self.special_fields + } + + fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { + &mut self.special_fields + } + + fn new() -> DeviceInfo { + DeviceInfo::new() + } + + fn clear(&mut self) { + self.name.clear(); + self.virtual_ip = 0; + self.device_status = 0; + self.special_fields.clear(); + } + + fn default_instance() -> &'static DeviceInfo { + static instance: DeviceInfo = DeviceInfo { + name: ::std::string::String::new(), + virtual_ip: 0, + device_status: 0, + special_fields: ::protobuf::SpecialFields::new(), + }; + &instance + } +} + +impl ::protobuf::MessageFull for DeviceInfo { + fn descriptor() -> ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); + descriptor.get(|| file_descriptor().message_by_package_relative_name("DeviceInfo").unwrap()).clone() + } +} + +impl ::std::fmt::Display for DeviceInfo { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for DeviceInfo { + type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; +} + #[derive(PartialEq,Clone,Default,Debug)] // @@protoc_insertion_point(message:DeviceList) pub struct DeviceList { // message fields // @@protoc_insertion_point(field:DeviceList.epoch) pub epoch: u32, - // @@protoc_insertion_point(field:DeviceList.virtual_ip_list) - pub virtual_ip_list: ::std::vec::Vec, + // @@protoc_insertion_point(field:DeviceList.device_info_list) + pub device_info_list: ::std::vec::Vec, // special fields // @@protoc_insertion_point(special_field:DeviceList.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -429,9 +623,9 @@ impl DeviceList { |m: &mut DeviceList| { &mut m.epoch }, )); fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>( - "virtual_ip_list", - |m: &DeviceList| { &m.virtual_ip_list }, - |m: &mut DeviceList| { &mut m.virtual_ip_list }, + "device_info_list", + |m: &DeviceList| { &m.device_info_list }, + |m: &mut DeviceList| { &mut m.device_info_list }, )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "DeviceList", @@ -455,10 +649,7 @@ impl ::protobuf::Message for DeviceList { self.epoch = is.read_uint32()?; }, 18 => { - is.read_repeated_packed_fixed32_into(&mut self.virtual_ip_list)?; - }, - 21 => { - self.virtual_ip_list.push(is.read_fixed32()?); + self.device_info_list.push(is.read_message()?); }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; @@ -475,7 +666,10 @@ impl ::protobuf::Message for DeviceList { if self.epoch != 0 { my_size += ::protobuf::rt::uint32_size(1, self.epoch); } - my_size += 5 * self.virtual_ip_list.len() as u64; + for value in &self.device_info_list { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len; + }; my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); self.special_fields.cached_size().set(my_size as u32); my_size @@ -485,8 +679,8 @@ impl ::protobuf::Message for DeviceList { if self.epoch != 0 { os.write_uint32(1, self.epoch)?; } - for v in &self.virtual_ip_list { - os.write_fixed32(2, *v)?; + for v in &self.device_info_list { + ::protobuf::rt::write_message_field_with_cached_size(2, v, os)?; }; os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) @@ -506,14 +700,14 @@ impl ::protobuf::Message for DeviceList { fn clear(&mut self) { self.epoch = 0; - self.virtual_ip_list.clear(); + self.device_info_list.clear(); self.special_fields.clear(); } fn default_instance() -> &'static DeviceList { static instance: DeviceList = DeviceList { epoch: 0, - virtual_ip_list: ::std::vec::Vec::new(), + device_info_list: ::std::vec::Vec::new(), special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -885,25 +1079,30 @@ impl Step { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\rmessage.proto\"L\n\x13RegistrationRequest\x12\x14\n\x05token\x18\x01\ + \n\rmessage.proto\"y\n\x13RegistrationRequest\x12\x14\n\x05token\x18\x01\ \x20\x01(\tR\x05token\x12\x1f\n\x0bmac_address\x18\x02\x20\x01(\tR\nmacA\ - ddress\"\x83\x02\n\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\ - \x20\x01(\x07R\tvirtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07\ - R\x0evirtualGateway\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0ev\ - irtualNetmask\x12\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x12&\n\x0f\ - virtual_ip_list\x18\x05\x20\x03(\x07R\rvirtualIpList\x12\x1b\n\tpublic_i\ - p\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\x20\ - \x01(\rR\npublicPort\"J\n\nDeviceList\x12\x14\n\x05epoch\x18\x01\x20\x01\ - (\rR\x05epoch\x12&\n\x0fvirtual_ip_list\x18\x02\x20\x03(\x07R\rvirtualIp\ - List\"\xef\x01\n\x05Punch\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tv\ - irtualIp\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIpList\ - \x12\x1f\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11publ\ - ic_port_range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12#\n\x08nat_type\ - \x18\x05\x20\x01(\x0e2\x08.NatTypeR\x07natType\x12\x14\n\x05reply\x18\ - \x06\x20\x01(\x08R\x05reply\x12\x19\n\x04step\x18\x07\x20\x01(\x0e2\x05.\ - StepR\x04step*\"\n\x07NatType\x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\ - \x10\x01*2\n\x04Step\x12\t\n\x05Step1\x10\0\x12\t\n\x05Step2\x10\x01\x12\ - \t\n\x05Step3\x10\x02\x12\t\n\x05Step4\x10\x03b\x06proto3\ + ddress\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\x07is_fas\ + t\x18\x04\x20\x01(\x08R\x06isFast\"\x92\x02\n\x14RegistrationResponse\ + \x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvirtualIp\x12'\n\x0fvirtua\ + l_gateway\x18\x02\x20\x01(\x07R\x0evirtualGateway\x12'\n\x0fvirtual_netm\ + ask\x18\x03\x20\x01(\x07R\x0evirtualNetmask\x12\x14\n\x05epoch\x18\x04\ + \x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x05\x20\x03(\x0b2\ + \x0b.DeviceInfoR\x0edeviceInfoList\x12\x1b\n\tpublic_ip\x18\x06\x20\x01(\ + \x07R\x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\x20\x01(\rR\npublicPo\ + rt\"d\n\nDeviceInfo\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\ + \x1d\n\nvirtual_ip\x18\x02\x20\x01(\x07R\tvirtualIp\x12#\n\rdevice_statu\ + s\x18\x03\x20\x01(\rR\x0cdeviceStatus\"Y\n\nDeviceList\x12\x14\n\x05epoc\ + h\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_info_list\x18\x02\x20\ + \x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xef\x01\n\x05Punch\x12\ + \x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tvirtualIp\x12$\n\x0epublic_ip_\ + list\x18\x02\x20\x03(\x07R\x0cpublicIpList\x12\x1f\n\x0bpublic_port\x18\ + \x03\x20\x01(\rR\npublicPort\x12*\n\x11public_port_range\x18\x04\x20\x01\ + (\rR\x0fpublicPortRange\x12#\n\x08nat_type\x18\x05\x20\x01(\x0e2\x08.Nat\ + TypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\x01(\x08R\x05reply\x12\ + \x19\n\x04step\x18\x07\x20\x01(\x0e2\x05.StepR\x04step*\"\n\x07NatType\ + \x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01*2\n\x04Step\x12\t\n\ + \x05Step1\x10\0\x12\t\n\x05Step2\x10\x01\x12\t\n\x05Step3\x10\x02\x12\t\ + \n\x05Step4\x10\x03b\x06proto3\ "; /// `FileDescriptorProto` object which was a source for this generated file @@ -921,9 +1120,10 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor { file_descriptor.get(|| { let generated_file_descriptor = generated_file_descriptor_lazy.get(|| { let mut deps = ::std::vec::Vec::with_capacity(0); - let mut messages = ::std::vec::Vec::with_capacity(4); + let mut messages = ::std::vec::Vec::with_capacity(5); messages.push(RegistrationRequest::generated_message_descriptor_data()); messages.push(RegistrationResponse::generated_message_descriptor_data()); + messages.push(DeviceInfo::generated_message_descriptor_data()); messages.push(DeviceList::generated_message_descriptor_data()); messages.push(Punch::generated_message_descriptor_data()); let mut enums = ::std::vec::Vec::with_capacity(2);