diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9840a8b..f4cbfc0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ on: version: description: 'Version for this release' type: string - default: 'v1.2.3' + default: 'v2.0.0' required: true make_latest: description: 'Mark this release as latest' diff --git a/Cargo.lock b/Cargo.lock index 10b63ed..55c766c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1539,7 +1539,7 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "easytier" -version = "1.2.3" +version = "2.0.0" dependencies = [ "aes-gcm", "anyhow", @@ -1597,6 +1597,7 @@ dependencies = [ "rust-i18n", "rustls", "serde", + "serde_json", "serial_test", "smoltcp", "socket2", @@ -1630,7 +1631,7 @@ dependencies = [ [[package]] name = "easytier-gui" -version = "1.2.3" +version = "2.0.0" dependencies = [ "anyhow", "chrono", diff --git a/easytier-gui/package.json b/easytier-gui/package.json index a75f220..ba26c7d 100644 --- a/easytier-gui/package.json +++ b/easytier-gui/package.json @@ -1,7 +1,7 @@ { "name": "easytier-gui", "type": "module", - "version": "1.2.3", + "version": "2.0.0", "private": true, "scripts": { "dev": "vite", diff --git a/easytier-gui/src-tauri/Cargo.toml b/easytier-gui/src-tauri/Cargo.toml index 5c9ded7..39a2ba8 100644 --- a/easytier-gui/src-tauri/Cargo.toml +++ b/easytier-gui/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "easytier-gui" -version = "1.2.3" +version = "2.0.0" description = "EasyTier GUI" authors = ["you"] edition = "2021" diff --git a/easytier-gui/src-tauri/tauri.conf.json b/easytier-gui/src-tauri/tauri.conf.json index a6a7ac7..1fcc2be 100644 --- a/easytier-gui/src-tauri/tauri.conf.json +++ b/easytier-gui/src-tauri/tauri.conf.json @@ -17,7 +17,7 @@ "createUpdaterArtifacts": false }, "productName": "easytier-gui", - "version": "1.2.3", + "version": "2.0.0", "identifier": "com.kkrainbow.easytier", "plugins": {}, "app": { diff --git a/easytier/Cargo.toml b/easytier/Cargo.toml index 91c64fc..a949929 100644 --- a/easytier/Cargo.toml +++ b/easytier/Cargo.toml @@ -3,7 +3,7 @@ name = "easytier" description = "A full meshed p2p VPN, connecting all your devices in one network with one command." homepage = "https://github.com/EasyTier/EasyTier" repository = "https://github.com/EasyTier/EasyTier" -version = "1.2.3" +version = "2.0.0" edition = "2021" authors = ["kkrainbow"] keywords = ["vpn", "p2p", "network", "easytier"] @@ -125,6 +125,7 @@ rand = "0.8.5" serde = { version = "1.0", features = ["derive"] } pnet = { version = "0.35.0", features = ["serde"] } +serde_json = "1" clap = { version = "4.4.8", features = [ "string", diff --git a/easytier/src/common/config.rs b/easytier/src/common/config.rs index 78b3416..709c6ef 100644 --- a/easytier/src/common/config.rs +++ b/easytier/src/common/config.rs @@ -208,7 +208,10 @@ struct Config { socks5_proxy: Option, - flags: Option, + flags: Option>, + + #[serde(skip)] + flags_struct: Option, } #[derive(Debug, Clone)] @@ -224,13 +227,15 @@ impl Default for TomlConfigLoader { impl TomlConfigLoader { pub fn new_from_str(config_str: &str) -> Result { - let config = toml::de::from_str::(config_str).with_context(|| { + let mut config = toml::de::from_str::(config_str).with_context(|| { format!( "failed to parse config file: {}\n{}", config_str, config_str ) })?; + config.flags_struct = Some(Self::gen_flags(config.flags.clone().unwrap_or_default())); + Ok(TomlConfigLoader { config: Arc::new(Mutex::new(config)), }) @@ -248,6 +253,28 @@ impl TomlConfigLoader { Ok(ret) } + + fn gen_flags(mut flags_hashmap: serde_json::Map) -> Flags { + let default_flags_json = serde_json::to_string(&Flags::default()).unwrap(); + let default_flags_hashmap = + serde_json::from_str::>(&default_flags_json) + .unwrap(); + + tracing::debug!("default_flags_hashmap: {:?}", default_flags_hashmap); + + let mut merged_hashmap = serde_json::Map::new(); + for (key, value) in default_flags_hashmap { + if let Some(v) = flags_hashmap.remove(&key) { + merged_hashmap.insert(key, v); + } else { + merged_hashmap.insert(key, value); + } + } + + tracing::debug!("merged_hashmap: {:?}", merged_hashmap); + + serde_json::from_value(serde_json::Value::Object(merged_hashmap)).unwrap() + } } impl ConfigLoader for TomlConfigLoader { @@ -474,13 +501,13 @@ impl ConfigLoader for TomlConfigLoader { self.config .lock() .unwrap() - .flags + .flags_struct .clone() .unwrap_or_default() } fn set_flags(&self, flags: Flags) { - self.config.lock().unwrap().flags = Some(flags); + self.config.lock().unwrap().flags_struct = Some(flags); } fn get_exit_nodes(&self) -> Vec { diff --git a/easytier/src/peers/rpc_service.rs b/easytier/src/peers/rpc_service.rs index 5e47e14..34dfac0 100644 --- a/easytier/src/peers/rpc_service.rs +++ b/easytier/src/peers/rpc_service.rs @@ -23,7 +23,15 @@ impl PeerManagerRpcService { } pub async fn list_peers(&self) -> Vec { - let peers = self.peer_manager.get_peer_map().list_peers().await; + let mut peers = self.peer_manager.get_peer_map().list_peers().await; + peers.extend( + self.peer_manager + .get_foreign_network_client() + .get_peer_map() + .list_peers() + .await + .iter(), + ); let mut peer_infos = Vec::new(); for peer in peers { let mut peer_info = PeerInfo::default(); @@ -31,6 +39,14 @@ impl PeerManagerRpcService { if let Some(conns) = self.peer_manager.get_peer_map().list_peer_conns(peer).await { peer_info.conns = conns; + } else if let Some(conns) = self + .peer_manager + .get_foreign_network_client() + .get_peer_map() + .list_peer_conns(peer) + .await + { + peer_info.conns = conns; } peer_infos.push(peer_info); diff --git a/easytier/src/tunnel/websocket.rs b/easytier/src/tunnel/websocket.rs index 5d7c07a..8214c65 100644 --- a/easytier/src/tunnel/websocket.rs +++ b/easytier/src/tunnel/websocket.rs @@ -1,9 +1,12 @@ -use std::{net::SocketAddr, sync::Arc}; +use std::{net::SocketAddr, sync::Arc, time::Duration}; use anyhow::Context; use bytes::BytesMut; use futures::{stream::FuturesUnordered, SinkExt, StreamExt}; -use tokio::net::{TcpListener, TcpSocket, TcpStream}; +use tokio::{ + net::{TcpListener, TcpSocket, TcpStream}, + time::timeout, +}; use tokio_rustls::TlsAcceptor; use tokio_websockets::{ClientBuilder, Limits, MaybeTlsStream, Message}; use zerocopy::AsBytes; @@ -141,9 +144,9 @@ impl TunnelListener for WSTunnelListener { // only fail on tcp accept error let (stream, _) = listener.accept().await?; stream.set_nodelay(true).unwrap(); - match self.try_accept(stream).await { - Ok(tunnel) => return Ok(tunnel), - Err(e) => { + match timeout(Duration::from_secs(3), self.try_accept(stream)).await { + Ok(Ok(tunnel)) => return Ok(tunnel), + e => { tracing::error!(?e, ?self, "Failed to accept ws/wss tunnel"); continue; }