diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9327d3d..75082c65 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ concurrency: env: PACKAGE: "tuic-server" PACKAGE2: "tuic-client" - RUST_TOOLCHAIN: "nightly-2024-11-26" + RUST_TOOLCHAIN: "nightly-2024-12-20" jobs: compile: diff --git a/Cargo.lock b/Cargo.lock index 7be48034..288e6059 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2069,7 +2069,7 @@ dependencies = [ [[package]] name = "tuic" -version = "1.4.0" +version = "1.4.1" dependencies = [ "bytes", "futures-util", @@ -2082,7 +2082,7 @@ dependencies = [ [[package]] name = "tuic-client" -version = "1.4.0" +version = "1.4.1" dependencies = [ "anyhow", "bytes", @@ -2114,7 +2114,7 @@ dependencies = [ [[package]] name = "tuic-quinn" -version = "1.4.0" +version = "1.4.1" dependencies = [ "bytes", "eyre", @@ -2128,7 +2128,7 @@ dependencies = [ [[package]] name = "tuic-server" -version = "1.4.0" +version = "1.4.1" dependencies = [ "arc-swap", "axum", diff --git a/Cargo.toml b/Cargo.toml index 05a10215..7a8caae6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ resolver = "2" [workspace.package] authors = ["EAimTY ", "Itsusinn "] -version = "1.4.0" +version = "1.4.1" rust-version = "1.80.0" edition = "2021" readme = "README.md" diff --git a/tuic-server/src/connection/handle_task.rs b/tuic-server/src/connection/handle_task.rs index df541e32..850cde8c 100644 --- a/tuic-server/src/connection/handle_task.rs +++ b/tuic-server/src/connection/handle_task.rs @@ -32,7 +32,7 @@ impl Connection { let target_addr = conn.addr().to_string(); info!( - "[{id:#010x}] [{addr}] [{user}] [TCP] {target_addr}", + "[{id:#010x}] [{addr}] [{user}] [TCP] {target_addr} ", id = self.id(), addr = self.inner.remote_address(), user = self.auth, @@ -63,6 +63,7 @@ impl Connection { // a <- b rx let (tx, rx, err) = exchange_tcp(&mut conn, &mut stream, self.ctx.cfg.stream_timeout).await; + // let (tx, rx) = tokio::io::copy_bidirectional(&mut conn, &mut stream).await?; _ = conn.reset(ERROR_CODE); _ = stream.shutdown().await; @@ -86,7 +87,7 @@ impl Connection { match process.await { Ok(()) => {} Err(err) => warn!( - "[{id:#010x}] [{addr}] [{user}] [TCP] {target_addr}: {err:#?}", + "[{id:#010x}] [{addr}] [{user}] [TCP] {target_addr}: {err}", id = self.id(), addr = self.inner.remote_address(), user = self.auth, diff --git a/tuic-server/src/connection/mod.rs b/tuic-server/src/connection/mod.rs index fbc20d23..658fd79e 100644 --- a/tuic-server/src/connection/mod.rs +++ b/tuic-server/src/connection/mod.rs @@ -19,7 +19,7 @@ mod handle_stream; mod handle_task; mod udp_session; -pub const ERROR_CODE: VarInt = VarInt::from_u32(0); +pub const ERROR_CODE: VarInt = VarInt::from_u32(6000); pub const INIT_CONCURRENT_STREAMS: u32 = 32; #[derive(Clone)] diff --git a/tuic-server/src/io.rs b/tuic-server/src/io.rs index 25eb2a52..3a810799 100644 --- a/tuic-server/src/io.rs +++ b/tuic-server/src/io.rs @@ -18,6 +18,7 @@ pub async fn exchange_tcp( let mut last_err = None; let mut timeout = tokio::time::interval(timeout); timeout.reset(); + loop { tokio::select! { _ = timeout.tick() => { @@ -28,7 +29,7 @@ pub async fn exchange_tcp( a2b_res = a.recv.read(&mut a2b) => match a2b_res { Ok(Some(num)) => { a2b_num += num; - if let Err(err) = b.write(&a2b).await { + if let Err(err) = b.write_all(&a2b[..num]).await { last_err = Some(err.into()); break; } @@ -50,7 +51,7 @@ pub async fn exchange_tcp( break; } b2a_num += num; - if let Err(err) = a.send.write(&b2a).await { + if let Err(err) = a.send.write_all(&b2a[..num]).await { last_err = Some(err.into()); break; } diff --git a/tuic-server/src/main.rs b/tuic-server/src/main.rs index c5772036..99396490 100644 --- a/tuic-server/src/main.rs +++ b/tuic-server/src/main.rs @@ -1,5 +1,4 @@ -#![feature(trivial_bounds)] -#![feature(let_chains, async_closure)] +#![feature(let_chains, trivial_bounds)] use std::{env, process, sync::Arc}; diff --git a/tuic-server/src/tls.rs b/tuic-server/src/tls.rs index 350ab6b7..106032f7 100644 --- a/tuic-server/src/tls.rs +++ b/tuic-server/src/tls.rs @@ -1,6 +1,7 @@ use std::{ + ops::Deref, path::{Path, PathBuf}, - sync::Arc, + sync::{Arc, RwLock}, }; use eyre::Context; @@ -10,8 +11,7 @@ use rustls::{ server::{ClientHello, ResolvesServerCert}, sign::CertifiedKey, }; -use tokio::sync::RwLock; -use tracing::{error, warn}; +use tracing::warn; use crate::utils::{self, FutResultExt}; @@ -40,16 +40,11 @@ impl CertResolver { let (mut watcher, mut rx) = utils::async_watcher().await?; watcher.watch(self.cert_path.as_ref(), RecursiveMode::NonRecursive)?; - - while let Some(res) = rx.recv().await { - match res { - Err(e) => error!("TLS cert-key reload watcher error: {:?}", e), - Ok(_) => { - warn!("TLS cert-key reload"); - let cert_key = load_cert_key(&self.cert_path, &self.key_path).await?; - let mut guard = self.cert_key.write().await; - *guard = cert_key; - } + while (rx.recv().await).is_ok() { + warn!("TLS cert-key reload"); + let cert_key = load_cert_key(&self.cert_path, &self.key_path).await?; + if let Ok(mut guard) = self.cert_key.write() { + *guard = cert_key; } } Ok(()) @@ -57,7 +52,7 @@ impl CertResolver { } impl ResolvesServerCert for CertResolver { fn resolve(&self, _: ClientHello<'_>) -> Option> { - Some(self.cert_key.blocking_read().clone()) + Some(self.cert_key.read().ok()?.deref().clone()) } } diff --git a/tuic-server/src/utils.rs b/tuic-server/src/utils.rs index 04a8467f..ee36d7bc 100644 --- a/tuic-server/src/utils.rs +++ b/tuic-server/src/utils.rs @@ -4,9 +4,9 @@ use std::{ }; use educe::Educe; -use notify::{Event, RecommendedWatcher, Watcher}; +use notify::{EventKind, RecommendedWatcher, Watcher}; use serde::{Deserialize, Serialize}; -use tokio::sync::mpsc::{Receiver, channel}; +use tokio::sync::broadcast; #[derive(Clone, Copy)] pub enum UdpRelayMode { @@ -70,16 +70,18 @@ where } } -pub async fn async_watcher() -> notify::Result<(RecommendedWatcher, Receiver>)> -{ - let (tx, rx) = channel(1); - +pub async fn async_watcher() -> eyre::Result<(RecommendedWatcher, broadcast::Receiver<()>)> { + let (tx, rx) = broadcast::channel(1); let watcher = RecommendedWatcher::new( - move |res| { - let tx = tx.clone(); - tokio::task::spawn(async move { - tx.send(res).await.unwrap(); - }); + move |res: Result| { + if let Ok(event) = res { + match event.kind { + EventKind::Create(_) | EventKind::Modify(_) => { + tx.send(()).unwrap(); + } + _ => {} + } + } }, notify::Config::default(), )?;