diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index dfea8b4..de6d899 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -58,6 +58,8 @@ jobs: OS: ubuntu-latest - TARGET: x86_64-apple-darwin # tested on a mac, is not properly signed so there are security warnings OS: macos-latest + - TARGET: aarch64-apple-darwin # tested on a mac, is not properly signed so there are security warnings + OS: macos-latest - TARGET: i686-pc-windows-msvc # tested on a windows machine OS: windows-latest - TARGET: x86_64-pc-windows-msvc # tested on a windows machine @@ -65,7 +67,7 @@ jobs: # needs: test runs-on: ${{ matrix.OS }} env: - NAME: switch-cmd # change with the name of your project + NAME: vnt-cli # change with the name of your project TARGET: ${{ matrix.TARGET }} OS: ${{ matrix.OS }} steps: @@ -106,7 +108,7 @@ jobs: - name: Install rust target run: rustup target add $TARGET - name: Run build - run: cargo build --package switch-cmd --release --verbose --target $TARGET + run: cargo build --package vnt-cli --release --verbose --target $TARGET - name: List target run: find ./target - name: Compress @@ -128,7 +130,7 @@ jobs: - name: Archive artifact uses: actions/upload-artifact@v2 with: - name: switch-cmd + name: vnt-cli path: | ./artifacts # deploys to github releases on tag @@ -140,7 +142,7 @@ jobs: - name: Download artifacts uses: actions/download-artifact@v2 with: - name: switch-cmd + name: vnt-cli path: ./artifacts - name: List run: find ./artifacts diff --git a/Cargo.toml b/Cargo.toml index 93b3367..677cb42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["switch","common","switch-desktop","switch-cmd","switch-jni"] +members = ["vnt","common","vnt-cli","vnt-jni"] [profile.release] opt-level = 'z' diff --git a/README.md b/README.md index 5ddf1c8..1ac9a0a 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,23 @@ -# switch +# Vnt A virtual network tool (VPN) 将不同网络下的多个设备虚拟到一个局域网下 -### switch-cmd参数详解 [参数说明](https://github.com/lbl8603/switch/blob/main/switch-cmd/README.md) +### vnt-cli参数详解 [参数说明](https://github.com/lbl8603/vnt/blob/main/vnt-cli/README.md) ### 快速使用: 1. 指定一个token,在多台设备上运行该程序,例如: ```shell # linux上 - root@DESKTOP-0BCHNIO:/opt# ./switch-cmd -k 123456 + root@DESKTOP-0BCHNIO:/opt# ./vnt-cli -k 123456 # 在另一台linux上使用nohup后台运行 - root@izj6cemne76ykdzkataftfz switch# nohup ./switch-cmd -k 123456 & + root@izj6cemne76ykdzkataftfz vnt# nohup ./vnt-cli -k 123456 & # windows上 - D:\switch\bin_v1>switch-cmd.exe -k 123456 + D:\vnt\bin_v1>vnt-cli.exe -k 123456 ``` 2. 可以执行info命令查看当前设备的虚拟ip ```shell - root@DESKTOP-0BCHNIO:/opt# ./switch-cmd --info + root@DESKTOP-0BCHNIO:/opt# ./vnt-cli --info Name: Ubuntu 18.04 (bionic) [64-bit] Virtual ip: 10.26.0.2 Virtual gateway: 10.26.0.1 @@ -30,14 +30,14 @@ A virtual network tool (VPN) ``` 3. 也可以执行list命令查看其他设备的虚拟ip ```shell - root@DESKTOP-0BCHNIO:/opt# ./switch-cmd --list + root@DESKTOP-0BCHNIO:/opt# ./vnt-cli --list Name Virtual Ip P2P/Relay Rt Status Windows 10.0.22621 (Windows 11 Professional) [64-bit] 10.26.0.3 p2p 2 Online CentOS 7.9.2009 (Core) [64-bit] 10.26.0.4 p2p 35 Online ``` 4. 最后可以用虚拟ip实现设备间相互访问 - ssh + ssh 5. 帮助,使用-h命令查看 ### 更多玩法 @@ -52,15 +52,15 @@ A virtual network tool (VPN) - token的作用是标识一个虚拟局域网,当使用公共服务器时,建议使用一个唯一值当token(比如uuid),否则有可能连接到其他人创建的虚拟局域网中 - 默认使用公共服务器,目前的配置是2核4G 4Mbps,有需要再扩展~ - 需要root/管理员权限 -- switch-cmd需要使用命令行运行 -- Mac和Linux下需要加可执行权限(例如:chmod +x ./switch-cmd) -- 可以自己搭注册和中继服务器([server](https://github.com/lbl8603/switch-server)) +- vnt-cli需要使用命令行运行 +- Mac和Linux下需要加可执行权限(例如:chmod +x ./vnt-cli) +- 可以自己搭注册和中继服务器([server](https://github.com/lbl8603/vnts)) ### 编译 前提条件:安装rust编译环境([install rust](https://www.rust-lang.org/zh-CN/tools/install)) -到项目根目录下执行 cargo build -p switch-cmd +到项目根目录下执行 cargo build -p vnt-cli ### 支持平台 @@ -98,13 +98,13 @@ A virtual network tool (VPN) ##### 可能原因: -switch默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突 +vnt默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突 ##### 解决方法: 1. 方法一:找到冲突的IP,将其改成别的 2. 方法二:自建服务器,指定其他不会冲突的网段 -3. 方法三:增加参数-d ,设置不同的id会让switch-server分配不同的IP,从而绕开有冲突的IP +3. 方法三:增加参数-d ,设置不同的id会让服务端分配不同的IP,从而绕开有冲突的IP #### 问题2: windows系统上wintun.dll加载失败 @@ -113,8 +113,8 @@ switch默认使用10.26.0.0/24网段,和本地网络适配器的ip冲突 ##### 解决方法: 1. 下载最新版的wintun.dll [下载链接](https://www.wintun.net/builds/wintun-0.14.1.zip) 2. 解压后找到对应架构的目录,通常是amd64 -3. 将对应的wintun.dll放到和switch-cmd同目录下(或者放到C盘Windows目录下) -4. 再次启动switch-cmd +3. 将对应的wintun.dll放到和vnt-cli同目录下(或者放到C盘Windows目录下) +4. 再次启动vnt-cli diff --git a/common/Cargo.toml b/common/Cargo.toml index 27839f2..35afc09 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "common" -version = "1.1.0" +version = "1.1.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/common/src/identifier.rs b/common/src/identifier.rs index 5876044..7301eeb 100644 --- a/common/src/identifier.rs +++ b/common/src/identifier.rs @@ -38,7 +38,6 @@ pub fn get_unique_identifier() -> Option { let identifier = result .lines() .find(|line| line.contains("IOPlatformUUID")) - .and_then(|line| line.split('"').nth(4)) .unwrap_or("").trim(); if identifier.is_empty() { None diff --git a/switch-desktop/Cargo.toml b/switch-desktop/Cargo.toml deleted file mode 100644 index affae88..0000000 --- a/switch-desktop/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "switch-desktop" -version = "1.1.0" -description = "switch desktop" -authors = ["lubeilin"] -license = "" -repository = "" -default-run = "switch-desktop" -edition = "2021" -rust-version = "1.60" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[build-dependencies] -tauri-build = { version = "1.4.0", features = [] } -embed-resource = "2.2" - -[dependencies] -switch = {path="../switch"} -common = {path="../common"} -dirs = "4.0.0" -os_info = "3.7.0" -lazy_static = "1.4.0" -parking_lot = "0.12.1" - -serde_json = "1.0" -serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.4.0", features = [] } - -[target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = [] } - -[features] -# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled. -# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes. -# DO NOT REMOVE!! -custom-protocol = [ "tauri/custom-protocol" ] diff --git a/switch-desktop/README.md b/switch-desktop/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/switch-desktop/build.rs b/switch-desktop/build.rs deleted file mode 100644 index 8c8da1a..0000000 --- a/switch-desktop/build.rs +++ /dev/null @@ -1,21 +0,0 @@ -fn main() { - if std::env::var_os("CARGO_CFG_WINDOWS").is_some() { - let mut windows = tauri_build::WindowsAttributes::new(); - windows = windows.app_manifest(r#" - - - - - - - - - - -"#); - let attrs = tauri_build::Attributes::new().windows_attributes(windows); - tauri_build::try_build(attrs).expect("failed to run build script"); - } else { - tauri_build::build(); - } -} diff --git a/switch-desktop/dll/amd64/wintun.dll b/switch-desktop/dll/amd64/wintun.dll deleted file mode 100644 index 9f1a181..0000000 Binary files a/switch-desktop/dll/amd64/wintun.dll and /dev/null differ diff --git a/switch-desktop/icons/128x128.png b/switch-desktop/icons/128x128.png deleted file mode 100644 index 77e7d23..0000000 Binary files a/switch-desktop/icons/128x128.png and /dev/null differ diff --git a/switch-desktop/icons/128x128@2x.png b/switch-desktop/icons/128x128@2x.png deleted file mode 100644 index 0f7976f..0000000 Binary files a/switch-desktop/icons/128x128@2x.png and /dev/null differ diff --git a/switch-desktop/icons/32x32.png b/switch-desktop/icons/32x32.png deleted file mode 100644 index 98fda06..0000000 Binary files a/switch-desktop/icons/32x32.png and /dev/null differ diff --git a/switch-desktop/icons/Square107x107Logo.png b/switch-desktop/icons/Square107x107Logo.png deleted file mode 100644 index f35d84f..0000000 Binary files a/switch-desktop/icons/Square107x107Logo.png and /dev/null differ diff --git a/switch-desktop/icons/Square142x142Logo.png b/switch-desktop/icons/Square142x142Logo.png deleted file mode 100644 index 1823bb2..0000000 Binary files a/switch-desktop/icons/Square142x142Logo.png and /dev/null differ diff --git a/switch-desktop/icons/Square150x150Logo.png b/switch-desktop/icons/Square150x150Logo.png deleted file mode 100644 index dc2b22c..0000000 Binary files a/switch-desktop/icons/Square150x150Logo.png and /dev/null differ diff --git a/switch-desktop/icons/Square284x284Logo.png b/switch-desktop/icons/Square284x284Logo.png deleted file mode 100644 index 0ed3984..0000000 Binary files a/switch-desktop/icons/Square284x284Logo.png and /dev/null differ diff --git a/switch-desktop/icons/Square30x30Logo.png b/switch-desktop/icons/Square30x30Logo.png deleted file mode 100644 index 60bf0ea..0000000 Binary files a/switch-desktop/icons/Square30x30Logo.png and /dev/null differ diff --git a/switch-desktop/icons/Square310x310Logo.png b/switch-desktop/icons/Square310x310Logo.png deleted file mode 100644 index c8ca0ad..0000000 Binary files a/switch-desktop/icons/Square310x310Logo.png and /dev/null differ diff --git a/switch-desktop/icons/Square44x44Logo.png b/switch-desktop/icons/Square44x44Logo.png deleted file mode 100644 index 8756459..0000000 Binary files a/switch-desktop/icons/Square44x44Logo.png and /dev/null differ diff --git a/switch-desktop/icons/Square71x71Logo.png b/switch-desktop/icons/Square71x71Logo.png deleted file mode 100644 index 2c8023c..0000000 Binary files a/switch-desktop/icons/Square71x71Logo.png and /dev/null differ diff --git a/switch-desktop/icons/Square89x89Logo.png b/switch-desktop/icons/Square89x89Logo.png deleted file mode 100644 index 2c5e603..0000000 Binary files a/switch-desktop/icons/Square89x89Logo.png and /dev/null differ diff --git a/switch-desktop/icons/StoreLogo.png b/switch-desktop/icons/StoreLogo.png deleted file mode 100644 index 17d142c..0000000 Binary files a/switch-desktop/icons/StoreLogo.png and /dev/null differ diff --git a/switch-desktop/icons/icon.icns b/switch-desktop/icons/icon.icns deleted file mode 100644 index a2993ad..0000000 Binary files a/switch-desktop/icons/icon.icns and /dev/null differ diff --git a/switch-desktop/icons/icon.ico b/switch-desktop/icons/icon.ico deleted file mode 100644 index 06c23c8..0000000 Binary files a/switch-desktop/icons/icon.ico and /dev/null differ diff --git a/switch-desktop/icons/icon.png b/switch-desktop/icons/icon.png deleted file mode 100644 index d1756ce..0000000 Binary files a/switch-desktop/icons/icon.png and /dev/null differ diff --git a/switch-desktop/src/config/mod.rs b/switch-desktop/src/config/mod.rs deleted file mode 100644 index 8c7518f..0000000 --- a/switch-desktop/src/config/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -use std::path::PathBuf; - -pub fn get_home() -> PathBuf { - let home = dirs::home_dir().unwrap().join(".switch_desktop"); - if !home.exists() { - std::fs::create_dir(&home).unwrap(); - } - home -} \ No newline at end of file diff --git a/switch-desktop/src/load_dll/mod.rs b/switch-desktop/src/load_dll/mod.rs deleted file mode 100644 index e1340dc..0000000 --- a/switch-desktop/src/load_dll/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::fs::File; -use std::io; -use std::io::Write; -use std::os::windows::ffi::OsStrExt; -use crate::config::get_home; - -const DLL_FILE: &'static [u8] = include_bytes!("../../dll/amd64/wintun.dll"); - -pub fn load_tun_dll() -> io::Result<()> { - let lib_path = get_home().join("lib"); - if !lib_path.exists() { - std::fs::create_dir(&lib_path).unwrap(); - } - let dll_path = lib_path.join("wintun.dll"); - if !dll_path.exists() { - let mut f = File::create(&dll_path)?; - f.write_all(DLL_FILE)?; - f.sync_data()?; - } - let dll_directory = lib_path.as_os_str(); - - let dll_directory_wide: Vec = dll_directory.encode_wide().chain(Some(0)).collect(); - unsafe { - winapi::um::winbase::SetDllDirectoryW(dll_directory_wide.as_ptr()); - } - Ok(()) -} \ No newline at end of file diff --git a/switch-desktop/src/main.rs b/switch-desktop/src/main.rs deleted file mode 100644 index c4ccd07..0000000 --- a/switch-desktop/src/main.rs +++ /dev/null @@ -1,225 +0,0 @@ -// Prevents additional console window on Windows in release, DO NOT REMOVE!! -#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] - -use std::net::{Ipv4Addr, ToSocketAddrs}; -use lazy_static::lazy_static; -use parking_lot::Mutex; -use common::args_parse::ips_parse; -use switch::core::Config; -use switch::core::{Switch, SwitchUtil}; -use switch::handle::registration_handler::ReqEnum; - -#[cfg(windows)] -mod load_dll; -#[cfg(windows)] -mod config; - -lazy_static! { - static ref SWITCH:Mutex> = Mutex::new(None); -} - -fn main() { - #[cfg(windows)] - { - load_dll::load_tun_dll().unwrap(); - } - tauri::Builder::default() - .invoke_handler(tauri::generate_handler![default_value_name,default_value_device_id,connect,close,list]) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); -} - -#[tauri::command] -fn default_value_name() -> String { - os_info::get().to_string() -} - -#[tauri::command] -fn default_value_device_id() -> String { - common::identifier::get_unique_identifier().unwrap_or(String::new()) -} - -#[tauri::command] -async fn connect(config: ConnectConfig) -> Result { - let tap = config.tap; - let token = config.token; - let device_id = config.device_id; - let name = config.name; - let server_address_str = config.server_address; - let server_address = match server_address_str.to_socket_addrs() { - Ok(mut addr) => { - if let Some(addr) = addr.next() { - addr - } else { - return Err(String::from("server")); - } - } - Err(e) => { - return Err(format!("server err:{}", e)); - } - }; - let nat_test_server = config.nat_test_server.split(&[',', ' '][..]).flat_map(|a| a.to_socket_addrs()).flatten() - .collect::>(); - let in_ips = config.in_ips.split(" ").into_iter().filter(|e| !e.is_empty()).map(|e| e.to_string()).collect(); - let in_ips = match ips_parse(&in_ips) { - Ok(in_ips) => { in_ips } - Err(e) => { - return Err(format!("inIps err:{}", e)); - } - }; - let out_ips = config.out_ips.split(" ").into_iter().filter(|e| !e.is_empty()).map(|e| e.to_string()).collect(); - let out_ips = match ips_parse(&out_ips) { - Ok(out_ips) => { out_ips } - Err(e) => { - return Err(format!("inIps err:{}", e)); - } - }; - let password = if config.key.is_empty() { - None - } else { - Some(config.key) - }; - let simulate_multicast = config.simulate_multicast; - let config = Config::new(tap, token, device_id, name, server_address, server_address_str, - nat_test_server, in_ips, out_ips, - password, simulate_multicast, None); - - let mut switch_util = SwitchUtil::new(config).await.unwrap(); - let mut count = 0; - let response = loop { - match switch_util.connect().await { - Ok(response) => { - break response; - } - Err(e) => { - match e { - ReqEnum::TokenError => { - return Err("token error".to_string()); - } - ReqEnum::AddressExhausted => { - return Err("address exhausted".to_string()); - } - ReqEnum::Timeout => { - count += 1; - if count > 3 { - return Err("connect timeout".to_string()); - } - continue; - } - ReqEnum::ServerError(str) => { - return Err(format!("error:{}", str)); - } - ReqEnum::Other(str) => { - return Err(format!("error:{}", str)); - } - } - } - } - }; - match switch_util.create_iface() { - Ok(_) => {} - Err(e) => { - return Err(format!("create net interface error:{}", e)); - } - } - match switch_util.build().await { - Ok(switch) => { - let _ = SWITCH.lock().insert(switch); - } - Err(e) => { - return Err(format!("build switch error:{}", e)); - } - } - Ok(ConnectRegResponse { - virtual_ip: response.virtual_ip, - virtual_gateway: response.virtual_gateway, - virtual_netmask: response.virtual_netmask, - }) -} - -#[tauri::command] -fn list() -> Vec { - let mut peer_list = Vec::new(); - let mut guard = SWITCH.lock(); - match &mut *guard { - None => {} - Some(switch) => { - let mut list = switch.device_list(); - let current_device = switch.current_device(); - list.sort_unstable_by_key(|v| { (v.status, v.virtual_ip) }); - for x in list { - let item = if let Some(route) = switch.route(&x.virtual_ip) { - let connect = if route.is_p2p() { - "p2p".to_string() - } else if route.addr == current_device.connect_server { - "server relay".to_string() - } else { - "client relay".to_string() - }; - SwitchPeerItem { - name: x.name, - virtual_ip: x.virtual_ip, - status: format!("{:?}", x.status), - connect, - rt: route.rt.to_string(), - addr: route.addr.to_string(), - } - } else { - SwitchPeerItem { - name: x.name, - virtual_ip: x.virtual_ip, - status: format!("{:?}", x.status), - connect: "".to_string(), - rt: "".to_string(), - addr: "".to_string(), - } - }; - peer_list.push(item); - } - } - } - peer_list -} - -#[tauri::command] -async fn close() { - let switch = SWITCH.lock().take(); - match switch { - None => {} - Some(mut switch) => { - switch.stop().unwrap(); - switch.wait_stop().await; - } - } -} - -#[derive(serde::Serialize, serde::Deserialize, Debug)] -pub struct ConnectConfig { - pub tap: bool, - pub token: String, - pub device_id: String, - pub name: String, - pub server_address: String, - pub nat_test_server: String, - pub in_ips: String, - pub out_ips: String, - pub key: String, - pub simulate_multicast: bool, -} - -#[derive(serde::Serialize, serde::Deserialize, Debug)] -pub struct ConnectRegResponse { - pub virtual_ip: Ipv4Addr, - pub virtual_gateway: Ipv4Addr, - pub virtual_netmask: Ipv4Addr, -} - -#[derive(serde::Serialize, serde::Deserialize, Debug)] -pub struct SwitchPeerItem { - pub name: String, - pub virtual_ip: Ipv4Addr, - pub status: String, - pub connect: String, - pub rt: String, - pub addr: String, -} diff --git a/switch-desktop/tauri.conf.json b/switch-desktop/tauri.conf.json deleted file mode 100644 index a419846..0000000 --- a/switch-desktop/tauri.conf.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "build": { - "withGlobalTauri": true, - "beforeBuildCommand": "", - "beforeDevCommand": "", - "devPath": "./ui", - "distDir": "./ui" - }, - "package": { - "productName": "switch-desktop", - "version": "1.1.0" - }, - "tauri": { - "allowlist": { - "all": false - }, - "bundle": { - "active": true, - "category": "DeveloperTool", - "copyright": "", - "deb": { - "depends": [] - }, - "externalBin": [], - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "identifier": "top.wherewego.switch", - "longDescription": "", - "macOS": { - "entitlements": null, - "exceptionDomain": "", - "frameworks": [], - "providerShortName": null, - "signingIdentity": null - }, - "resources": [], - "shortDescription": "", - "targets": "all", - "windows": { - "certificateThumbprint": null, - "digestAlgorithm": "sha256", - "timestampUrl": "" - } - }, - "security": { - "csp": null - }, - "updater": { - "active": false - }, - "windows": [ - { - "fullscreen": false, - "height": 600, - "resizable": true, - "title": "Switch Desktop", - "width": 892, - "minWidth": 892, - "minHeight": 600, - "center": true - } - ] - } -} diff --git a/switch-desktop/ui/index.html b/switch-desktop/ui/index.html deleted file mode 100644 index 1086c31..0000000 --- a/switch-desktop/ui/index.html +++ /dev/null @@ -1,681 +0,0 @@ - - - - - - Switch Desktop - - - - - -
-
-
-
-
-
-
-
-
- - -
- -
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
- -
-
-
- - -
-
- - -
-
- - -
-
- - - - - - -
-
-
- close -
-
-
- -
-
- -
-
-
- - - - \ No newline at end of file diff --git a/switch-desktop/ui/js/jquery-3.7.0.min.js b/switch-desktop/ui/js/jquery-3.7.0.min.js deleted file mode 100644 index e7e29d5..0000000 --- a/switch-desktop/ui/js/jquery-3.7.0.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.7.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.0",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},R=function(){V()},M=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&z(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function X(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&M(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function U(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function z(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",R),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|&#?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Me(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="
",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return R(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return R(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0, - pub public_ip: Ipv4Addr, - pub public_port: u16, -} - -///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致 -pub async fn registration( - main_channel: &UdpSocket, - server_address: SocketAddr, - token: String, - device_id: String, - name: String, -) -> Result { - let request_packet = - registration_request_packet(token.clone(), device_id.clone(), name.clone(), false).unwrap(); - let buf = request_packet.buffer(); - let mut recv_buf = [0u8; 10240]; - return match main_channel.send_to(buf, server_address).await { - Ok(_) => { - match tokio::time::timeout(Duration::from_millis(300), main_channel.recv_from(&mut recv_buf)).await { - Ok(rs) => { - match rs { - Ok((len, addr)) => { - if server_address == addr { - let net_packet = match NetPacket::new(&recv_buf[..len]) { - Ok(net_packet) => { - net_packet - } - Err(e) => { - return Err(ReqEnum::ServerError(format!("{}",e))) - } - }; - match net_packet.protocol() { - Protocol::Service => { - match service_packet::Protocol::from(net_packet.transport_protocol()) { - service_packet::Protocol::RegistrationResponse => { - match RegistrationResponse::parse_from_bytes(net_packet.payload()) { - Ok(response) => { - let device_info_list: Vec = response - .device_info_list - .into_iter() - .map(|info| { - PeerDeviceInfo::new( - Ipv4Addr::from(info.virtual_ip), - info.name, - info.device_status as u8, - ) - }) - .collect(); - Ok(RegResponse { - virtual_ip: Ipv4Addr::from(response.virtual_ip), - virtual_gateway: Ipv4Addr::from(response.virtual_gateway), - virtual_netmask: Ipv4Addr::from(response.virtual_netmask), - epoch: response.epoch as u16, - device_info_list, - public_ip: Ipv4Addr::from(response.public_ip), - public_port: response.public_port as u16, - }) - } - Err(_) => { - Err(ReqEnum::ServerError("invalid data".to_string())) - } - } - } - _ => { - Err(ReqEnum::ServerError("invalid data".to_string())) - } - } - } - Protocol::Error => { - match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload()) { - Ok(e) => match e { - InErrorPacket::TokenError => Err(ReqEnum::TokenError), - InErrorPacket::Disconnect => { - Err(ReqEnum::ServerError("disconnect".to_string())) - } - InErrorPacket::AddressExhausted => { - Err(ReqEnum::AddressExhausted) - } - InErrorPacket::OtherError(e) => match e.message() { - Ok(str) => { - Err(ReqEnum::ServerError(str)) - } - Err(e) => Err(ReqEnum::Other(format!("{}", e))), - }, - }, - Err(e) => Err(ReqEnum::Other(format!("{}", e))), - } - } - _ => Err(ReqEnum::ServerError("invalid data".to_string())), - } - } else { - Err(ReqEnum::Other(format!("invalid data,from {}", addr))) - } - } - Err(e) => { - Err(ReqEnum::Other(format!("receiver error:{}", e))) - } - } - } - Err(_) => { - Err(ReqEnum::Timeout) - } - } - } - Err(e) => { - Err(ReqEnum::Other(format!("send error:{}", e))) - } - }; -} - -fn registration_request_packet( - token: String, - device_id: String, - name: String, - is_fast: bool, -) -> crate::Result>> { - let mut request = RegistrationRequest::new(); - request.token = token; - request.device_id = device_id; - request.name = name; - request.is_fast = is_fast; - request.version = "1.1.0".to_string(); - let bytes = request.write_to_bytes()?; - let buf = vec![0u8; 12 + bytes.len()]; - let mut net_packet = NetPacket::new(buf)?; - net_packet.set_version(Version::V1); - net_packet.set_protocol(Protocol::Service); - net_packet.set_transport_protocol(service_packet::Protocol::RegistrationRequest.into()); - net_packet.first_set_ttl(MAX_TTL); - net_packet.set_payload(&bytes); - Ok(net_packet) -} - -pub struct Register { - sender: ChannelSender, - server_address: SocketAddr, - token: String, - device_id: String, - name: String, - time: AtomicCell, -} - -impl Register { - pub fn new( - sender: ChannelSender, - server_address: SocketAddr, - token: String, - device_id: String, - name: String, - ) -> Self { - Self { - sender, - server_address, - token, - device_id, - name, - time: AtomicCell::new(Instant::now()), - } - } - pub async fn fast_register(&self) -> io::Result<()> { - let last = self.time.load(); - if last.elapsed() < Duration::from_secs(2) - || self - .time - .compare_exchange(last, Instant::now()) - .is_err() - { - //短时间不重复注册 - return Ok(()); - } - log::info!("重新连接"); - let request_packet = registration_request_packet( - self.token.clone(), - self.device_id.clone(), - self.name.clone(), - false, - ) - .unwrap(); - let buf = request_packet.buffer(); - self.sender.send_main(buf, self.server_address).await?; - Ok(()) - } -} diff --git a/switch-cmd/Cargo.toml b/vnt-cli/Cargo.toml similarity index 73% rename from switch-cmd/Cargo.toml rename to vnt-cli/Cargo.toml index 50f1ef5..829ab32 100644 --- a/switch-cmd/Cargo.toml +++ b/vnt-cli/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "switch-cmd" -version = "1.1.0" +name = "vnt-cli" +version = "1.1.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -switch = {path="../switch"} +vnt = {path="../vnt"} common = {path="../common"} tokio = { version = "1.28.1", features = ["full"] } getopts = "0.2.21" @@ -16,6 +16,11 @@ dirs = "4.0.0" serde = "1.0" serde_json = "1.0.94" log = "0.4.17" +[dependencies.uuid] +version = "1.4.1" +features = [ + "v4", # Lets you generate random UUIDs +] [target.'cfg(any(target_os = "linux",target_os = "macos"))'.dependencies] sudo = "0.6.0" @@ -24,4 +29,7 @@ sudo = "0.6.0" winapi = { version = "0.3.9", features = ["handleapi", "processthreadsapi", "winnt", "securitybaseapi", "impl-default"] } [features] default = [] -mini = [] \ No newline at end of file +mini = [] + +[build-dependencies] +embed-manifest = "1.4.0" \ No newline at end of file diff --git a/switch-cmd/README.md b/vnt-cli/README.md similarity index 100% rename from switch-cmd/README.md rename to vnt-cli/README.md diff --git a/vnt-cli/build.rs b/vnt-cli/build.rs new file mode 100644 index 0000000..430832c --- /dev/null +++ b/vnt-cli/build.rs @@ -0,0 +1,10 @@ +// use embed_manifest::{embed_manifest, new_manifest}; +// use embed_manifest::manifest::ExecutionLevel; + +fn main() { + ////强制用管理员运行貌似体验更差了 + // if std::env::var_os("CARGO_CFG_WINDOWS").is_some() { + // embed_manifest(new_manifest("vnt") + // .requested_execution_level(ExecutionLevel::RequireAdministrator)).expect("unable to embed manifest file"); + // } +} \ No newline at end of file diff --git a/switch-cmd/src/command/client.rs b/vnt-cli/src/command/client.rs similarity index 96% rename from switch-cmd/src/command/client.rs rename to vnt-cli/src/command/client.rs index 903dbe9..21143a9 100644 --- a/switch-cmd/src/command/client.rs +++ b/vnt-cli/src/command/client.rs @@ -11,7 +11,7 @@ pub struct CommandClient { impl CommandClient { pub fn new() -> io::Result { - let path_buf = dirs::home_dir().unwrap().join(".switch_desktop").join("command-port"); + let path_buf = crate::app_home()?.join("command-port"); if !path_buf.exists() { return Err(io::Error::new(io::ErrorKind::Other, "not started")); } diff --git a/switch-cmd/src/command/entity.rs b/vnt-cli/src/command/entity.rs similarity index 100% rename from switch-cmd/src/command/entity.rs rename to vnt-cli/src/command/entity.rs diff --git a/switch-cmd/src/command/mod.rs b/vnt-cli/src/command/mod.rs similarity index 83% rename from switch-cmd/src/command/mod.rs rename to vnt-cli/src/command/mod.rs index 7b9f11b..a0f3e9f 100644 --- a/switch-cmd/src/command/mod.rs +++ b/vnt-cli/src/command/mod.rs @@ -1,5 +1,5 @@ use std::io; -use switch::core::Switch; +use vnt::core::Vnt; use crate::command::entity::{DeviceItem, RouteItem, Info}; use crate::console_out; @@ -47,11 +47,11 @@ fn command_(cmd: CommandEnum) -> io::Result<()> { Ok(()) } -pub fn command_route(switch: &Switch) -> Vec { - let route_table = switch.route_table(); +pub fn command_route(vnt: &Vnt) -> Vec { + let route_table = vnt.route_table(); let mut route_list = Vec::with_capacity(route_table.len()); for (destination, route) in route_table { - let next_hop = switch.route_key(&route.route_key()).map_or(String::new(), |v| v.to_string()); + let next_hop = vnt.route_key(&route.route_key()).map_or(String::new(), |v| v.to_string()); let metric = route.metric.to_string(); let rt = if route.rt < 0 { "".to_string() @@ -71,13 +71,13 @@ pub fn command_route(switch: &Switch) -> Vec { route_list } -pub fn command_list(switch: &Switch) -> Vec { - let device_list = switch.device_list(); +pub fn command_list(vnt: &Vnt) -> Vec { + let device_list = vnt.device_list(); let mut list = Vec::new(); for peer in device_list { let name = peer.name; let virtual_ip = peer.virtual_ip.to_string(); - let (nat_type, public_ips, local_ip) = if let Some(nat_info) = switch.peer_nat_info(&peer.virtual_ip) { + let (nat_type, public_ips, local_ip) = if let Some(nat_info) = vnt.peer_nat_info(&peer.virtual_ip) { let nat_type = format!("{:?}", nat_info.nat_type); let public_ips: Vec = nat_info.public_ips.iter().map(|v| v.to_string()).collect(); let public_ips = public_ips.join(","); @@ -86,7 +86,7 @@ pub fn command_list(switch: &Switch) -> Vec { } else { ("".to_string(), "".to_string(), "".to_string()) }; - let (nat_traversal_type, rt) = if let Some(route) = switch.route(&peer.virtual_ip) { + let (nat_traversal_type, rt) = if let Some(route) = vnt.route(&peer.virtual_ip) { let nat_traversal_type = if route.metric == 1 { "p2p" } else { "relay" }.to_string(); let rt = if route.rt < 0 { "".to_string() @@ -113,14 +113,14 @@ pub fn command_list(switch: &Switch) -> Vec { list } -pub fn command_info(switch: &Switch) -> Info { - let current_device = switch.current_device(); - let nat_info = switch.nat_info(); - let name = switch.name().to_string(); +pub fn command_info(vnt: &Vnt) -> Info { + let current_device = vnt.current_device(); + let nat_info = vnt.nat_info(); + let name = vnt.name().to_string(); let virtual_ip = current_device.virtual_ip().to_string(); let virtual_gateway = current_device.virtual_gateway().to_string(); let virtual_netmask = current_device.virtual_netmask.to_string(); - let connect_status = format!("{:?}", switch.connection_status()); + let connect_status = format!("{:?}", vnt.connection_status()); let relay_server = current_device.connect_server.to_string(); let nat_type = format!("{:?}", nat_info.nat_type); let public_ips: Vec = nat_info.public_ips.iter().map(|v| v.to_string()).collect(); diff --git a/switch-cmd/src/command/server.rs b/vnt-cli/src/command/server.rs similarity index 79% rename from switch-cmd/src/command/server.rs rename to vnt-cli/src/command/server.rs index d46b240..83eff1d 100644 --- a/switch-cmd/src/command/server.rs +++ b/vnt-cli/src/command/server.rs @@ -2,7 +2,7 @@ use std::io; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use tokio::net::UdpSocket; -use switch::core::Switch; +use vnt::core::Vnt; pub struct CommandServer {} @@ -14,7 +14,7 @@ impl CommandServer { } impl CommandServer { - pub async fn start(self, switch: Switch) -> io::Result<()> { + pub async fn start(self, vnt: Vnt) -> io::Result<()> { let mut port = 21637 as u16; let udp = loop { match UdpSocket::bind(SocketAddr::V4(SocketAddrV4::new( @@ -34,20 +34,17 @@ impl CommandServer { } } }; - let path_buf = dirs::home_dir().unwrap().join(".switch_desktop").join("command-port"); - if !path_buf.parent().unwrap().exists() { - std::fs::create_dir_all(path_buf.parent().unwrap())?; - } - std::fs::write(path_buf,udp.local_addr()?.port().to_string())?; + let path_buf = crate::app_home()?.join("command-port"); + std::fs::write(path_buf, udp.local_addr()?.port().to_string())?; let mut buf = [0u8; 64]; loop { let (len, addr) = udp.recv_from(&mut buf).await?; match std::str::from_utf8(&buf[..len]) { Ok(cmd) => { - if let Ok(out) = command(cmd, &switch) { + if let Ok(out) = command(cmd, &vnt) { let _ = udp.send_to(out.as_bytes(), addr).await; if "stopped" == &out { - break; + break; } } } @@ -61,10 +58,10 @@ impl CommandServer { } -fn command(cmd: &str, switch: &Switch) -> io::Result { +fn command(cmd: &str, vnt: &Vnt) -> io::Result { let out_str = match cmd { "route" => { - match serde_json::to_string(&crate::command::command_route(switch)) { + match serde_json::to_string(&crate::command::command_route(vnt)) { Ok(str) => { str } @@ -74,7 +71,7 @@ fn command(cmd: &str, switch: &Switch) -> io::Result { } } "list" => { - match serde_json::to_string(&crate::command::command_list(switch)) { + match serde_json::to_string(&crate::command::command_list(vnt)) { Ok(str) => { str } @@ -84,7 +81,7 @@ fn command(cmd: &str, switch: &Switch) -> io::Result { } } "info" => { - match serde_json::to_string(&crate::command::command_info(switch)) { + match serde_json::to_string(&crate::command::command_info(vnt)) { Ok(str) => { str } @@ -94,7 +91,7 @@ fn command(cmd: &str, switch: &Switch) -> io::Result { } } "stop" => { - switch.stop()?; + vnt.stop()?; "stopped".to_string() } _ => { diff --git a/switch-cmd/src/console_out/mod.rs b/vnt-cli/src/console_out/mod.rs similarity index 100% rename from switch-cmd/src/console_out/mod.rs rename to vnt-cli/src/console_out/mod.rs diff --git a/switch-cmd/src/console_out/table.rs b/vnt-cli/src/console_out/table.rs similarity index 100% rename from switch-cmd/src/console_out/table.rs rename to vnt-cli/src/console_out/table.rs diff --git a/switch-cmd/src/main.rs b/vnt-cli/src/main.rs similarity index 68% rename from switch-cmd/src/main.rs rename to vnt-cli/src/main.rs index a6fea52..ba046e0 100644 --- a/switch-cmd/src/main.rs +++ b/vnt-cli/src/main.rs @@ -1,36 +1,52 @@ -use std::net::ToSocketAddrs; +use std::io; +use std::net::{Ipv4Addr, ToSocketAddrs}; +use std::path::PathBuf; use std::str::FromStr; -#[cfg(not(feature = "mini"))] use console::style; use getopts::Options; use tokio::io::{AsyncBufReadExt, BufReader}; use common::args_parse::ips_parse; -use switch::core::{Config, SwitchUtil}; -use switch::handle::registration_handler::ReqEnum; +use vnt::core::{Config, VntUtil}; +use vnt::handle::registration_handler::ReqEnum; mod command; mod console_out; mod root_check; +pub fn app_home() -> io::Result { + let path = dirs::home_dir().ok_or(io::Error::new(io::ErrorKind::Other, "not home"))?.join(".vnt-cli"); + if !path.exists() { + std::fs::create_dir_all(&path)?; + } + Ok(path) +} + #[tokio::main] async fn main() { + main0().await; + std::process::exit(0); +} + +async fn main0() { let args: Vec = std::env::args().collect(); let program = args[0].clone(); let mut opts = Options::new(); opts.long_only(false); - opts.optopt("k", "", &format!("{}", green("使用相同的token,就能组建一个局域网络".to_string())), ""); - opts.optopt("n", "", "给设备一个名字", ""); - opts.optopt("d", "", "设备唯一标识符,凭id分配ip", ""); - #[cfg(not(feature = "mini"))] - opts.optflag("c", "", "关闭交互式命令"); + opts.optopt("k", "", &format!("{}", green("必选,使用相同的token,就能组建一个局域网络".to_string())), ""); + opts.optopt("n", "", "给设备一个名字,默认使用系统版本", ""); + opts.optopt("d", "", "设备唯一标识符,不使用--ip参数时,服务端凭此参数分配ip", ""); + opts.optflag("c", "", "关闭交互式命令,使用此参数禁用控制台输入"); opts.optopt("s", "", "注册和中继服务器地址", ""); opts.optopt("e", "", "NAT探测服务器地址,使用逗号分隔", ""); opts.optflag("a", "", "使用tap模式,默认使用tun模式"); - opts.optmulti("i", "", "配置点对网(IP代理)时使用,-i 192.168.10.0/24,10.26.0.3,表示允许接收网段192.168.10.0/24的数据并转发到10.26.0.3", ""); - opts.optmulti("o", "", "配置点对网时使用,-o 192.168.10.0/24,192.168.1.10,表示允许目标为192.168.10.0/24的数据从网卡192.168.1.10转发出去", ""); + opts.optmulti("i", "", "配置点对网(IP代理)时使用,-i 192.168.0.0/24,10.26.0.3,表示允许接收网段192.168.0.0/24的数据并转发到10.26.0.3", ""); + opts.optmulti("o", "", "配置点对网时使用,-o 192.168.0.0/24,192.168.0.10,表示允许目标为192.168.0.0/24的数据从网卡192.168.0.10转发出去", ""); opts.optopt("w", "", "使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信", ""); opts.optflag("m", "", "模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送"); opts.optopt("u", "", "虚拟网卡mtu值", ""); + opts.optflag("", "tcp", "和服务端使用tcp通信,默认使用udp,一般来说udp延迟和消耗更低"); + opts.optopt("", "ip", "指定虚拟ip,指定的ip不能和其他设备重复,必须有效并且在服务端所属网段下,默认情况由服务端分配", ""); + opts.optflag("", "relay", "仅使用服务器转发,不使用p2p,默认情况允许使用p2p"); //"后台运行时,查看其他设备列表" opts.optflag("", "list", &format!("{}", yellow("后台运行时,查看其他设备列表".to_string()))); opts.optflag("", "all", &format!("{}", yellow("后台运行时,查看其他设备完整信息".to_string()))); @@ -52,6 +68,8 @@ async fn main() { } if !root_check::is_app_elevated() { println!("Please run it with administrator or root privileges"); + #[cfg(any(target_os = "linux", target_os = "macos"))] + sudo::escalate_if_needed().unwrap(); return; } if matches.opt_present("list") { @@ -78,9 +96,19 @@ async fn main() { let tap = matches.opt_present("a"); let token: String = matches.opt_get("k").unwrap().unwrap(); let device_id = matches.opt_get_default("d", String::new()).unwrap(); - #[cfg(not(feature = "mini"))] - let device_id = if device_id.is_empty() { - common::identifier::get_unique_identifier().unwrap_or(String::new()) + let device_id = if device_id.is_empty() { + if let Some(id) = common::identifier::get_unique_identifier() { + id + } else { + let path_buf = app_home().unwrap().join("device-id"); + if let Ok(id) = std::fs::read_to_string(path_buf.as_path()) { + id + } else { + let id = uuid::Uuid::new_v4().to_string(); + let _ = std::fs::write(path_buf, &id); + id + } + } } else { device_id }; @@ -91,7 +119,20 @@ async fn main() { } let name = matches.opt_get_default("n", os_info::get().to_string()).unwrap(); let server_address_str = matches.opt_get_default("s", "nat1.wherewego.top:29871".to_string()).unwrap(); - let server_address = server_address_str.to_socket_addrs().unwrap().next().unwrap(); + let server_address = match server_address_str.to_socket_addrs() { + Ok(mut addr) => { + if let Some(addr) = addr.next() { + addr + } else { + println!("parameter -s error ."); + return; + } + } + Err(e) => { + println!("parameter -s error {}.", e); + return; + } + }; let nat_test_server = matches.opt_get_default("e", "nat1.wherewego.top:35061,nat1.wherewego.top:35062,nat2.wherewego.top:35061,nat2.wherewego.top:35062".to_string()).unwrap(); @@ -120,10 +161,7 @@ async fn main() { }; let password: Option = matches.opt_get("w").unwrap(); let simulate_multicast = matches.opt_present("m"); - #[cfg(feature = "mini")] - let unused_cmd = true; - #[cfg(not(feature = "mini"))] - let unused_cmd = matches.opt_present("c"); + let unused_cmd = matches.opt_present("c"); let mtu: Option = matches.opt_get("u").unwrap(); let mtu = if let Some(mtu) = mtu { match u16::from_str(&mtu) { @@ -140,14 +178,24 @@ async fn main() { } else { None }; + let virtual_ip: Option = matches.opt_get("ip").unwrap(); + let virtual_ip = virtual_ip.map(|v| Ipv4Addr::from_str(&v).expect("--ip error")); + if let Some(virtual_ip) = virtual_ip { + if virtual_ip.is_unspecified() || virtual_ip.is_broadcast() || virtual_ip.is_multicast() { + println!("--ip invalid"); + return; + } + } + let tcp_channel = matches.opt_present("tcp"); + let relay = matches.opt_present("relay"); let config = Config::new(tap, token, device_id, name, server_address, server_address_str, nat_test_server, in_ip, - out_ip, password, simulate_multicast, mtu); - let mut switch_util = SwitchUtil::new(config).await.unwrap(); + out_ip, password, simulate_multicast, mtu, tcp_channel, virtual_ip, relay); + let mut vnt_util = VntUtil::new(config).await.unwrap(); let response = loop { - match switch_util.connect().await { + match vnt_util.connect().await { Ok(response) => { break response; } @@ -165,9 +213,17 @@ async fn main() { } ReqEnum::ServerError(str) => { println!("error:{}", str); + continue; } ReqEnum::Other(str) => { println!("error:{}", str); + continue; + } + ReqEnum::IpAlreadyExists => { + println!("ip already exists"); + } + ReqEnum::InvalidIp => { + println!("invalid ip"); } } return; @@ -177,13 +233,13 @@ async fn main() { println!(" ====== Connect Successfully ====== "); println!("virtual_gateway:{}", response.virtual_gateway); println!("virtual_ip:{}", green(response.virtual_ip.to_string())); - let driver_info = switch_util.create_iface().unwrap(); + let driver_info = vnt_util.create_iface().unwrap(); println!(" ====== Create Network Interface Successfully ====== "); println!("name:{}", driver_info.name); println!("version:{}", driver_info.version); - let mut switch = match switch_util.build().await { - Ok(switch) => { - switch + let mut vnt = match vnt_util.build().await { + Ok(vnt) => { + vnt } Err(e) => { println!("error:{}", e); @@ -191,25 +247,21 @@ async fn main() { } }; println!(" ====== Start Successfully ====== "); - let switch_s = switch.clone(); + let vnt_c = vnt.clone(); tokio::spawn(async { - if let Err(e) = command::server::CommandServer::new().start(switch_s).await { + if let Err(e) = command::server::CommandServer::new().start(vnt_c).await { println!("command error :{}", e); } }); - if unused_cmd { - switch.wait_stop().await; - } else { - #[cfg(not(feature = "mini"))] - { - let stdin = tokio::io::stdin(); - let mut cmd = String::new(); - let mut reader = BufReader::new(stdin); - loop { - cmd.clear(); - println!("input:list,info,route,all,stop"); - tokio::select! { - _ = switch.wait_stop()=>{ + if !unused_cmd { + let stdin = tokio::io::stdin(); + let mut cmd = String::new(); + let mut reader = BufReader::new(stdin); + loop { + cmd.clear(); + println!("input:list,info,route,all,stop"); + tokio::select! { + _ = vnt.wait_stop()=>{ break; } rs = reader.read_line(&mut cmd)=>{ @@ -220,23 +272,23 @@ async fn main() { } match cmd[..len].to_lowercase().trim() { "list" => { - let list = command::command_list(&switch); + let list = command::command_list(&vnt); console_out::console_device_list(list); } "info"=>{ - let info = command::command_info(&switch); + let info = command::command_info(&vnt); console_out::console_info(info); } "route" =>{ - let route = command::command_route(&switch); + let route = command::command_route(&vnt); console_out::console_route_table(route); } "all" =>{ - let list = command::command_list(&switch); + let list = command::command_list(&vnt); console_out::console_device_list_all(list); } "stop" =>{ - let _ = switch.stop(); + let _ = vnt.stop(); break; } _ => { @@ -251,16 +303,14 @@ async fn main() { } } } - } - switch.wait_stop().await; } } - std::process::exit(0); + vnt.wait_stop().await; } fn print_usage(program: &str, opts: Options) { let brief = format!("Usage: {} [options]", program); - println!("version:1.1.0"); + println!("version:1.1.1"); println!("{}", opts.usage(&brief)); } diff --git a/switch-cmd/src/root_check/mod.rs b/vnt-cli/src/root_check/mod.rs similarity index 100% rename from switch-cmd/src/root_check/mod.rs rename to vnt-cli/src/root_check/mod.rs diff --git a/switch-cmd/src/root_check/unix.rs b/vnt-cli/src/root_check/unix.rs similarity index 100% rename from switch-cmd/src/root_check/unix.rs rename to vnt-cli/src/root_check/unix.rs diff --git a/switch-cmd/src/root_check/windows.rs b/vnt-cli/src/root_check/windows.rs similarity index 100% rename from switch-cmd/src/root_check/windows.rs rename to vnt-cli/src/root_check/windows.rs diff --git a/switch-jni/Cargo.toml b/vnt-jni/Cargo.toml similarity index 84% rename from switch-jni/Cargo.toml rename to vnt-jni/Cargo.toml index f0d2119..cd2b911 100644 --- a/switch-jni/Cargo.toml +++ b/vnt-jni/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "switch-jni" +name = "vnt-jni" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -switch = {path="../switch"} +vnt = {path="../vnt"} jni = { version = "0.21.1", default-features = false } [lib] diff --git a/switch-jni/README.md b/vnt-jni/README.md similarity index 100% rename from switch-jni/README.md rename to vnt-jni/README.md diff --git a/vnt-jni/src/lib.rs b/vnt-jni/src/lib.rs new file mode 100644 index 0000000..e76b773 --- /dev/null +++ b/vnt-jni/src/lib.rs @@ -0,0 +1,2 @@ +pub mod vnt_util; +pub mod vnt; \ No newline at end of file diff --git a/switch-jni/src/switch.rs b/vnt-jni/src/vnt.rs similarity index 68% rename from switch-jni/src/switch.rs rename to vnt-jni/src/vnt.rs index b73d2f7..893d864 100644 --- a/switch-jni/src/switch.rs +++ b/vnt-jni/src/vnt.rs @@ -3,39 +3,39 @@ use jni::errors::Error; use jni::JNIEnv; use jni::objects::{JClass, JObject, JValue}; use jni::sys::{jboolean, jbyte, jint, jlong, jobject, jobjectArray, jsize}; -use switch::channel::Route; -use switch::core::sync::SwitchSync; -use switch::handle::PeerDeviceInfo; +use vnt::channel::Route; +use vnt::core::sync::VntSync; +use vnt::handle::PeerDeviceInfo; #[no_mangle] -pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_stop0( +pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_stop0( _env: JNIEnv, _class: JClass, - raw_switch: jlong, + raw_vnt: jlong, ) { - let switch = raw_switch as *mut SwitchSync; - let _ = (&*switch).stop(); + let vnt = raw_vnt as *mut VntSync; + let _ = (&*vnt).stop(); } #[no_mangle] -pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_waitStop0( +pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_waitStop0( _env: JNIEnv, _class: JClass, - raw_switch: jlong, + raw_vnt: jlong, ) { - let switch = raw_switch as *mut SwitchSync; - let _ = (&mut *switch).wait_stop(); + let vnt = raw_vnt as *mut VntSync; + let _ = (&mut *vnt).wait_stop(); } #[no_mangle] -pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_waitStopMs0( +pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_waitStopMs0( _env: JNIEnv, _class: JClass, - raw_switch: jlong, + raw_vnt: jlong, ms: jlong, ) -> jboolean { - let switch = raw_switch as *mut SwitchSync; - if (&mut *switch).wait_stop_ms(ms as _) { + let vnt = raw_vnt as *mut VntSync; + if (&mut *vnt).wait_stop_ms(ms as _) { jni::sys::JNI_TRUE } else { jni::sys::JNI_FALSE @@ -43,28 +43,28 @@ pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_waitStopMs0( } #[no_mangle] -pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_drop0( +pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_drop0( _env: JNIEnv, _class: JClass, - raw_switch: jlong, + raw_vnt: jlong, ) { - let switch = raw_switch as *mut SwitchSync; - let _ = Box::from_raw(switch).stop(); + let vnt = raw_vnt as *mut VntSync; + let _ = Box::from_raw(vnt).stop(); } #[no_mangle] -pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_list0( +pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_list0( mut env: JNIEnv, _class: JClass, - raw_switch: jlong, + raw_vnt: jlong, ) -> jobjectArray { - let switch = raw_switch as *mut SwitchSync; - let switch = &mut *switch; - let list = switch.device_list(); + let vnt = raw_vnt as *mut VntSync; + let vnt = &mut *vnt; + let list = vnt.device_list(); let arr = match env.new_object_array( list.len() as jsize, - "top/wherewego/switchjni/PeerDeviceInfo", + "top/wherewego/vnt/jni/PeerDeviceInfo", JObject::null(), ) { Ok(arr) => { arr } @@ -75,7 +75,7 @@ pub unsafe extern "C" fn Java_top_wherewego_switchjni_Switch_list0( } }; for (index, peer) in list.into_iter().enumerate() { - let route = if let Some(route) = switch.route(&peer.virtual_ip) { + let route = if let Some(route) = vnt.route(&peer.virtual_ip) { match route_parse(&mut env, route) { Ok(route) => { JObject::from_raw(route) @@ -113,7 +113,7 @@ fn route_parse(env: &mut JNIEnv, route: Route) -> Result { let metric = route.metric; let rt = route.rt; let rs = env.new_object( - "top/wherewego/switchjni/Route", + "top/wherewego/vnt/jni/Route", "(Ljava/lang/String;BI)V", &[JValue::Object(&env.new_string(address)?.into()), JValue::Byte(metric as jbyte), @@ -127,8 +127,8 @@ fn peer_device_info_parse(env: &mut JNIEnv, peer: PeerDeviceInfo, route: JObject let name = peer.name.to_string(); let status = format!("{:?}", peer.status); let rs = env.new_object( - "top/wherewego/switchjni/PeerDeviceInfo", - "(ILjava/lang/String;Ljava/lang/String;Ltop/wherewego/switchjni/Route;)V", + "top/wherewego/vnt/jni/PeerDeviceInfo", + "(ILjava/lang/String;Ljava/lang/String;Ltop/wherewego/vnt/jni/Route;)V", &[JValue::Int(virtual_ip as jint), JValue::Object(&env.new_string(name)?.into()), JValue::Object(&env.new_string(status)?.into()), diff --git a/switch-jni/src/switch_util.rs b/vnt-jni/src/vnt_util.rs similarity index 71% rename from switch-jni/src/switch_util.rs rename to vnt-jni/src/vnt_util.rs index ca81111..e1fe6e0 100644 --- a/switch-jni/src/switch_util.rs +++ b/vnt-jni/src/vnt_util.rs @@ -7,11 +7,11 @@ use jni::objects::{JClass, JObject, JString, JValue}; use jni::sys::jboolean; use jni::sys::{jint, jlong, jobject}; use jni::JNIEnv; -use switch::core::Config; -use switch::core::sync::SwitchUtilSync; -use switch::handle::registration_handler::{RegResponse, ReqEnum}; +use vnt::core::Config; +use vnt::core::sync::VntUtilSync; +use vnt::handle::registration_handler::{RegResponse, ReqEnum}; #[cfg(not(target_os = "android"))] -use switch::tun_tap_device::DriverInfo; +use vnt::tun_tap_device::DriverInfo; fn to_string_not_null(env: &mut JNIEnv, config: &JObject, name: &'static str) -> Result { let value = env.get_field(config, name, "Ljava/lang/String;")?.l()?; @@ -49,7 +49,7 @@ fn to_string(env: &mut JNIEnv, config: &JObject, name: &str) -> Result Result { +fn new_sync(env: &mut JNIEnv, config: JObject) -> Result { let token = to_string_not_null(env, &config, "token")?; let name = to_string_not_null(env, &config, "name")?; let device_id = to_string_not_null(env, &config, "deviceId")?; @@ -78,13 +78,13 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result token, device_id, name, server_address, server_address_str, nat_test_server, vec![], - vec![], password, false, None); - match SwitchUtilSync::new(config) { - Ok(switch_util) => { - Ok(switch_util) + vec![], password, false, None, false, None, false); + match VntUtilSync::new(config) { + Ok(vnt_util) => { + Ok(vnt_util) } Err(e) => { - env.throw_new("Ljava/lang/RuntimeException", format!("switch start error {}", e)) + env.throw_new("Ljava/lang/RuntimeException", format!("vnt start error {}", e)) .expect("throw"); return Err(Error::JavaException); } @@ -92,14 +92,14 @@ fn new_sync(env: &mut JNIEnv, config: JObject) -> Result } #[no_mangle] -pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_new0( +pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_new0( mut env: JNIEnv, _class: JClass, config: JObject, ) -> jlong { match new_sync(&mut env, config) { - Ok(switch_util) => { - let ptr = Box::into_raw(Box::new(switch_util)); + Ok(vnt_util) => { + let ptr = Box::into_raw(Box::new(vnt_util)); return ptr as jlong; } Err(_) => {} @@ -108,43 +108,51 @@ pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_new0( } #[no_mangle] -pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_connect0( +pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_connect0( mut env: JNIEnv, _class: JClass, - raw_switch_util: jlong, + raw_vnt_util: jlong, ) -> jobject { - let raw_switch_util = raw_switch_util as *mut SwitchUtilSync; - match (&mut *raw_switch_util).connect() { + let raw_vnt_util = raw_vnt_util as *mut VntUtilSync; + match (&mut *raw_vnt_util).connect() { Ok(response) => { match reg_response(&mut env, response) { Ok(res) => { return res; } Err(e) => { - env.throw(format!("switch connect error {}", e)).expect("throw"); + env.throw(format!("vnt connect error {}", e)).expect("throw"); } } } Err(e) => { match e { ReqEnum::TokenError => { - env.throw_new("top/wherewego/switchjni/exception/TokenErrorException", "TokenError") + env.throw_new("top/wherewego/vnt/jni/exception/TokenErrorException", "TokenError") .expect("throw"); } ReqEnum::AddressExhausted => { - env.throw_new("top/wherewego/switchjni/exception/AddressExhaustedException", "AddressExhausted") + env.throw_new("top/wherewego/vnt/jni/exception/AddressExhaustedException", "AddressExhausted") .expect("throw"); } ReqEnum::Timeout => { - env.throw_new("top/wherewego/switchjni/exception/TimeoutException", "Timeout") + env.throw_new("top/wherewego/vnt/jni/exception/TimeoutException", "Timeout") .expect("throw"); } ReqEnum::ServerError(str) => { - env.throw_new("java/lang/RuntimeException", format!("switch connect error {}", str)) + env.throw_new("java/lang/RuntimeException", format!("vnt connect error {}", str)) .expect("throw"); } ReqEnum::Other(str) => { - env.throw_new("java/lang/RuntimeException", format!("switch connect error {}", str)) + env.throw_new("java/lang/RuntimeException", format!("vnt connect error {}", str)) + .expect("throw"); + } + ReqEnum::IpAlreadyExists => { + env.throw_new("top/wherewego/vnt/jni/exception/IpAlreadyExistsException", "IpAlreadyExists") + .expect("throw"); + } + ReqEnum::InvalidIp => { + env.throw_new("top/wherewego/vnt/jni/exception/InvalidIpException", "InvalidIp") .expect("throw"); } } @@ -155,27 +163,26 @@ pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_connect0( #[cfg(target_os = "android")] #[no_mangle] -pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_createIface0( +pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_createIface0( _env: JNIEnv, _class: JClass, - raw_switch_util: jlong, + raw_vnt_util: jlong, fd: jint, ) { - let raw_switch_util = raw_switch_util as *mut SwitchUtilSync; + let raw_vnt_util = raw_vnt_util as *mut VntUtilSync; - (&mut *raw_switch_util).create_iface(fd as i32); + (&mut *raw_vnt_util).create_iface(fd as i32); } #[cfg(not(target_os = "android"))] #[no_mangle] -pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_createIface0( +pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_createIface0( mut env: JNIEnv, _class: JClass, - raw_switch_util: jlong, + raw_vnt_util: jlong, ) -> jobject { - let raw_switch_util = raw_switch_util as *mut SwitchUtilSync; - #[cfg(not(target_os = "android"))] - let rs = (&mut *raw_switch_util).create_iface(); + let raw_vnt_util = raw_vnt_util as *mut VntUtilSync; + let rs = (&mut *raw_vnt_util).create_iface(); match rs { Ok(driver_info) => { match driver_info_e(&mut env, driver_info) { @@ -183,12 +190,12 @@ pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_createIface0( return res; } Err(e) => { - env.throw(format!("switch create iface error {}", e)).expect("throw"); + env.throw(format!("vnt create iface error {}", e)).expect("throw"); } } } Err(e) => { - env.throw_new("java/lang/RuntimeException", format!("switch create iface error {}", e)) + env.throw_new("java/lang/RuntimeException", format!("vnt create iface error {}", e)) .expect("throw"); } } @@ -196,18 +203,18 @@ pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_createIface0( } #[no_mangle] -pub unsafe extern "C" fn Java_top_wherewego_switchjni_SwitchUtil_build0( +pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_build0( mut env: JNIEnv, _class: JClass, - raw_switch_util: jlong, + raw_vnt_util: jlong, ) -> jlong { - let raw_switch_util = Box::from_raw(raw_switch_util as *mut SwitchUtilSync); - match raw_switch_util.build() { + let raw_vnt_util = Box::from_raw(raw_vnt_util as *mut VntUtilSync); + match raw_vnt_util.build() { Ok(rs) => { return Box::into_raw(Box::new(rs)) as jlong; } Err(e) => { - env.throw_new("java/lang/RuntimeException", format!("switch start error:{:?}", e)) + env.throw_new("java/lang/RuntimeException", format!("vnt start error:{:?}", e)) .expect("throw"); } } @@ -219,7 +226,7 @@ fn reg_response(env: &mut JNIEnv, response: RegResponse) -> Result Result, - pub(crate) count: AtomicUsize, + //udp用于打洞、服务端通信(可选) pub(crate) main_channel: Arc, + //在udp的基础上,可以选择使用tcp和服务端通信 + pub(crate) main_tcp_channel: Option>>, pub(crate) route_table: SkipMap>, pub(crate) route_table_time: SkipMap<(RouteKey, Ipv4Addr), AtomicCell>, pub(crate) status_receiver: Receiver, pub(crate) status_sender: Sender, pub(crate) udp_map: SkipMap>, pub(crate) channel_num: usize, + current_device: Arc>, } #[derive(Clone)] @@ -31,20 +36,21 @@ pub struct Context { } impl Context { - pub fn new(main_channel: Arc, _channel_num: usize) -> Self { + pub fn new(main_channel: Arc, main_tcp_channel: Option>>, current_device: Arc>, _channel_num: usize) -> Self { //当前版本只支持一个通道 let channel_num = 1; let (status_sender, status_receiver) = channel(Status::Cone); let inner = Arc::new(ContextInner { lock: Mutex::new(()), - count: AtomicUsize::new(0), main_channel, + main_tcp_channel, route_table: SkipMap::new(), route_table_time: SkipMap::new(), status_receiver, status_sender, udp_map: SkipMap::new(), channel_num, + current_device, }); Self { inner @@ -82,7 +88,30 @@ impl Context { self.inner.main_channel.local_addr().map(|k| k.port()) } pub async fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result { - self.inner.main_channel.send_to(buf, addr).await + if let Some(sender) = &self.inner.main_tcp_channel { + let mut vec = vec![0; 4 + buf.len()]; + vec[4..].copy_from_slice(buf); + if sender.send(vec).await.is_ok() { + Ok(buf.len()) + } else { + Err(io::Error::new(io::ErrorKind::Other, "send_main err")) + } + } else { + self.inner.main_channel.send_to(buf, addr).await + } + } + pub fn try_send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result { + if let Some(sender) = &self.inner.main_tcp_channel { + let mut vec = vec![0; 4 + buf.len()]; + vec[4..].copy_from_slice(buf); + if sender.try_send(vec).is_ok() { + Ok(buf.len()) + } else { + Err(io::Error::new(io::ErrorKind::Other, "try_send_main err")) + } + } else { + self.inner.main_channel.try_send_to(buf, addr) + } } pub(crate) async fn send_all(&self, buf: &[u8], addr: SocketAddr) -> io::Result<()> { @@ -91,31 +120,36 @@ impl Context { } Ok(()) } - pub fn try_send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result { - self.inner.main_channel.try_send_to(buf, addr) - } + pub async fn send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result { if let Some(v) = self.inner.route_table.get(id) { - let route = match v.value().len() { - 0 => { - return Err(io::Error::new(io::ErrorKind::NotFound, "route not found")); - } - 1 => v.value()[0], - len => v.value()[self.inner.count.fetch_add(1, Ordering::Relaxed) % len] - }; + if v.value().is_empty() { + return Err(io::Error::new(io::ErrorKind::NotFound, "route not found")); + } + let route = v.value()[0]; drop(v); + if !route.is_p2p() { + if let Some(time) = self.inner.route_table_time.get(&(route.route_key(), *id)) { + //借道传输时,长时间不通信的通道不使用 + if time.value().load().elapsed() > Duration::from_secs(3) { + return Err(io::Error::new(io::ErrorKind::NotFound, "route time out")); + } + } + } + if let Some(udp) = self.inner.udp_map.get(&route.index) { return udp.value().send_to(buf, route.addr).await; } } Err(io::Error::new(io::ErrorKind::NotFound, "route not found")) } + pub fn try_send_by_id(&self, buf: &[u8], id: &Ipv4Addr) -> io::Result { if let Some(v) = self.inner.route_table.get(id) { if v.value().is_empty() { return Err(io::Error::new(io::ErrorKind::NotFound, "route not found")); } - let route = v.value()[self.inner.count.fetch_add(1, Ordering::Relaxed) % v.value().len()]; + let route = v.value()[0]; drop(v); if let Some(udp) = self.inner.udp_map.get(&route.index) { return udp.value().try_send_to(buf, route.addr); @@ -124,12 +158,34 @@ impl Context { Err(io::Error::new(io::ErrorKind::NotFound, "route not found")) } pub async fn send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result { + if route_key.index == 0 { + if let Some(sender) = &self.inner.main_tcp_channel { + let mut vec = vec![0; 4 + buf.len()]; + vec[4..].copy_from_slice(buf); + return if sender.send(vec).await.is_ok() { + Ok(buf.len()) + } else { + Err(io::Error::new(io::ErrorKind::Other, "send_by_key err")) + }; + } + } if let Some(udp) = self.inner.udp_map.get(&route_key.index) { return udp.value().send_to(buf, route_key.addr).await; } Err(io::Error::new(io::ErrorKind::NotFound, "route not found")) } pub fn try_send_by_key(&self, buf: &[u8], route_key: &RouteKey) -> io::Result { + if route_key.index == 0 { + if let Some(sender) = &self.inner.main_tcp_channel { + let mut vec = vec![0; 4 + buf.len()]; + vec[4..].copy_from_slice(buf); + return if sender.try_send(vec).is_ok() { + Ok(buf.len()) + } else { + Err(io::Error::new(io::ErrorKind::Other, "try_send_by_key err")) + }; + } + } if let Some(udp) = self.inner.udp_map.get(&route_key.index) { return udp.value().try_send_to(buf, route_key.addr); } @@ -280,30 +336,105 @@ impl Channel { impl Channel { async fn handle(handler: &mut ChannelDataHandler, - udp: &Arc, context: &Context, id: usize, result: io::Result<(usize, SocketAddr)>, buf: &mut [u8], start: usize) { match result { Ok((len, addr)) => { - handler.handle(buf, start, start + len, RouteKey::new(id, addr), &udp, context).await; + handler.handle(buf, start, start + len, RouteKey::new(id, addr), context).await; } Err(e) => { log::error!("{:?}",e) } } } + async fn tcp_handle(mut tcp_r: OwnedReadHalf, context: Context, + mut handler: ChannelDataHandler, head_reserve: usize, ) -> io::Result<()> { + let mut buf = [0; 4096]; + let addr = tcp_r.peer_addr()?; + let key = RouteKey::new(0, addr); + loop { + tcp_r.read_exact(&mut buf[head_reserve..head_reserve + 4]).await?; + let len = 4 + (((buf[head_reserve + 2] as u16) << 8) | buf[head_reserve + 3] as u16) as usize; + tcp_r.read_exact(&mut buf[head_reserve + 4..head_reserve + len]).await?; + handler.handle(&mut buf[4..], head_reserve, head_reserve + len - 4, key, &context).await; + } + } + async fn start_tcp(mut worker: VntWorker, tcp_stream: TcpStream, mut receiver: tokio::sync::mpsc::Receiver>, context: Context, handler: ChannelDataHandler, head_reserve: usize) { + let (tcp_r, mut tcp_w) = tcp_stream.into_split(); + { + let context = context.clone(); + let handler = handler.clone(); + tokio::spawn(async move { + if let Err(e) = Self::tcp_handle(tcp_r, context, handler, head_reserve).await { + log::info!("tcp链接断开:{:?}",e); + } + }); + } + loop { + tokio::select! { + _=worker.stop_wait()=>{ + break; + } + rs=receiver.recv()=>{ + if let Some(mut data) = rs{ + if data.len()<4{ + continue + } + let len = data.len() - 4; + data[2] = (len >> 8) as u8; + data[3] = (len & 0xFF) as u8; + if let Err(e) = tcp_w.write_all(&data).await { + if context.is_close() { + break; + } + log::info!("发送失败,需要重连:{:?}",e); + let _ = tcp_w.shutdown().await; + match TcpStream::connect(context.inner.current_device.load().connect_server).await { + Ok(tcp_stream) => { + let (r, w) = tcp_stream.into_split(); + tcp_w = w; + let context = context.clone(); + let handler = handler.clone(); + tokio::spawn(async move { + if let Err(e) = Self::tcp_handle(r, context, handler, head_reserve).await { + log::info!("tcp 链接断开:{:?}",e); + } + }); + } + Err(e) => { + log::info!("重连失败:{:?}",e); + } + }; + } + }else{ + break; + } + } + } + } + worker.stop_all(); + } pub async fn start(self, - mut worker: SwitchWorker, + mut worker: VntWorker, + tcp: Option<(TcpStream, tokio::sync::mpsc::Receiver>)>, head_reserve: usize,//头部预留字节 symmetric_channel_num: usize,//对称网络,则再加一组监听,提升打洞成功率 + relay: bool, ) { let context = self.context; let main_channel = context.inner.main_channel.clone(); let handler = self.handler.clone(); + if let Some((tcp_stream, receiver)) = tcp { + tokio::spawn(Self::start_tcp(worker.worker("main_channel_tcp"), tcp_stream, receiver, context.clone(), handler.clone(), head_reserve)); + } tokio::spawn(Self::start_(worker.worker("main_channel_1"), context.clone(), handler.clone(), main_channel.clone(), head_reserve, true)); - tokio::spawn(Self::start_(worker.worker("main_channel_2"), context.clone(), handler, main_channel, head_reserve, true)); + // tokio::spawn(Self::start_(worker.worker("main_channel_2"), context.clone(), handler, main_channel, head_reserve, true)); + if relay { + worker.stop_wait().await; + return; + } let mut cur_status = Status::Cone; let mut status_receiver = context.inner.status_receiver.clone(); loop { @@ -352,7 +483,7 @@ impl Channel { } worker.stop_all(); } - async fn start_(mut worker: SwitchWorker, context: Context, + async fn start_(mut worker: VntWorker, context: Context, mut handler: ChannelDataHandler, udp: Arc, head_reserve: usize, @@ -361,17 +492,17 @@ impl Channel { #[cfg(target_os = "windows")] use std::os::windows::io::AsRawSocket; #[cfg(target_os = "windows")] - let id = udp.as_raw_socket() as usize; + let id = 1 + udp.as_raw_socket() as usize; #[cfg(any(unix))] use std::os::fd::AsRawFd; #[cfg(any(unix))] - let id = udp.as_raw_fd() as usize; + let id = 1 + udp.as_raw_fd() as usize; context.inner.udp_map.insert(id, udp.clone()); let mut buf = [0; 4096]; loop { tokio::select! { rs=udp.recv_from(&mut buf[head_reserve..])=>{ - Self::handle(&mut handler,&udp,&context,id,rs,&mut buf,head_reserve).await; + Self::handle(&mut handler,&context,id,rs,&mut buf,head_reserve).await; } changed=status_receiver.changed()=>{ match changed { diff --git a/switch/src/channel/idle.rs b/vnt/src/channel/idle.rs similarity index 83% rename from switch/src/channel/idle.rs rename to vnt/src/channel/idle.rs index 80010ea..06c95b7 100644 --- a/switch/src/channel/idle.rs +++ b/vnt/src/channel/idle.rs @@ -25,7 +25,7 @@ impl Idle { /// 获取空闲路由 pub async fn next_idle(&self) -> io::Result<(Ipv4Addr, RouteKey)> { loop { - let mut max = Duration::from_secs(10); + let mut max = Duration::from_secs(0); for entry in self.context.inner.route_table_time.iter() { let last_read = entry.value().load().elapsed(); if last_read >= self.read_idle { @@ -36,8 +36,10 @@ impl Idle { } } } - let sleep_time = self.read_idle - max; - tokio::time::sleep(sleep_time).await; + if self.read_idle > max { + let sleep_time = self.read_idle - max; + tokio::time::sleep(sleep_time).await; + } if self.context.is_close() { return Err(Error::new(ErrorKind::Other, "closed")); } diff --git a/switch/src/channel/mod.rs b/vnt/src/channel/mod.rs similarity index 100% rename from switch/src/channel/mod.rs rename to vnt/src/channel/mod.rs diff --git a/switch/src/channel/punch.rs b/vnt/src/channel/punch.rs similarity index 100% rename from switch/src/channel/punch.rs rename to vnt/src/channel/punch.rs diff --git a/switch/src/channel/sender.rs b/vnt/src/channel/sender.rs similarity index 100% rename from switch/src/channel/sender.rs rename to vnt/src/channel/sender.rs diff --git a/vnt/src/cipher/mod.rs b/vnt/src/cipher/mod.rs new file mode 100644 index 0000000..f3d9f7d --- /dev/null +++ b/vnt/src/cipher/mod.rs @@ -0,0 +1,115 @@ +use std::io; + +use aes_gcm::{AeadInPlace, Aes128Gcm, Aes256Gcm, Key, Nonce, Tag,KeyInit}; +use aes_gcm::aead::consts::{U12, U16}; +use aes_gcm::aead::generic_array::GenericArray; +use sha2::Digest; + +use crate::protocol; +use crate::protocol::{ip_turn_packet, NetPacket}; + +#[derive(Clone)] +pub enum Cipher { + AesGCM128(Aes128Gcm), + AesGCM256(Aes256Gcm), + None, +} + +impl Cipher { + pub fn new(password: Option) -> Self { + if let Some(password) = password { + let mut hasher = sha2::Sha256::new(); + hasher.update(password.as_bytes()); + let key: [u8; 32] = hasher.finalize().into(); + if password.len() < 8 { + let key: &Key = key[..16].into(); + Cipher::AesGCM128(Aes128Gcm::new(&key)) + } else { + let key: &Key = &key.into(); + Cipher::AesGCM256(Aes256Gcm::new(&key)) + } + } else { + Cipher::None + } + } + pub fn decrypt_ipv4(&self, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { + match &self { + Cipher::None => { + return Ok(None); + } + _ => {} + } + if !net_packet.is_encrypt() { + //未加密的数据直接丢弃 + return Err(io::Error::new(io::ErrorKind::Other, "not encrypt")); + } + if net_packet.payload().len() < 16 { + log::error!("数据异常,长度小于16"); + return Err(io::Error::new(io::ErrorKind::Other, "data err")); + } + let mut nonce = [0; 12]; + nonce[0..4].copy_from_slice(&net_packet.source().octets()); + nonce[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce[8] = protocol::Protocol::IpTurn.into(); + nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); + let nonce: &GenericArray = Nonce::from_slice(&nonce); + let payload_len = net_packet.payload().len() - 16; + let tag: GenericArray = Tag::clone_from_slice(&net_packet.payload()[payload_len..]); + let rs = match &self { + Cipher::AesGCM128(cipher) => { + cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag) + } + Cipher::AesGCM256(cipher) => { + cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len], &tag) + } + Cipher::None => { + return Ok(None); + } + }; + if let Err(e) = rs { + return Err(io::Error::new(io::ErrorKind::Other, format!("解密失败:{}", e))); + } + return Ok(Some(payload_len)); + } + /// net_packet 必须预留足够长度 + /// data_len是有效载荷的长度 + /// 返回加密后载荷的长度 + pub fn encrypt_ipv4(&self, payload_len: usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result> { + match &self { + Cipher::None => { + return Ok(None); + } + _ => {} + } + let mut nonce = [0; 12]; + nonce[0..4].copy_from_slice(&net_packet.source().octets()); + nonce[4..8].copy_from_slice(&net_packet.destination().octets()); + nonce[8] = protocol::Protocol::IpTurn.into(); + nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); + let nonce: &GenericArray = Nonce::from_slice(&nonce); + let rs = match &self { + Cipher::AesGCM128(cipher) => { + cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len]) + } + Cipher::AesGCM256(cipher) => { + cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..payload_len]) + } + Cipher::None => { + return Ok(None); + } + }; + return match rs { + Ok(tag) => { + if tag.len() != 16 { + return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len()))); + } + net_packet.set_encrypt_flag(true); + net_packet.payload_mut()[payload_len..payload_len + 16].copy_from_slice(tag.as_slice()); + Ok(Some(payload_len + 16)) + } + Err(e) => { + Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e))) + } + }; + } +} \ No newline at end of file diff --git a/switch/src/core/mod.rs b/vnt/src/core/mod.rs similarity index 79% rename from switch/src/core/mod.rs rename to vnt/src/core/mod.rs index 6063ba3..ecaeef0 100644 --- a/switch/src/core/mod.rs +++ b/vnt/src/core/mod.rs @@ -3,12 +3,10 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::sync::Arc; use std::time::Duration; -use aes_gcm::{Aes256Gcm, Key, KeyInit}; use crossbeam_skiplist::SkipMap; use crossbeam_utils::atomic::AtomicCell; use parking_lot::Mutex; -use sha2::Digest; -use tokio::net::UdpSocket; +use tokio::net::{TcpStream, UdpSocket}; use tokio::sync::mpsc::channel; use crate::channel::{Route, RouteKey}; @@ -16,7 +14,8 @@ use crate::channel::channel::{Channel, Context}; use crate::channel::idle::Idle; use crate::channel::punch::{NatInfo, Punch}; use crate::channel::sender::ChannelSender; -use crate::core::status::SwitchStatusManger; +use crate::cipher::Cipher; +use crate::core::status::VntStatusManger; use crate::error::Error; use crate::external_route::ExternalRoute; use crate::handle::{ConnectStatus, CurrentDeviceInfo, heartbeat_handler, PeerDeviceInfo, punch_handler, registration_handler}; @@ -35,11 +34,11 @@ pub mod sync; #[derive(Clone)] -pub struct Switch { +pub struct Vnt { name: String, current_device: Arc>, context: Context, - switch_status_manager: SwitchStatusManger, + vnt_status_manager: VntStatusManger, device_writer: DeviceWriter, /// 0. 机器纪元,每一次上线或者下线都会增1,用于感知网络中机器变化 /// 服务端和客户端的不一致,则服务端会推送新的设备列表 @@ -50,27 +49,34 @@ pub struct Switch { peer_nat_info_map: Arc>, } -pub struct SwitchUtil { +pub struct VntUtil { config: Config, - main_channel: Arc, + main_channel: UdpSocket, + main_tcp_channel: Option, response: Option, iface: Option<(DeviceWriter, DeviceReader)>, } -impl SwitchUtil { - pub async fn new(config: Config) -> io::Result { - let main_channel = Arc::new(UdpSocket::bind("0.0.0.0:0").await?); - Ok(SwitchUtil { +impl VntUtil { + pub async fn new(config: Config) -> io::Result { + let main_channel = UdpSocket::bind("0.0.0.0:0").await?; + let main_tcp_channel = if config.tcp { + Some(TcpStream::connect(config.server_address).await?) + } else { + None + }; + Ok(VntUtil { config, main_channel, + main_tcp_channel, response: None, iface: None, }) } pub async fn connect(&mut self) -> Result { - match registration_handler::registration(&self.main_channel, self.config.server_address, + match registration_handler::registration(&self.main_channel, self.main_tcp_channel.as_mut(), self.config.server_address, self.config.token.clone(), self.config.device_id.clone(), - self.config.name.clone()).await { + self.config.name.clone(), self.config.ip.unwrap_or(Ipv4Addr::UNSPECIFIED)).await { Ok(res) => { let _ = self.response.insert(res.clone()); Ok(res) @@ -101,14 +107,14 @@ impl SwitchUtil { let device_type = if self.config.tap { #[cfg(windows)] { - //删除switch的tun网卡避免ip冲突,因为非正常退出会保留网卡 + //删除tun网卡避免ip冲突,因为非正常退出会保留网卡 tun_tap_device::delete_device(tun_tap_device::DeviceType::Tun); } tun_tap_device::DeviceType::Tap } else { #[cfg(windows)] { - //删除switch的tap网卡避免ip冲突,非正常退出会保留网卡 + //删除tap网卡避免ip冲突,非正常退出会保留网卡 tun_tap_device::delete_device(tun_tap_device::DeviceType::Tap); } tun_tap_device::DeviceType::Tun @@ -121,7 +127,7 @@ impl SwitchUtil { let _ = self.iface.insert((device_writer, device_reader)); Ok(driver_info) } - pub async fn build(self) -> crate::Result { + pub async fn build(self) -> crate::Result { let response = match self.response { None => { return Err(Error::Stop("response None".to_string())); @@ -139,16 +145,22 @@ impl SwitchUtil { } }; let config = self.config; - let switch_status_manager = SwitchStatusManger::new(); - let cipher = if let Some(key) = &config.key { - let key: &Key = key.into(); - Some(Aes256Gcm::new(&key)) - } else { - None - }; + let vnt_status_manager = VntStatusManger::new(); + let cipher = Cipher::new(config.password.clone()); + let virtual_ip = response.virtual_ip; + let virtual_gateway = response.virtual_gateway; + let virtual_netmask = response.virtual_netmask; + let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, config.server_address))); + let (cone_sender, cone_receiver) = channel(3); let (symmetric_sender, symmetric_receiver) = channel(2); - let context = Context::new(self.main_channel, 1); + let (tcp_sender, tcp) = if let Some(main_tcp_channel) = self.main_tcp_channel { + let (tcp_sender, tcp_receiver) = channel::>(100); + (Some(tcp_sender), Some((main_tcp_channel, tcp_receiver))) + } else { + (None, None) + }; + let context = Context::new(Arc::new(self.main_channel), tcp_sender, current_device.clone(), 1); let punch = Punch::new(context.clone()); let idle = Idle::new(Duration::from_secs(16), context.clone()); let channel_sender = ChannelSender::new(context.clone()); @@ -159,9 +171,7 @@ impl SwitchUtil { let device_list: Arc)>> = Arc::new(Mutex::new((response.epoch, response.device_info_list))); let peer_nat_info_map: Arc> = Arc::new(SkipMap::new()); let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected)); - let virtual_ip = response.virtual_ip; - let virtual_gateway = response.virtual_gateway; - let virtual_netmask = response.virtual_netmask; + let local_ip = crate::nat::local_ip()?; let local_port = context.main_local_port()?; @@ -175,7 +185,6 @@ impl SwitchUtil { } else { Some(ExternalRoute::new(config.in_ips)) }; - let current_device = Arc::new(AtomicCell::new(CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, config.server_address))); let (tcp_proxy, udp_proxy, ip_proxy_map) = if out_ips.is_empty() { (None, None, None) } else { @@ -190,14 +199,14 @@ impl SwitchUtil { }; #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] if config.tap { - tap_handler::start(switch_status_manager.worker("tap_handler"), channel_sender.clone(), device_reader, device_writer.clone(), + tap_handler::start(vnt_status_manager.worker("tap_handler"), channel_sender.clone(), device_reader, device_writer.clone(), igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone()); } else { - tun_handler::start(switch_status_manager.worker("tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(), + tun_handler::start(vnt_status_manager.worker("tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(), igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone()); } #[cfg(any(target_os = "android"))] - tun_handler::start(switch_status_manager.worker("android tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(), + tun_handler::start(vnt_status_manager.worker("android tun_handler"), channel_sender.clone(), device_reader, device_writer.clone(), igmp_server.clone(), current_device.clone(), in_external_route, ip_proxy_map.clone(), cipher.clone()); //外部数据接收处理 @@ -205,10 +214,11 @@ impl SwitchUtil { register.clone(), nat_test.clone(), igmp_server, device_writer.clone(), connect_status.clone(), peer_nat_info_map.clone(), ip_proxy_map, out_external_route, - cone_sender, symmetric_sender, cipher); + cone_sender, symmetric_sender, cipher, config.relay); { let channel = Channel::new(context.clone(), channel_recv_handler); - let channel_worker = switch_status_manager.worker("channel_worker"); + let channel_worker = vnt_status_manager.worker("channel_worker"); + let relay = config.relay; if let Some(tcp_proxy) = tcp_proxy { tokio::spawn(tcp_proxy.start()); } @@ -216,11 +226,11 @@ impl SwitchUtil { tokio::spawn(udp_proxy.start()); } tokio::spawn(async move { - channel.start(channel_worker, 14, 65).await + channel.start(channel_worker, tcp, 14, 65, relay).await }); } { - let other_worker = switch_status_manager.worker("punch_handler"); + let other_worker = vnt_status_manager.worker("punch_handler"); let nat_test = nat_test.clone(); let device_list = device_list.clone(); let current_device = current_device.clone(); @@ -228,18 +238,20 @@ impl SwitchUtil { heartbeat_handler::start_heartbeat(other_worker.worker("heartbeat"), channel_sender.clone(), device_list.clone(), current_device.clone(), config.server_address_str); // 空闲检查 heartbeat_handler::start_idle(other_worker.worker("idle"), idle, channel_sender.clone()); - // 打洞处理 - punch_handler::start(other_worker.worker("cone_receiver"), cone_receiver, punch.clone(), current_device.clone()); - punch_handler::start(other_worker.worker("symmetric_receiver"), symmetric_receiver, punch, current_device.clone()); - tokio::spawn(punch_handler::start_punch(other_worker, nat_test, - device_list, channel_sender, current_device)); + if !config.relay { + // 打洞处理 + punch_handler::start(other_worker.worker("cone_receiver"), cone_receiver, punch.clone(), current_device.clone()); + punch_handler::start(other_worker.worker("symmetric_receiver"), symmetric_receiver, punch, current_device.clone()); + tokio::spawn(punch_handler::start_punch(other_worker, nat_test, + device_list, channel_sender, current_device)); + } } context.switch(nat_test.nat_info().nat_type); - Ok(Switch { + Ok(Vnt { name: config.name, current_device, context, - switch_status_manager, + vnt_status_manager, device_writer, nat_test, device_list, @@ -249,7 +261,7 @@ impl SwitchUtil { } } -impl Switch { +impl Vnt { pub fn name(&self) -> &str { &self.name } @@ -282,7 +294,7 @@ impl Switch { } pub fn stop(&self) -> io::Result<()> { self.context.close(); - self.switch_status_manager.stop_all(); + self.vnt_status_manager.stop_all(); self.device_writer.close()?; let virtual_gateway = self.current_device.load().virtual_gateway; let _ = std::net::UdpSocket::bind("0.0.0.0:0")?.send_to(&[0], @@ -290,12 +302,12 @@ impl Switch { Ok(()) } pub async fn wait_stop(&mut self) { - self.switch_status_manager.wait().await; + self.vnt_status_manager.wait().await; let _ = self.stop(); } pub async fn wait_stop_ms(&mut self, ms: Duration) -> bool { tokio::select! { - _=self.switch_status_manager.wait()=>{ + _=self.vnt_status_manager.wait()=>{ let _ = self.stop(); return true; } @@ -306,7 +318,7 @@ impl Switch { } } -impl Drop for Switch { +impl Drop for Vnt { fn drop(&mut self) { let _ = self.stop(); } @@ -323,9 +335,12 @@ pub struct Config { pub nat_test_server: Vec, pub in_ips: Vec<(u32, u32, Ipv4Addr)>, pub out_ips: Vec<(u32, u32, Ipv4Addr)>, - pub key: Option<[u8; 32]>, + pub password: Option, pub simulate_multicast: bool, pub mtu: Option, + pub tcp: bool, + pub ip: Option, + pub relay: bool, } @@ -337,15 +352,9 @@ impl Config { server_address_str: String, nat_test_server: Vec, in_ips: Vec<(u32, u32, Ipv4Addr)>, out_ips: Vec<(u32, u32, Ipv4Addr)>, - password: Option, simulate_multicast: bool, mtu: Option, ) -> Self { - let key = if let Some(password) = password { - let mut hasher = sha2::Sha256::new(); - hasher.update(password.as_bytes()); - let key: [u8; 32] = hasher.finalize().into(); - Some(key) - } else { - None - }; + password: Option, simulate_multicast: bool, mtu: Option, tcp: bool, + ip: Option, + relay: bool, ) -> Self { Self { tap, token, @@ -356,9 +365,12 @@ impl Config { nat_test_server, in_ips, out_ips, - key, + password, simulate_multicast, mtu, + tcp, + ip, + relay, } } } \ No newline at end of file diff --git a/switch/src/core/status.rs b/vnt/src/core/status.rs similarity index 64% rename from switch/src/core/status.rs rename to vnt/src/core/status.rs index ff9c8fb..1e56df6 100644 --- a/switch/src/core/status.rs +++ b/vnt/src/core/status.rs @@ -4,22 +4,22 @@ use tokio::sync::watch::{Receiver, Sender}; use crate::util::wait::WaitGroup; #[derive(Copy, Clone, Eq, PartialEq)] -pub enum SwitchStatus { +pub enum VntStatus { Starting, Stopping, } -pub struct SwitchWorker { +pub struct VntWorker { _name: String, wg: WaitGroup, - status_s: Arc>, - status_r: Receiver, + status_s: Arc>, + status_r: Receiver, } -impl SwitchWorker { +impl VntWorker { pub fn worker(&self, name: &str) -> Self { self.wg.add(); - SwitchWorker { + VntWorker { _name: name.to_string(), wg: self.wg.clone(), status_s: self.status_s.clone(), @@ -28,24 +28,24 @@ impl SwitchWorker { } } -impl Drop for SwitchWorker { +impl Drop for VntWorker { fn drop(&mut self) { self.wg.done(); } } -impl SwitchWorker { +impl VntWorker { pub fn stop_all(&self) { - let _ = self.status_s.send(SwitchStatus::Stopping); + let _ = self.status_s.send(VntStatus::Stopping); } pub async fn stop_wait(&mut self) { loop { - if *self.status_r.borrow() == SwitchStatus::Stopping { + if *self.status_r.borrow() == VntStatus::Stopping { return; } match self.status_r.changed().await { Ok(_) => { - if *self.status_r.borrow() == SwitchStatus::Stopping { + if *self.status_r.borrow() == VntStatus::Stopping { return; } } @@ -56,15 +56,15 @@ impl SwitchWorker { } #[derive(Clone)] -pub struct SwitchStatusManger { +pub struct VntStatusManger { wg: WaitGroup, - status_s: Arc>, - status_r: Receiver, + status_s: Arc>, + status_r: Receiver, } -impl SwitchStatusManger { +impl VntStatusManger { pub fn new() -> Self { - let (status_s, status_r) = watch::channel(SwitchStatus::Starting); + let (status_s, status_r) = watch::channel(VntStatus::Starting); Self { wg: WaitGroup::new(), status_s: Arc::new(status_s), @@ -72,14 +72,14 @@ impl SwitchStatusManger { } } pub fn stop_all(&self) { - let _ = self.status_s.send(SwitchStatus::Stopping); + let _ = self.status_s.send(VntStatus::Stopping); } pub async fn wait(&mut self) { self.wg.wait().await } - pub fn worker(&self, name: &str) -> SwitchWorker { + pub fn worker(&self, name: &str) -> VntWorker { self.wg.add(); - SwitchWorker { + VntWorker { _name: name.to_string(), wg: self.wg.clone(), status_s: self.status_s.clone(), diff --git a/switch/src/core/sync.rs b/vnt/src/core/sync.rs similarity index 51% rename from switch/src/core/sync.rs rename to vnt/src/core/sync.rs index 7aa4f4d..8d9c65c 100644 --- a/switch/src/core/sync.rs +++ b/vnt/src/core/sync.rs @@ -2,68 +2,68 @@ use std::io; use std::ops::Deref; use std::time::Duration; use tokio::runtime::Runtime; -use crate::core::{Config, Switch, SwitchUtil}; +use crate::core::{Config, Vnt, VntUtil}; use crate::handle::registration_handler::{RegResponse, ReqEnum}; -pub struct SwitchUtilSync { - switch_util: SwitchUtil, +pub struct VntUtilSync { + vnt_util: VntUtil, runtime: Runtime, } -pub struct SwitchSync { - switch: Switch, +pub struct VntSync { + vnt: Vnt, runtime: Runtime, } -impl SwitchUtilSync { - pub fn new(config: Config) -> io::Result { +impl VntUtilSync { + pub fn new(config: Config) -> io::Result { let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap(); - let switch_util = runtime.block_on(SwitchUtil::new(config))?; - Ok(SwitchUtilSync { - switch_util, + let vnt_util = runtime.block_on(VntUtil::new(config))?; + Ok(VntUtilSync { + vnt_util, runtime, }) } pub fn connect(&mut self) -> Result { - self.runtime.block_on(self.switch_util.connect()) + self.runtime.block_on(self.vnt_util.connect()) } #[cfg(any(target_os = "android"))] pub fn create_iface(&mut self, vpn_fd: i32) { - self.switch_util.create_iface(vpn_fd) + self.vnt_util.create_iface(vpn_fd) } #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] pub fn create_iface(&mut self) -> io::Result { - self.switch_util.create_iface() + self.vnt_util.create_iface() } - pub fn build(self) -> crate::Result { + pub fn build(self) -> crate::Result { let runtime = self.runtime; - let switch = runtime.block_on(self.switch_util.build())?; + let vnt = runtime.block_on(self.vnt_util.build())?; { - let mut switch = switch.clone(); + let mut vnt = vnt.clone(); std::thread::spawn(move || { - runtime.block_on(switch.wait_stop()) + runtime.block_on(vnt.wait_stop()) }); } - Ok(SwitchSync { - switch, + Ok(VntSync { + vnt, runtime: tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(), }) } } -impl SwitchSync { +impl VntSync { pub fn wait_stop(&mut self) { - self.runtime.block_on(self.switch.wait_stop()) + self.runtime.block_on(self.vnt.wait_stop()) } pub fn wait_stop_ms(&mut self, ms: u64) -> bool { - self.runtime.block_on(self.switch.wait_stop_ms(Duration::from_millis(ms))) + self.runtime.block_on(self.vnt.wait_stop_ms(Duration::from_millis(ms))) } } -impl Deref for SwitchSync { - type Target = Switch; +impl Deref for VntSync { + type Target = Vnt; fn deref(&self) -> &Self::Target { - &self.switch + &self.vnt } } \ No newline at end of file diff --git a/switch/src/error/mod.rs b/vnt/src/error/mod.rs similarity index 100% rename from switch/src/error/mod.rs rename to vnt/src/error/mod.rs diff --git a/switch/src/external_route/mod.rs b/vnt/src/external_route/mod.rs similarity index 100% rename from switch/src/external_route/mod.rs rename to vnt/src/external_route/mod.rs diff --git a/switch/src/handle/heartbeat_handler.rs b/vnt/src/handle/heartbeat_handler.rs similarity index 97% rename from switch/src/handle/heartbeat_handler.rs rename to vnt/src/handle/heartbeat_handler.rs index eb7f793..0b98a2f 100644 --- a/switch/src/handle/heartbeat_handler.rs +++ b/vnt/src/handle/heartbeat_handler.rs @@ -9,14 +9,14 @@ use rand::prelude::SliceRandom; use crate::channel::idle::Idle; use crate::channel::Route; use crate::channel::sender::ChannelSender; -use crate::core::status::SwitchWorker; +use crate::core::status::VntWorker; use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo}; use crate::protocol::control_packet::PingPacket; use crate::protocol::{control_packet, NetPacket, Protocol, Version}; -pub fn start_idle(mut worker: SwitchWorker, idle: Idle, sender: ChannelSender) { +pub fn start_idle(mut worker: VntWorker, idle: Idle, sender: ChannelSender) { tokio::spawn(async move { tokio::select! { _=worker.stop_wait()=>{ @@ -45,7 +45,7 @@ async fn start_idle_(idle: Idle, sender: ChannelSender) -> io::Result<()> { } pub fn start_heartbeat( - mut worker: SwitchWorker, + mut worker: VntWorker, sender: ChannelSender, device_list: Arc)>>, current_device: Arc>, diff --git a/switch/src/handle/mod.rs b/vnt/src/handle/mod.rs similarity index 100% rename from switch/src/handle/mod.rs rename to vnt/src/handle/mod.rs diff --git a/switch/src/handle/punch_handler.rs b/vnt/src/handle/punch_handler.rs similarity index 95% rename from switch/src/handle/punch_handler.rs rename to vnt/src/handle/punch_handler.rs index c1b4b80..8d71bd6 100644 --- a/switch/src/handle/punch_handler.rs +++ b/vnt/src/handle/punch_handler.rs @@ -13,9 +13,9 @@ use std::io; use tokio::sync::mpsc::Receiver; use crate::channel::punch::{NatInfo, Punch}; use crate::channel::sender::ChannelSender; -use crate::core::status::SwitchWorker; +use crate::core::status::VntWorker; -pub fn start(mut worker: SwitchWorker, receiver: Receiver<(Ipv4Addr, NatInfo)>, punch: Punch, current_device: Arc>) { +pub fn start(mut worker: VntWorker, receiver: Receiver<(Ipv4Addr, NatInfo)>, punch: Punch, current_device: Arc>) { tokio::spawn(async move { tokio::select! { _=start0(receiver, punch, current_device)=>{} @@ -54,7 +54,7 @@ async fn start_( } pub async fn start_punch( - mut worker: SwitchWorker, + mut worker: VntWorker, nat_test: NatTest, device_list: Arc)>>, sender: ChannelSender, diff --git a/switch/src/handle/recv_handler.rs b/vnt/src/handle/recv_handler.rs similarity index 85% rename from switch/src/handle/recv_handler.rs rename to vnt/src/handle/recv_handler.rs index d497ea1..da4c0b4 100644 --- a/switch/src/handle/recv_handler.rs +++ b/vnt/src/handle/recv_handler.rs @@ -1,14 +1,10 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::sync::Arc; -use aes_gcm::{AeadInPlace, Aes256Gcm, Nonce, Tag}; -use aes_gcm::aead::consts::{U12, U16}; -use aes_gcm::aead::generic_array::GenericArray; use crossbeam_utils::atomic::AtomicCell; use crossbeam_skiplist::SkipMap; use parking_lot::Mutex; use protobuf::Message; -use tokio::net::UdpSocket; use tokio::sync::mpsc::Sender; use packet::icmp::{icmp, Kind}; @@ -18,6 +14,7 @@ use packet::ip::ipv4::packet::IpV4Packet; use crate::channel::channel::Context; use crate::channel::punch::{NatInfo, NatType}; use crate::channel::{Route, RouteKey}; +use crate::cipher::Cipher; use crate::error::Error; use crate::external_route::ExternalRoute; @@ -47,7 +44,8 @@ pub struct ChannelDataHandler { out_external_route: ExternalRoute, cone_sender: Sender<(Ipv4Addr, NatInfo)>, symmetric_sender: Sender<(Ipv4Addr, NatInfo)>, - cipher: Option, + cipher: Cipher, + relay: bool, } impl ChannelDataHandler { @@ -63,7 +61,8 @@ impl ChannelDataHandler { out_external_route: ExternalRoute, cone_sender: Sender<(Ipv4Addr, NatInfo)>, symmetric_sender: Sender<(Ipv4Addr, NatInfo)>, - cipher: Option, ) -> Self { + cipher: Cipher, + relay: bool, ) -> Self { Self { current_device, device_list, @@ -78,14 +77,14 @@ impl ChannelDataHandler { cone_sender, symmetric_sender, cipher, + relay, } } } impl ChannelDataHandler { - pub async fn handle(&mut self, buf: &mut [u8], start: usize, end: usize, route_key: RouteKey, _udp: &Arc, - context: &Context, ) { + pub async fn handle(&mut self, buf: &mut [u8], start: usize, end: usize, route_key: RouteKey, context: &Context) { assert_eq!(start, 14); match self.handle0(&mut buf[..end], &route_key, context).await { Ok(_) => {} @@ -104,7 +103,7 @@ impl ChannelDataHandler { let destination = net_packet.destination(); let not_broadcast = !destination.is_broadcast() && !destination.is_multicast() && destination != current_device.broadcast_address; if current_device.virtual_ip() != destination - && not_broadcast + && not_broadcast && !destination.is_unspecified() && self.connect_status.load() == ConnectStatus::Connected { if !check_dest(source, current_device.virtual_netmask, current_device.virtual_network) { log::warn!("转发数据,源地址错误:{:?},当前网络:{:?},route_key:{:?}",source,current_device.virtual_network,route_key); @@ -150,32 +149,8 @@ impl ChannelDataHandler { return Ok(()); } ip_turn_packet::Protocol::Ipv4 => { - let data = if let Some(cipher) = &self.cipher { - if !net_packet.is_encrypt() { - //未加密的数据之间丢弃 - return Ok(()); - } - if net_packet.payload().len() < 16 { - log::error!("数据异常,长度小于16"); - return Ok(()); - } - //需要解密 - let mut nonce = [0; 12]; - nonce[0..4].copy_from_slice(&source.octets()); - nonce[4..8].copy_from_slice(&destination.octets()); - nonce[8] = Protocol::IpTurn.into(); - nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); - let nonce: &GenericArray = Nonce::from_slice(&nonce); - let data_len = net_packet.payload().len() - 16; - let tag: GenericArray = Tag::clone_from_slice(&net_packet.payload()[data_len..]); - match cipher.decrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..data_len], &tag) { - Ok(_) => {} - Err(e) => { - log::error!("数据解密异常:{}",e); - return Ok(()); - } - } - &mut net_packet.payload_mut()[..data_len] + let data = if let Some(payload_len) = self.cipher.decrypt_ipv4(&mut net_packet)? { + &mut net_packet.payload_mut()[..payload_len] } else { net_packet.payload_mut() }; @@ -199,30 +174,8 @@ impl ChannelDataHandler { ipv4.update_checksum(); net_packet.set_source(destination); net_packet.set_destination(source); - if let Some(cipher) = &self.cipher { - //需要加密 - let mut nonce = [0; 12]; - nonce[0..4].copy_from_slice(&destination.octets()); - nonce[4..8].copy_from_slice(&source.octets()); - nonce[8] = Protocol::IpTurn.into(); - nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); - let nonce: &GenericArray = Nonce::from_slice(&nonce); - let data_len = net_packet.payload().len() - 16; - match cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..data_len]) { - Ok(tag) => { - if tag.len() != 16 { - log::error!("加密tag长度错误:{}",tag.len()); - return Ok(()); - } - net_packet.set_encrypt_flag(true); - net_packet.payload_mut()[data_len..data_len + 16].copy_from_slice(tag.as_slice()); - } - Err(e) => { - log::error!("加密失败:{}",e); - return Ok(()); - } - } - } + //不管加不加密,和接收到的数据长度都一致 + let _ = self.cipher.encrypt_ipv4(net_packet.payload().len() - 16, &mut net_packet)?; context.send_by_key(net_packet.buffer(), route_key).await?; return Ok(()); } @@ -311,10 +264,6 @@ impl ChannelDataHandler { Ok(()) } async fn service(&self, context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { - //todo 校验来源 - if route_key.addr != current_device.connect_server { - return Ok(()); - } match service_packet::Protocol::from(net_packet.transport_protocol()) { service_packet::Protocol::RegistrationRequest => {} service_packet::Protocol::RegistrationResponse => { @@ -378,10 +327,8 @@ impl ChannelDataHandler { } Ok(()) } - async fn error(&self, _context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { - if route_key.addr != current_device.connect_server { - return Ok(()); - } + async fn error(&self, _context: &Context, current_device: CurrentDeviceInfo, _source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, _route_key: &RouteKey) -> crate::Result<()> { + log::info!("current_device:{:?}",current_device); match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload())? { InErrorPacket::TokenError => { return Err(Error::Stop("Token error".to_string())); @@ -394,7 +341,7 @@ impl ChannelDataHandler { } self.connect_status.store(ConnectStatus::Connecting); - self.register.fast_register().await?; + self.register.fast_register(current_device.virtual_ip).await?; } InErrorPacket::AddressExhausted => { //地址用尽 @@ -403,6 +350,12 @@ impl ChannelDataHandler { InErrorPacket::OtherError(e) => { log::error!("OtherError {:?}", e.message()); } + InErrorPacket::IpAlreadyExists => { + log::error!("IpAlreadyExists"); + } + InErrorPacket::InvalidIp => { + log::error!("InvalidIp"); + } } Ok(()) } @@ -428,7 +381,7 @@ impl ChannelDataHandler { let rt = (current_time - pong_packet.time()) as i64; let route = Route::from(*route_key, metric, rt); context.add_route(source, route); - if route_key.addr == current_device.connect_server && source == current_device.virtual_gateway() { + if source == current_device.virtual_gateway() { let epoch = self.device_list.lock().0; if pong_packet.epoch() != epoch { let mut poll_device = NetPacket::new([0; 12])?; @@ -438,11 +391,14 @@ impl ChannelDataHandler { poll_device.first_set_ttl(MAX_TTL); poll_device.set_protocol(Protocol::Service); poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into()); - context.send_by_key(poll_device.buffer(), route_key).await?; + context.send_main(poll_device.buffer(), current_device.connect_server).await?; } } } ControlPacket::PunchRequest => { + if self.relay { + return Ok(()); + } //回应 net_packet.set_transport_protocol(control_packet::Protocol::PunchResponse.into()); net_packet.set_source(current_device.virtual_ip()); @@ -453,6 +409,9 @@ impl ChannelDataHandler { context.add_route_if_absent(source, route); } ControlPacket::PunchResponse => { + if self.relay { + return Ok(()); + } // log::info!("PunchResponse route_key:{:?}",route_key); let route = Route::from(*route_key, metric, 99); context.add_route_if_absent(source, route); @@ -461,6 +420,9 @@ impl ChannelDataHandler { Ok(()) } async fn other_turn(&self, context: &Context, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> { + if self.relay { + return Ok(()); + } match other_turn_packet::Protocol::from(net_packet.transport_protocol()) { other_turn_packet::Protocol::Punch => { let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?; diff --git a/vnt/src/handle/registration_handler.rs b/vnt/src/handle/registration_handler.rs new file mode 100644 index 0000000..36130fe --- /dev/null +++ b/vnt/src/handle/registration_handler.rs @@ -0,0 +1,244 @@ +use std::io; +use std::net::{Ipv4Addr, SocketAddr}; +use std::time::{Duration, Instant}; +use crossbeam_utils::atomic::AtomicCell; + +use protobuf::Message; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::{TcpStream, UdpSocket}; +use crate::channel::sender::ChannelSender; +use crate::handle::PeerDeviceInfo; + +use crate::proto::message::{RegistrationRequest, RegistrationResponse}; +use crate::protocol::error_packet::InErrorPacket; +use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL}; + +pub enum ReqEnum { + TokenError, + AddressExhausted, + IpAlreadyExists, + InvalidIp, + Timeout, + ServerError(String), + Other(String), +} + +#[derive(Clone, Debug)] +pub struct RegResponse { + pub virtual_ip: Ipv4Addr, + pub virtual_gateway: Ipv4Addr, + pub virtual_netmask: Ipv4Addr, + pub epoch: u16, + pub device_info_list: Vec, + pub public_ip: Ipv4Addr, + pub public_port: u16, +} + +///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致 +pub async fn registration( + main_channel: &UdpSocket, + main_tcp_channel: Option<&mut TcpStream>, + server_address: SocketAddr, + token: String, + device_id: String, + name: String, + ip: Ipv4Addr, +) -> Result { + let request_packet = + registration_request_packet(token.clone(), device_id.clone(), name.clone(), ip, false, false).unwrap(); + let buf = request_packet.buffer(); + let mut recv_buf = [0u8; 10240]; + let recv_buf = if let Some(main_tcp_channel) = main_tcp_channel { + let mut vec = vec![0; 4 + buf.len()]; + let len = buf.len(); + vec[2] = (len >> 8) as u8; + vec[3] = (len & 0xFF) as u8; + vec[4..].copy_from_slice(buf); + if let Err(e) = main_tcp_channel.write_all(&vec).await { + return Err(ReqEnum::Other(format!("send error:{}", e))); + } + if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[..4]).await { + return Err(ReqEnum::Other(format!("read error:{}", e))); + } + let len = 4 + (((recv_buf[2] as u16) << 8) | recv_buf[3] as u16) as usize; + if let Err(e) = main_tcp_channel.read_exact(&mut recv_buf[4..len]).await { + return Err(ReqEnum::Other(format!("read error:{}", e))); + } + &recv_buf[4..len] + } else { + if let Err(e) = main_channel.send_to(buf, server_address).await { + return Err(ReqEnum::Other(format!("send error:{}", e))); + } + match tokio::time::timeout(Duration::from_millis(300), main_channel.recv_from(&mut recv_buf)).await { + Ok(rs) => { + match rs { + Ok((len, addr)) => { + if server_address != addr { + return Err(ReqEnum::Other(format!("invalid data,from {}", addr))); + } + &recv_buf[..len] + } + Err(e) => { + return Err(ReqEnum::Other(format!("receiver error:{}", e))); + } + } + } + Err(_) => { + return Err(ReqEnum::Timeout); + } + } + }; + let net_packet = match NetPacket::new(recv_buf) { + Ok(net_packet) => { + net_packet + } + Err(e) => { + return Err(ReqEnum::ServerError(format!("{}", e))); + } + }; + match net_packet.protocol() { + Protocol::Service => { + match service_packet::Protocol::from(net_packet.transport_protocol()) { + service_packet::Protocol::RegistrationResponse => { + match RegistrationResponse::parse_from_bytes(net_packet.payload()) { + Ok(response) => { + let device_info_list: Vec = response + .device_info_list + .into_iter() + .map(|info| { + PeerDeviceInfo::new( + Ipv4Addr::from(info.virtual_ip), + info.name, + info.device_status as u8, + ) + }) + .collect(); + Ok(RegResponse { + virtual_ip: Ipv4Addr::from(response.virtual_ip), + virtual_gateway: Ipv4Addr::from(response.virtual_gateway), + virtual_netmask: Ipv4Addr::from(response.virtual_netmask), + epoch: response.epoch as u16, + device_info_list, + public_ip: Ipv4Addr::from(response.public_ip), + public_port: response.public_port as u16, + }) + } + Err(_) => { + Err(ReqEnum::ServerError("invalid data".to_string())) + } + } + } + _ => { + Err(ReqEnum::ServerError("invalid data".to_string())) + } + } + } + Protocol::Error => { + match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload()) { + Ok(e) => match e { + InErrorPacket::TokenError => Err(ReqEnum::TokenError), + InErrorPacket::Disconnect => { + Err(ReqEnum::ServerError("disconnect".to_string())) + } + InErrorPacket::AddressExhausted => { + Err(ReqEnum::AddressExhausted) + } + InErrorPacket::OtherError(e) => match e.message() { + Ok(str) => { + Err(ReqEnum::ServerError(str)) + } + Err(e) => Err(ReqEnum::Other(format!("{}", e))), + }, + InErrorPacket::IpAlreadyExists => { + Err(ReqEnum::IpAlreadyExists) + } + InErrorPacket::InvalidIp => { + Err(ReqEnum::InvalidIp) + } + }, + Err(e) => Err(ReqEnum::Other(format!("{}", e))), + } + } + _ => Err(ReqEnum::ServerError("invalid data".to_string())), + } +} + +fn registration_request_packet( + token: String, + device_id: String, + name: String, + ip: Ipv4Addr, + is_fast: bool, + allow_ip_change: bool, +) -> crate::Result>> { + let mut request = RegistrationRequest::new(); + request.token = token; + request.device_id = device_id; + request.name = name; + request.virtual_ip = ip.into(); + request.allow_ip_change = allow_ip_change; + request.is_fast = is_fast; + request.version = "1.1.1".to_string(); + let bytes = request.write_to_bytes()?; + let buf = vec![0u8; 12 + bytes.len()]; + let mut net_packet = NetPacket::new(buf)?; + net_packet.set_version(Version::V1); + net_packet.set_protocol(Protocol::Service); + net_packet.set_transport_protocol(service_packet::Protocol::RegistrationRequest.into()); + net_packet.first_set_ttl(MAX_TTL); + net_packet.set_payload(&bytes); + Ok(net_packet) +} + +pub struct Register { + sender: ChannelSender, + server_address: SocketAddr, + token: String, + device_id: String, + name: String, + time: AtomicCell, +} + +impl Register { + pub fn new( + sender: ChannelSender, + server_address: SocketAddr, + token: String, + device_id: String, + name: String, + ) -> Self { + Self { + sender, + server_address, + token, + device_id, + name, + time: AtomicCell::new(Instant::now()), + } + } + pub async fn fast_register(&self, ip: Ipv4Addr) -> io::Result<()> { + let last = self.time.load(); + if last.elapsed() < Duration::from_secs(2) + || self + .time + .compare_exchange(last, Instant::now()) + .is_err() + { + //短时间不重复注册 + return Ok(()); + } + log::info!("重新连接"); + let request_packet = registration_request_packet( + self.token.clone(), + self.device_id.clone(), + self.name.clone(), + ip, + false, + true, + ) + .unwrap(); + let buf = request_packet.buffer(); + self.sender.send_main(buf, self.server_address).await?; + Ok(()) + } +} diff --git a/switch/src/handle/tun_tap/mod.rs b/vnt/src/handle/tun_tap/mod.rs similarity index 84% rename from switch/src/handle/tun_tap/mod.rs rename to vnt/src/handle/tun_tap/mod.rs index 84402ef..b391197 100644 --- a/switch/src/handle/tun_tap/mod.rs +++ b/vnt/src/handle/tun_tap/mod.rs @@ -1,13 +1,10 @@ -use std::io; use std::net::{Ipv4Addr, SocketAddrV4}; -use aes_gcm::{AeadInPlace, Aes256Gcm, Nonce}; -use aes_gcm::aead::consts::U12; -use aes_gcm::aead::generic_array::GenericArray; use packet::ip::ipv4::packet::IpV4Packet; use packet::ip::ipv4::protocol::Protocol; use packet::tcp::tcp::TcpPacket; use packet::udp::udp::UdpPacket; use crate::channel::sender::ChannelSender; +use crate::cipher::Cipher; use crate::external_route::ExternalRoute; use crate::handle::{check_dest, CurrentDeviceInfo}; use crate::ip_proxy::IpProxyMap; @@ -18,7 +15,7 @@ use crate::protocol; use crate::protocol::ip_turn_packet::BroadcastPacketEnd; pub mod tun_handler; -#[cfg(any(target_os = "linux", target_os = "macos",target_os = "windows"))] +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] pub mod tap_handler; async fn broadcast(sender: &ChannelSender, net_packet: &mut NetPacket<&mut [u8]>, data_len: usize, current_device: &CurrentDeviceInfo) -> Result<()> { @@ -109,7 +106,7 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], mut data_len: usize,//数据总长度=ip长度+12 igmp_server: &Option, current_device: CurrentDeviceInfo, - ip_route: &Option, proxy_map: &Option, cipher: &Option) -> Result<()> { + ip_route: &Option, proxy_map: &Option, cipher: &Cipher) -> Result<()> { let ipv4_packet = IpV4Packet::new(&buf[12..data_len])?; let protocol = ipv4_packet.protocol(); let ip_head_len = ipv4_packet.header_len() as usize * 4; @@ -143,9 +140,8 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], } Protocol::Udp => { if let Some(igmp_server) = igmp_server { - if let Some(cipher) = cipher { - //需要加密 - encrypt(cipher, &mut data_len, &mut net_packet)?; + if let Some(len) = cipher.encrypt_ipv4(data_len - 12, &mut net_packet)? { + data_len = 12 + len; } multicast(igmp_server, dest_ip, sender, &mut net_packet, data_len, ¤t_device).await?; return Ok(()); @@ -163,9 +159,8 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], if dest_ip.is_broadcast() || current_device.broadcast_address == dest_ip { // 广播 发送到直连目标 if Protocol::Udp == protocol { - if let Some(cipher) = cipher { - //需要加密 - encrypt(cipher, &mut data_len, &mut net_packet)?; + if let Some(len) = cipher.encrypt_ipv4(data_len - 12, &mut net_packet)? { + data_len = 12 + len; } broadcast(sender, &mut net_packet, data_len, ¤t_device).await?; } @@ -224,9 +219,8 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], _ => {} } } - if let Some(cipher) = cipher { - //需要加密 - encrypt(cipher, &mut data_len, &mut net_packet)?; + if let Some(len) = cipher.encrypt_ipv4(data_len - 12, &mut net_packet)? { + data_len = 12 + len; } //优先发到直连到地址 @@ -235,26 +229,3 @@ pub async fn base_handle(sender: &ChannelSender, buf: &mut [u8], } return Ok(()); } - -fn encrypt(cipher: &Aes256Gcm, data_len: &mut usize, net_packet: &mut NetPacket<&mut [u8]>) -> io::Result<()> { - let mut nonce = [0; 12]; - nonce[0..4].copy_from_slice(&net_packet.source().octets()); - nonce[4..8].copy_from_slice(&net_packet.destination().octets()); - nonce[8] = protocol::Protocol::IpTurn.into(); - nonce[9] = ip_turn_packet::Protocol::Ipv4.into(); - let nonce: &GenericArray = Nonce::from_slice(&nonce); - return match cipher.encrypt_in_place_detached(nonce, &[], &mut net_packet.payload_mut()[..*data_len - 12]) { - Ok(tag) => { - if tag.len() != 16 { - return Err(io::Error::new(io::ErrorKind::Other, format!("加密tag长度错误:{}", tag.len()))); - } - net_packet.set_encrypt_flag(true); - net_packet.payload_mut()[*data_len - 12..*data_len - 12 + 16].copy_from_slice(tag.as_slice()); - *data_len += 16; - Ok(()) - } - Err(e) => { - Err(io::Error::new(io::ErrorKind::Other, format!("加密失败:{}", e))) - } - }; -} \ No newline at end of file diff --git a/switch/src/handle/tun_tap/tap_handler.rs b/vnt/src/handle/tun_tap/tap_handler.rs similarity index 95% rename from switch/src/handle/tun_tap/tap_handler.rs rename to vnt/src/handle/tun_tap/tap_handler.rs index 6137782..4ea5771 100644 --- a/switch/src/handle/tun_tap/tap_handler.rs +++ b/vnt/src/handle/tun_tap/tap_handler.rs @@ -1,7 +1,8 @@ -use std::sync::Arc; use std::{io, thread}; -use aes_gcm::Aes256Gcm; +use std::sync::Arc; + use crossbeam_utils::atomic::AtomicCell; + use packet::arp::arp::ArpPacket; use packet::ethernet; use packet::ethernet::packet::EthernetPacket; @@ -9,22 +10,24 @@ use packet::icmp::icmp::IcmpPacket; use packet::icmp::Kind; use packet::ip::ipv4; use packet::ip::ipv4::packet::IpV4Packet; + use crate::channel::sender::ChannelSender; -use crate::core::status::SwitchWorker; +use crate::cipher::Cipher; +use crate::core::status::VntWorker; use crate::external_route::ExternalRoute; use crate::handle::CurrentDeviceInfo; use crate::igmp_server::IgmpServer; use crate::ip_proxy::IpProxyMap; use crate::tun_tap_device::{DeviceReader, DeviceWriter}; -pub fn start(worker: SwitchWorker, sender: ChannelSender, +pub fn start(worker: VntWorker, sender: ChannelSender, device_reader: DeviceReader, device_writer: DeviceWriter, igmp_server: Option, current_device: Arc>, ip_route: Option, ip_proxy_map: Option, - cipher: Option) { + cipher: Cipher) { thread::Builder::new().name("tap_handler".into()).spawn(move || { tokio::runtime::Builder::new_current_thread() .enable_all().build().unwrap() @@ -46,7 +49,7 @@ async fn start_(sender: ChannelSender, current_device: Arc>, ip_route: Option, ip_proxy_map: Option, - cipher: Option) -> io::Result<()> { + cipher: Cipher) -> io::Result<()> { let mut buf = [0; 4096]; loop { //ip拆包了会直接丢弃? @@ -58,7 +61,7 @@ async fn start_(sender: ChannelSender, } async fn handle(buf: &mut [u8], len: usize, igmp_server: &Option, current_device: &AtomicCell, - device_writer: &DeviceWriter, sender: &ChannelSender, ip_route: &Option, proxy_map: &Option, cipher: &Option) -> crate::Result<()> { + device_writer: &DeviceWriter, sender: &ChannelSender, ip_route: &Option, proxy_map: &Option, cipher: &Cipher) -> crate::Result<()> { let mut ethernet_packet = EthernetPacket::new(&mut buf[..len])?; let current_device = current_device.load(); match ethernet_packet.protocol() { diff --git a/switch/src/handle/tun_tap/tun_handler.rs b/vnt/src/handle/tun_tap/tun_handler.rs similarity index 92% rename from switch/src/handle/tun_tap/tun_handler.rs rename to vnt/src/handle/tun_tap/tun_handler.rs index fa50c4f..895e2ae 100644 --- a/switch/src/handle/tun_tap/tun_handler.rs +++ b/vnt/src/handle/tun_tap/tun_handler.rs @@ -1,6 +1,5 @@ use std::{io, thread}; use std::sync::Arc; -use aes_gcm::Aes256Gcm; use crossbeam_utils::atomic::AtomicCell; @@ -9,7 +8,8 @@ use packet::icmp::icmp::IcmpPacket; use packet::ip::ipv4; use packet::ip::ipv4::packet::IpV4Packet; use crate::channel::sender::ChannelSender; -use crate::core::status::SwitchWorker; +use crate::cipher::Cipher; +use crate::core::status::VntWorker; use crate::error::*; use crate::external_route::ExternalRoute; @@ -37,7 +37,7 @@ fn icmp(device_writer: &DeviceWriter, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> /// 接收tun数据,并且转发到udp上 #[inline] async fn handle(sender: &ChannelSender, data: &mut [u8], len: usize, device_writer: &DeviceWriter, igmp_server: &Option, current_device: CurrentDeviceInfo, - ip_route: &Option, proxy_map: &Option, cipher: &Option) -> Result<()> { + ip_route: &Option, proxy_map: &Option, cipher: &Cipher) -> Result<()> { let ipv4_packet = if let Ok(ipv4_packet) = IpV4Packet::new(&mut data[12..len]) { ipv4_packet } else { @@ -54,14 +54,14 @@ async fn handle(sender: &ChannelSender, data: &mut [u8], len: usize, device_writ return crate::handle::tun_tap::base_handle(sender, data, len, igmp_server, current_device, ip_route, proxy_map, cipher).await; } -pub fn start(worker: SwitchWorker, sender: ChannelSender, +pub fn start(worker: VntWorker, sender: ChannelSender, device_reader: DeviceReader, device_writer: DeviceWriter, igmp_server: Option, current_device: Arc>, ip_route: Option, ip_proxy_map: Option, - cipher: Option) { + cipher: Cipher) { thread::Builder::new().name("tun_handler".into()).spawn(move || { tokio::runtime::Builder::new_current_thread() .enable_all().build().unwrap() @@ -82,7 +82,7 @@ async fn start_(sender: ChannelSender, current_device: Arc>, ip_route: Option, ip_proxy_map: Option, - cipher: Option) -> io::Result<()> { + cipher: Cipher) -> io::Result<()> { let mut buf = [0; 4096]; loop { if sender.is_close() { diff --git a/switch/src/igmp_server/mod.rs b/vnt/src/igmp_server/mod.rs similarity index 100% rename from switch/src/igmp_server/mod.rs rename to vnt/src/igmp_server/mod.rs diff --git a/switch/src/ip_proxy/icmp_proxy.rs b/vnt/src/ip_proxy/icmp_proxy.rs similarity index 89% rename from switch/src/ip_proxy/icmp_proxy.rs rename to vnt/src/ip_proxy/icmp_proxy.rs index c5c5e8b..df36c74 100644 --- a/switch/src/ip_proxy/icmp_proxy.rs +++ b/vnt/src/ip_proxy/icmp_proxy.rs @@ -57,7 +57,7 @@ impl IcmpProxy { current_device, }) } - pub fn icmp_socket(&self) ->Arc{ + pub fn icmp_socket(&self) -> Arc { self.icmp_socket.clone() } pub fn start(self) { @@ -85,12 +85,16 @@ impl IcmpProxy { let dest_ip = *entry.value(); ipv4_packet.set_destination_ip(dest_ip); ipv4_packet.update_checksum(); - let virtual_ip = self.current_device.load().virtual_ip(); + let current_device = self.current_device.load(); + let virtual_ip = current_device.virtual_ip(); + let connect_server = current_device.connect_server; net_packet.set_source(virtual_ip); net_packet.set_destination(dest_ip); let data_len = ipv4_packet.buffer.len(); net_packet.set_payload(ipv4_packet.buffer); - let _ = self.sender.try_send_by_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip); + if self.sender.try_send_by_id(&net_packet.buffer()[..(12 + data_len)], &dest_ip).is_err() { + let _ = self.sender.try_send_main(&net_packet.buffer()[..(12 + data_len)], connect_server); + } } } _ => { diff --git a/switch/src/ip_proxy/mod.rs b/vnt/src/ip_proxy/mod.rs similarity index 100% rename from switch/src/ip_proxy/mod.rs rename to vnt/src/ip_proxy/mod.rs diff --git a/switch/src/ip_proxy/tcp_proxy.rs b/vnt/src/ip_proxy/tcp_proxy.rs similarity index 100% rename from switch/src/ip_proxy/tcp_proxy.rs rename to vnt/src/ip_proxy/tcp_proxy.rs diff --git a/switch/src/ip_proxy/udp_proxy.rs b/vnt/src/ip_proxy/udp_proxy.rs similarity index 100% rename from switch/src/ip_proxy/udp_proxy.rs rename to vnt/src/ip_proxy/udp_proxy.rs diff --git a/switch/src/lib.rs b/vnt/src/lib.rs similarity index 94% rename from switch/src/lib.rs rename to vnt/src/lib.rs index b4a1401..5365075 100644 --- a/switch/src/lib.rs +++ b/vnt/src/lib.rs @@ -14,3 +14,4 @@ pub mod tun_tap_device; pub mod core; pub mod channel; pub mod util; +pub mod cipher; diff --git a/switch/src/nat/check.rs b/vnt/src/nat/check.rs similarity index 100% rename from switch/src/nat/check.rs rename to vnt/src/nat/check.rs diff --git a/switch/src/nat/mod.rs b/vnt/src/nat/mod.rs similarity index 100% rename from switch/src/nat/mod.rs rename to vnt/src/nat/mod.rs diff --git a/switch/src/proto/message.rs b/vnt/src/proto/message.rs similarity index 88% rename from switch/src/proto/message.rs rename to vnt/src/proto/message.rs index d082655..2827aaf 100644 --- a/switch/src/proto/message.rs +++ b/vnt/src/proto/message.rs @@ -39,6 +39,10 @@ pub struct RegistrationRequest { pub is_fast: bool, // @@protoc_insertion_point(field:RegistrationRequest.version) pub version: ::std::string::String, + // @@protoc_insertion_point(field:RegistrationRequest.virtual_ip) + pub virtual_ip: u32, + // @@protoc_insertion_point(field:RegistrationRequest.allow_ip_change) + pub allow_ip_change: bool, // special fields // @@protoc_insertion_point(special_field:RegistrationRequest.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -56,7 +60,7 @@ impl RegistrationRequest { } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(5); + let mut fields = ::std::vec::Vec::with_capacity(7); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( "token", @@ -83,6 +87,16 @@ impl RegistrationRequest { |m: &RegistrationRequest| { &m.version }, |m: &mut RegistrationRequest| { &mut m.version }, )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "virtual_ip", + |m: &RegistrationRequest| { &m.virtual_ip }, + |m: &mut RegistrationRequest| { &mut m.virtual_ip }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "allow_ip_change", + |m: &RegistrationRequest| { &m.allow_ip_change }, + |m: &mut RegistrationRequest| { &mut m.allow_ip_change }, + )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "RegistrationRequest", fields, @@ -116,6 +130,12 @@ impl ::protobuf::Message for RegistrationRequest { 42 => { self.version = is.read_string()?; }, + 53 => { + self.virtual_ip = is.read_fixed32()?; + }, + 56 => { + self.allow_ip_change = is.read_bool()?; + }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; }, @@ -143,6 +163,12 @@ impl ::protobuf::Message for RegistrationRequest { if !self.version.is_empty() { my_size += ::protobuf::rt::string_size(5, &self.version); } + if self.virtual_ip != 0 { + my_size += 1 + 4; + } + if self.allow_ip_change != 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 @@ -164,6 +190,12 @@ impl ::protobuf::Message for RegistrationRequest { if !self.version.is_empty() { os.write_string(5, &self.version)?; } + if self.virtual_ip != 0 { + os.write_fixed32(6, self.virtual_ip)?; + } + if self.allow_ip_change != false { + os.write_bool(7, self.allow_ip_change)?; + } os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) } @@ -186,6 +218,8 @@ impl ::protobuf::Message for RegistrationRequest { self.name.clear(); self.is_fast = false; self.version.clear(); + self.virtual_ip = 0; + self.allow_ip_change = false; self.special_fields.clear(); } @@ -196,6 +230,8 @@ impl ::protobuf::Message for RegistrationRequest { name: ::std::string::String::new(), is_fast: false, version: ::std::string::String::new(), + virtual_ip: 0, + allow_ip_change: false, special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -237,6 +273,8 @@ pub struct RegistrationResponse { pub public_ip: u32, // @@protoc_insertion_point(field:RegistrationResponse.public_port) pub public_port: u32, + // @@protoc_insertion_point(field:RegistrationResponse.public_ipv6) + pub public_ipv6: ::std::vec::Vec, // special fields // @@protoc_insertion_point(special_field:RegistrationResponse.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -254,7 +292,7 @@ impl RegistrationResponse { } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(7); + let mut fields = ::std::vec::Vec::with_capacity(8); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( "virtual_ip", @@ -291,6 +329,11 @@ impl RegistrationResponse { |m: &RegistrationResponse| { &m.public_port }, |m: &mut RegistrationResponse| { &mut m.public_port }, )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "public_ipv6", + |m: &RegistrationResponse| { &m.public_ipv6 }, + |m: &mut RegistrationResponse| { &mut m.public_ipv6 }, + )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "RegistrationResponse", fields, @@ -330,6 +373,9 @@ impl ::protobuf::Message for RegistrationResponse { 56 => { self.public_port = is.read_uint32()?; }, + 66 => { + self.public_ipv6 = is.read_bytes()?; + }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; }, @@ -364,6 +410,9 @@ impl ::protobuf::Message for RegistrationResponse { if self.public_port != 0 { my_size += ::protobuf::rt::uint32_size(7, self.public_port); } + if !self.public_ipv6.is_empty() { + my_size += ::protobuf::rt::bytes_size(8, &self.public_ipv6); + } my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); self.special_fields.cached_size().set(my_size as u32); my_size @@ -391,6 +440,9 @@ impl ::protobuf::Message for RegistrationResponse { if self.public_port != 0 { os.write_uint32(7, self.public_port)?; } + if !self.public_ipv6.is_empty() { + os.write_bytes(8, &self.public_ipv6)?; + } os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) } @@ -415,6 +467,7 @@ impl ::protobuf::Message for RegistrationResponse { self.device_info_list.clear(); self.public_ip = 0; self.public_port = 0; + self.public_ipv6.clear(); self.special_fields.clear(); } @@ -427,6 +480,7 @@ impl ::protobuf::Message for RegistrationResponse { device_info_list: ::std::vec::Vec::new(), public_ip: 0, public_port: 0, + public_ipv6: ::std::vec::Vec::new(), special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -767,6 +821,8 @@ pub struct PunchInfo { pub local_ip: u32, // @@protoc_insertion_point(field:PunchInfo.local_port) pub local_port: u32, + // @@protoc_insertion_point(field:PunchInfo.public_ipv6_list) + pub public_ipv6_list: ::std::vec::Vec<::std::vec::Vec>, // special fields // @@protoc_insertion_point(special_field:PunchInfo.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -784,7 +840,7 @@ impl PunchInfo { } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(7); + let mut fields = ::std::vec::Vec::with_capacity(8); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>( "public_ip_list", @@ -821,6 +877,11 @@ impl PunchInfo { |m: &PunchInfo| { &m.local_port }, |m: &mut PunchInfo| { &mut m.local_port }, )); + fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>( + "public_ipv6_list", + |m: &PunchInfo| { &m.public_ipv6_list }, + |m: &mut PunchInfo| { &mut m.public_ipv6_list }, + )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "PunchInfo", fields, @@ -863,6 +924,9 @@ impl ::protobuf::Message for PunchInfo { 64 => { self.local_port = is.read_uint32()?; }, + 74 => { + self.public_ipv6_list.push(is.read_bytes()?); + }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; }, @@ -894,6 +958,9 @@ impl ::protobuf::Message for PunchInfo { if self.local_port != 0 { my_size += ::protobuf::rt::uint32_size(8, self.local_port); } + for value in &self.public_ipv6_list { + my_size += ::protobuf::rt::bytes_size(9, &value); + }; my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); self.special_fields.cached_size().set(my_size as u32); my_size @@ -921,6 +988,9 @@ impl ::protobuf::Message for PunchInfo { if self.local_port != 0 { os.write_uint32(8, self.local_port)?; } + for v in &self.public_ipv6_list { + os.write_bytes(9, &v)?; + }; os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) } @@ -945,6 +1015,7 @@ impl ::protobuf::Message for PunchInfo { self.reply = false; self.local_ip = 0; self.local_port = 0; + self.public_ipv6_list.clear(); self.special_fields.clear(); } @@ -957,6 +1028,7 @@ impl ::protobuf::Message for PunchInfo { reply: false, local_ip: 0, local_port: 0, + public_ipv6_list: ::std::vec::Vec::new(), special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -1035,29 +1107,33 @@ impl PunchNatType { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\rmessage.proto\"\x8f\x01\n\x13RegistrationRequest\x12\x14\n\x05token\ + \n\rmessage.proto\"\xd6\x01\n\x13RegistrationRequest\x12\x14\n\x05token\ \x18\x01\x20\x01(\tR\x05token\x12\x1b\n\tdevice_id\x18\x02\x20\x01(\tR\ \x08deviceId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x17\n\x07\ is_fast\x18\x04\x20\x01(\x08R\x06isFast\x12\x18\n\x07version\x18\x05\x20\ - \x01(\tR\x07version\"\x92\x02\n\x14RegistrationResponse\x12\x1d\n\nvirtu\ - al_ip\x18\x01\x20\x01(\x07R\tvirtualIp\x12'\n\x0fvirtual_gateway\x18\x02\ - \x20\x01(\x07R\x0evirtualGateway\x12'\n\x0fvirtual_netmask\x18\x03\x20\ - \x01(\x07R\x0evirtualNetmask\x12\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05e\ - poch\x125\n\x10device_info_list\x18\x05\x20\x03(\x0b2\x0b.DeviceInfoR\ - \x0edeviceInfoList\x12\x1b\n\tpublic_ip\x18\x06\x20\x01(\x07R\x08publicI\ - p\x12\x1f\n\x0bpublic_port\x18\x07\x20\x01(\rR\npublicPort\"d\n\nDeviceI\ - nfo\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\x12\x1d\n\nvirtual_ip\ - \x18\x02\x20\x01(\x07R\tvirtualIp\x12#\n\rdevice_status\x18\x03\x20\x01(\ - \rR\x0cdeviceStatus\"Y\n\nDeviceList\x12\x14\n\x05epoch\x18\x01\x20\x01(\ - \rR\x05epoch\x125\n\x10device_info_list\x18\x02\x20\x03(\x0b2\x0b.Device\ - InfoR\x0edeviceInfoList\"\xf8\x01\n\tPunchInfo\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\r.PunchNatT\ - ypeR\x07natType\x12\x14\n\x05reply\x18\x06\x20\x01(\x08R\x05reply\x12\ - \x19\n\x08local_ip\x18\x07\x20\x01(\x07R\x07localIp\x12\x1d\n\nlocal_por\ - t\x18\x08\x20\x01(\rR\tlocalPort*'\n\x0cPunchNatType\x12\r\n\tSymmetric\ - \x10\0\x12\x08\n\x04Cone\x10\x01b\x06proto3\ + \x01(\tR\x07version\x12\x1d\n\nvirtual_ip\x18\x06\x20\x01(\x07R\tvirtual\ + Ip\x12&\n\x0fallow_ip_change\x18\x07\x20\x01(\x08R\rallowIpChange\"\xb3\ + \x02\n\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\ + \x07R\tvirtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07R\x0evirt\ + ualGateway\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0evirtualNet\ + mask\x12\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x125\n\x10device_in\ + fo_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\npublicPort\x12\x1f\n\x0bpublic_ipv6\x18\x08\x20\ + \x01(\x0cR\npublicIpv6\"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_status\x18\x03\x20\x01(\rR\x0cdeviceStatus\"Y\n\nDeviceL\ + ist\x12\x14\n\x05epoch\x18\x01\x20\x01(\rR\x05epoch\x125\n\x10device_inf\ + o_list\x18\x02\x20\x03(\x0b2\x0b.DeviceInfoR\x0edeviceInfoList\"\xa2\x02\ + \n\tPunchInfo\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIp\ + List\x12\x1f\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11\ + public_port_range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12(\n\x08nat_t\ + ype\x18\x05\x20\x01(\x0e2\r.PunchNatTypeR\x07natType\x12\x14\n\x05reply\ + \x18\x06\x20\x01(\x08R\x05reply\x12\x19\n\x08local_ip\x18\x07\x20\x01(\ + \x07R\x07localIp\x12\x1d\n\nlocal_port\x18\x08\x20\x01(\rR\tlocalPort\ + \x12(\n\x10public_ipv6_list\x18\t\x20\x03(\x0cR\x0epublicIpv6List*'\n\ + \x0cPunchNatType\x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\x10\x01b\x06\ + proto3\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/switch/src/proto/mod.rs b/vnt/src/proto/mod.rs similarity index 100% rename from switch/src/proto/mod.rs rename to vnt/src/proto/mod.rs diff --git a/switch/src/protocol/control_packet.rs b/vnt/src/protocol/control_packet.rs similarity index 99% rename from switch/src/protocol/control_packet.rs rename to vnt/src/protocol/control_packet.rs index 4cc67ca..333e3f5 100644 --- a/switch/src/protocol/control_packet.rs +++ b/vnt/src/protocol/control_packet.rs @@ -43,7 +43,6 @@ impl Into for Protocol { } } } - pub enum ControlPacket { PingPacket(PingPacket), PongPacket(PongPacket), diff --git a/switch/src/protocol/error_packet.rs b/vnt/src/protocol/error_packet.rs similarity index 83% rename from switch/src/protocol/error_packet.rs rename to vnt/src/protocol/error_packet.rs index c6b8405..45be4bc 100644 --- a/switch/src/protocol/error_packet.rs +++ b/vnt/src/protocol/error_packet.rs @@ -5,6 +5,8 @@ pub enum Protocol { TokenError, Disconnect, AddressExhausted, + IpAlreadyExists, + InvalidIp, Other(u8), } @@ -14,6 +16,8 @@ impl From for Protocol { 1 => Self::TokenError, 2 => Self::Disconnect, 3 => Self::AddressExhausted, + 4 => Self::IpAlreadyExists, + 5 => Self::InvalidIp, val => Self::Other(val), } } @@ -25,6 +29,8 @@ impl Into for Protocol { Protocol::TokenError => 1, Protocol::Disconnect => 2, Protocol::AddressExhausted => 3, + Protocol::IpAlreadyExists => 4, + Protocol::InvalidIp => 5, Protocol::Other(val) => val, } } @@ -34,6 +40,8 @@ pub enum InErrorPacket { TokenError, Disconnect, AddressExhausted, + IpAlreadyExists, + InvalidIp, OtherError(ErrorPacket), } @@ -43,6 +51,8 @@ impl> InErrorPacket { Protocol::TokenError => Ok(InErrorPacket::TokenError), Protocol::Disconnect => Ok(InErrorPacket::Disconnect), Protocol::AddressExhausted => Ok(InErrorPacket::AddressExhausted), + Protocol::IpAlreadyExists => Ok(InErrorPacket::IpAlreadyExists), + Protocol::InvalidIp => Ok(InErrorPacket::InvalidIp), Protocol::Other(_) => Ok(InErrorPacket::OtherError(ErrorPacket::new(buffer)?)), } } diff --git a/switch/src/protocol/ip_turn_packet.rs b/vnt/src/protocol/ip_turn_packet.rs similarity index 100% rename from switch/src/protocol/ip_turn_packet.rs rename to vnt/src/protocol/ip_turn_packet.rs diff --git a/switch/src/protocol/mod.rs b/vnt/src/protocol/mod.rs similarity index 100% rename from switch/src/protocol/mod.rs rename to vnt/src/protocol/mod.rs diff --git a/switch/src/protocol/other_turn_packet.rs b/vnt/src/protocol/other_turn_packet.rs similarity index 100% rename from switch/src/protocol/other_turn_packet.rs rename to vnt/src/protocol/other_turn_packet.rs diff --git a/switch/src/protocol/service_packet.rs b/vnt/src/protocol/service_packet.rs similarity index 100% rename from switch/src/protocol/service_packet.rs rename to vnt/src/protocol/service_packet.rs diff --git a/switch/src/tun_tap_device/android.rs b/vnt/src/tun_tap_device/android.rs similarity index 100% rename from switch/src/tun_tap_device/android.rs rename to vnt/src/tun_tap_device/android.rs diff --git a/switch/src/tun_tap_device/linux.rs b/vnt/src/tun_tap_device/linux.rs similarity index 100% rename from switch/src/tun_tap_device/linux.rs rename to vnt/src/tun_tap_device/linux.rs diff --git a/switch/src/tun_tap_device/linux_mac.rs b/vnt/src/tun_tap_device/linux_mac.rs similarity index 100% rename from switch/src/tun_tap_device/linux_mac.rs rename to vnt/src/tun_tap_device/linux_mac.rs diff --git a/switch/src/tun_tap_device/mac.rs b/vnt/src/tun_tap_device/mac.rs similarity index 100% rename from switch/src/tun_tap_device/mac.rs rename to vnt/src/tun_tap_device/mac.rs diff --git a/switch/src/tun_tap_device/mod.rs b/vnt/src/tun_tap_device/mod.rs similarity index 100% rename from switch/src/tun_tap_device/mod.rs rename to vnt/src/tun_tap_device/mod.rs diff --git a/switch/src/tun_tap_device/windows.rs b/vnt/src/tun_tap_device/windows.rs similarity index 98% rename from switch/src/tun_tap_device/windows.rs rename to vnt/src/tun_tap_device/windows.rs index 3bcae56..2ef5f83 100644 --- a/switch/src/tun_tap_device/windows.rs +++ b/vnt/src/tun_tap_device/windows.rs @@ -10,9 +10,9 @@ use packet::ethernet::packet::EthernetPacket; use win_tun_tap::{IFace, TapDevice, TunDevice}; use crate::tun_tap_device::{DriverInfo, DeviceType}; -pub const TUN_INTERFACE_NAME: &str = "Switch-Tun-V1"; -pub const TUN_POOL_NAME: &str = "Switch-Tun-V1"; -pub const TAP_INTERFACE_NAME: &str = "Switch-Tap-V1"; +pub const TUN_INTERFACE_NAME: &str = "Vnt-Tun-V1"; +pub const TUN_POOL_NAME: &str = "Vnt-Tun-V1"; +pub const TAP_INTERFACE_NAME: &str = "Vnt-Tap-V1"; pub enum Device { Tun(TunDevice), diff --git a/switch/src/util/mod.rs b/vnt/src/util/mod.rs similarity index 100% rename from switch/src/util/mod.rs rename to vnt/src/util/mod.rs diff --git a/switch/src/util/wait.rs b/vnt/src/util/wait.rs similarity index 100% rename from switch/src/util/wait.rs rename to vnt/src/util/wait.rs diff --git a/switch/win-tun-tap/Cargo.toml b/vnt/win-tun-tap/Cargo.toml similarity index 100% rename from switch/win-tun-tap/Cargo.toml rename to vnt/win-tun-tap/Cargo.toml diff --git a/switch/win-tun-tap/src/ffi.rs b/vnt/win-tun-tap/src/ffi.rs similarity index 100% rename from switch/win-tun-tap/src/ffi.rs rename to vnt/win-tun-tap/src/ffi.rs diff --git a/switch/win-tun-tap/src/lib.rs b/vnt/win-tun-tap/src/lib.rs similarity index 100% rename from switch/win-tun-tap/src/lib.rs rename to vnt/win-tun-tap/src/lib.rs diff --git a/switch/win-tun-tap/src/netsh.rs b/vnt/win-tun-tap/src/netsh.rs similarity index 100% rename from switch/win-tun-tap/src/netsh.rs rename to vnt/win-tun-tap/src/netsh.rs diff --git a/switch/win-tun-tap/src/route.rs b/vnt/win-tun-tap/src/route.rs similarity index 100% rename from switch/win-tun-tap/src/route.rs rename to vnt/win-tun-tap/src/route.rs diff --git a/switch/win-tun-tap/src/tap/iface.rs b/vnt/win-tun-tap/src/tap/iface.rs similarity index 100% rename from switch/win-tun-tap/src/tap/iface.rs rename to vnt/win-tun-tap/src/tap/iface.rs diff --git a/switch/win-tun-tap/src/tap/mod.rs b/vnt/win-tun-tap/src/tap/mod.rs similarity index 100% rename from switch/win-tun-tap/src/tap/mod.rs rename to vnt/win-tun-tap/src/tap/mod.rs diff --git a/switch/win-tun-tap/src/tun/log.rs b/vnt/win-tun-tap/src/tun/log.rs similarity index 100% rename from switch/win-tun-tap/src/tun/log.rs rename to vnt/win-tun-tap/src/tun/log.rs diff --git a/switch/win-tun-tap/src/tun/mod.rs b/vnt/win-tun-tap/src/tun/mod.rs similarity index 100% rename from switch/win-tun-tap/src/tun/mod.rs rename to vnt/win-tun-tap/src/tun/mod.rs diff --git a/switch/win-tun-tap/src/tun/packet.rs b/vnt/win-tun-tap/src/tun/packet.rs similarity index 100% rename from switch/win-tun-tap/src/tun/packet.rs rename to vnt/win-tun-tap/src/tun/packet.rs diff --git a/switch/win-tun-tap/src/tun/wintun_raw.rs b/vnt/win-tun-tap/src/tun/wintun_raw.rs similarity index 100% rename from switch/win-tun-tap/src/tun/wintun_raw.rs rename to vnt/win-tun-tap/src/tun/wintun_raw.rs