From d677b9c61caa0d20876d9481a2501819961bdb96 Mon Sep 17 00:00:00 2001 From: Mariappan Ramasamy <142216110+kp-mariappan-ramasamy@users.noreply.github.com> Date: Wed, 26 Nov 2025 11:22:13 +0800 Subject: [PATCH 1/8] app-utils: add NonZeroDuration args module and use for server's key_update_interval and client's tracer timeout --- lightway-app-utils/src/args.rs | 2 + lightway-app-utils/src/args/duration.rs | 7 ++++ .../src/args/nonzero_duration.rs | 37 +++++++++++++++++++ lightway-client/src/args.rs | 4 +- lightway-server/src/args.rs | 6 ++- 5 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 lightway-app-utils/src/args/nonzero_duration.rs diff --git a/lightway-app-utils/src/args.rs b/lightway-app-utils/src/args.rs index e4d6df11..61263677 100644 --- a/lightway-app-utils/src/args.rs +++ b/lightway-app-utils/src/args.rs @@ -5,9 +5,11 @@ mod connection_type; mod duration; mod ip_map; mod logging; +mod nonzero_duration; pub use cipher::Cipher; pub use connection_type::ConnectionType; pub use duration::Duration; pub use ip_map::IpMap; pub use logging::{LogFormat, LogLevel}; +pub use nonzero_duration::NonZeroDuration; diff --git a/lightway-app-utils/src/args/duration.rs b/lightway-app-utils/src/args/duration.rs index 2de5443b..9a66d23e 100644 --- a/lightway-app-utils/src/args/duration.rs +++ b/lightway-app-utils/src/args/duration.rs @@ -31,3 +31,10 @@ impl std::str::FromStr for Duration { Ok(Duration(s.parse::()?)) } } + +impl Duration { + /// Returns true if this `Duration` spans no time. + pub fn is_zero(&self) -> bool { + self.0.is_zero() + } +} diff --git a/lightway-app-utils/src/args/nonzero_duration.rs b/lightway-app-utils/src/args/nonzero_duration.rs new file mode 100644 index 00000000..4d1984b2 --- /dev/null +++ b/lightway-app-utils/src/args/nonzero_duration.rs @@ -0,0 +1,37 @@ +use serde::{Deserialize, Serialize}; +use serde_with::{DisplayFromStr, serde_as}; + +/// Wrapper for compatibility with both clap and twelf at the same time +#[serde_as] +#[derive(Copy, Clone, Serialize, Deserialize)] +pub struct NonZeroDuration(#[serde_as(as = "DisplayFromStr")] humantime::Duration); + +impl std::fmt::Display for NonZeroDuration { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl std::fmt::Debug for NonZeroDuration { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl From for std::time::Duration { + fn from(d: NonZeroDuration) -> Self { + d.0.into() + } +} + +impl std::str::FromStr for NonZeroDuration { + type Err = humantime::DurationError; + + fn from_str(s: &str) -> Result { + let duration = NonZeroDuration(s.parse::()?); + if duration.0.is_zero() { + return Err(humantime::DurationError::Empty); + } + Ok(duration) + } +} diff --git a/lightway-client/src/args.rs b/lightway-client/src/args.rs index 4231e005..d84c1286 100644 --- a/lightway-client/src/args.rs +++ b/lightway-client/src/args.rs @@ -3,7 +3,7 @@ use super::route_manager::RouteMode; use anyhow::{Result, anyhow}; use bytesize::ByteSize; use clap::Parser; -use lightway_app_utils::args::{Cipher, ConnectionType, Duration, LogLevel}; +use lightway_app_utils::args::{Cipher, ConnectionType, Duration, LogLevel, NonZeroDuration}; use lightway_core::{AuthMethod, MAX_OUTSIDE_MTU}; use serde::Serialize; use std::{net::Ipv4Addr, path::PathBuf}; @@ -99,7 +99,7 @@ pub struct Config { /// Time it takes to trigger a tracer packet /// when we haven't received an outside packet #[clap(long, default_value = "10s")] - pub tracer_packet_timeout: Duration, + pub tracer_packet_timeout: NonZeroDuration, /// How long to wait before selecting the best connection. If the preferred /// connection connects before the timeout, it will be used immediately. diff --git a/lightway-server/src/args.rs b/lightway-server/src/args.rs index fd557510..fd67a03a 100644 --- a/lightway-server/src/args.rs +++ b/lightway-server/src/args.rs @@ -8,7 +8,9 @@ use clap::Parser; use ipnet::Ipv4Net; use twelf::config; -use lightway_app_utils::args::{ConnectionType, Duration, IpMap, LogFormat, LogLevel}; +use lightway_app_utils::args::{ + ConnectionType, Duration, IpMap, LogFormat, LogLevel, NonZeroDuration, +}; #[config] #[derive(Parser, Debug)] @@ -101,7 +103,7 @@ pub struct Config { /// The key update interval for DTLS/TLS 1.3 connections #[clap(long, default_value = "15m")] - pub key_update_interval: Duration, + pub key_update_interval: NonZeroDuration, /// Address to listen to #[clap(long, default_value = "0.0.0.0:27690")] From 7b7166bc1215ad74eaf76b4359d6b8233ba9a205 Mon Sep 17 00:00:00 2001 From: Mariappan Ramasamy <142216110+kp-mariappan-ramasamy@users.noreply.github.com> Date: Wed, 26 Nov 2025 11:22:13 +0800 Subject: [PATCH 2/8] client: make keepalive intervals as nonzero value and add continuous_keepalive as config parameter. Before the commit 399777519e7961eca545699abdcccf74323f7c87, we implicitly use keepalive_interval to enable/disable keepalive. If keepalive_interval is 0s, we do not start the keepalive task. But in 399777519e7961eca545699abdcccf74323f7c87, we have enhanced keepalive module to support continuous and non-continuous keepalive mechanism. Non continuous keepalive was needed when we want to check connection liveliness during network transition. There were two problems in this commit: - noncontinuous keepalive used the interval and timeout value of normal keepalive. So if the interval is 0, non-continuous keepalive does not work since there is no task. - Hardcode continuous_keepalive as true in binary. - In non-continuous mode, if there is a network change, it moved the state to Waiting. Hence keepalive will be sent only after the interval period instead of sending immediately. This commit fixes the first two issues, by using nonzero duration for keepalive_interval and keepalive_timeout and also adding a new variable for continuous_keepalive. The third problem was fixed in e129a70faf6ac65151c38eb6196d621c4f32c415 --- lightway-client/src/args.rs | 12 ++++-- lightway-client/src/keepalive.rs | 41 +++---------------- lightway-client/src/main.rs | 2 +- tests/client/client_config.yaml | 5 ++- .../parallel_connect/client_config.tcp.yaml | 4 +- .../client_config.tcp_then_udp.yaml | 6 +-- .../parallel_connect/client_config.udp.yaml | 4 +- .../client_config.udp_then_tcp.yaml | 6 +-- 8 files changed, 27 insertions(+), 53 deletions(-) diff --git a/lightway-client/src/args.rs b/lightway-client/src/args.rs index d84c1286..0581e732 100644 --- a/lightway-client/src/args.rs +++ b/lightway-client/src/args.rs @@ -89,12 +89,16 @@ pub struct Config { pub enable_pqc: bool, /// Interval between keepalives - #[clap(long, default_value = "0s")] - pub keepalive_interval: Duration, + #[clap(long, default_value = "10s")] + pub keepalive_interval: NonZeroDuration, /// Keepalive timeout - #[clap(long, default_value = "0s")] - pub keepalive_timeout: Duration, + #[clap(long, default_value = "60s")] + pub keepalive_timeout: NonZeroDuration, + + /// Enable continuous Keepalive + #[clap(long, default_value_t = true)] + pub keepalive_continuous: bool, /// Time it takes to trigger a tracer packet /// when we haven't received an outside packet diff --git a/lightway-client/src/keepalive.rs b/lightway-client/src/keepalive.rs index ee30b719..b546041e 100644 --- a/lightway-client/src/keepalive.rs +++ b/lightway-client/src/keepalive.rs @@ -27,8 +27,6 @@ impl Connection for Weak bool; - fn timeout_is_zero(&self) -> bool; fn sleep_for_interval(&self) -> impl std::future::Future + std::marker::Send; fn sleep_for_timeout(&self) -> impl std::future::Future + std::marker::Send; fn continuous(&self) -> bool; @@ -43,14 +41,6 @@ pub struct Config { } impl SleepManager for Config { - fn interval_is_zero(&self) -> bool { - self.interval.is_zero() - } - - fn timeout_is_zero(&self) -> bool { - self.timeout.is_zero() - } - async fn sleep_for_interval(&self) { tokio::time::sleep(self.interval).await } @@ -93,16 +83,6 @@ impl Keepalive { ) -> (Self, OptionFuture>) { let cancel = CancellationToken::new(); - if config.interval_is_zero() { - return ( - Self { - tx: None, - _cancellation: Arc::new(cancel.drop_guard()), - }, - None.into(), - ); - } - let (tx, rx) = mpsc::channel(1024); let task = tokio::spawn(keepalive(config, conn, rx, cancel.clone())); let cancel = Arc::new(cancel.drop_guard()); @@ -263,26 +243,23 @@ async fn keepalive( tracing::error!("Send Keepalive failed: {e:?}"); } state = State::Pending; - if !config.timeout_is_zero() { - let fut = config.sleep_for_timeout(); - timeout.as_mut().set(Some(fut).into()); - } + let fut = config.sleep_for_timeout(); + timeout.as_mut().set(Some(fut).into()); } _ = config.sleep_for_interval(), if matches!(state, State::Pending | State::Waiting) => { if let Err(e) = conn.keepalive() { tracing::error!("Send Keepalive failed: {e:?}"); } - if matches!(state, State::Waiting) && !config.timeout_is_zero() { + if matches!(state, State::Waiting) { state = State::Pending; let fut = config.sleep_for_timeout(); timeout.as_mut().set(Some(fut).into()); } } - // Note that `timeout` is `Some` only when state == - // `State::Pending` and `config.timeout` is non-zero and - // evaluates to `None` otherwise. + // Note that `timeout` is `Some` only when state == `State::Pending` + // Evaluates to `None` otherwise. Some(_) = timeout.as_mut() => { // Keepalive timed out: increment failure counter failed_keepalives = failed_keepalives.saturating_add(1); @@ -365,14 +342,6 @@ mod tests { } impl SleepManager for MockSleepManager { - fn interval_is_zero(&self) -> bool { - self.interval.is_zero() - } - - fn timeout_is_zero(&self) -> bool { - self.timeout.is_zero() - } - async fn sleep_for_interval(&self) { if self.interval.is_zero() { return; diff --git a/lightway-client/src/main.rs b/lightway-client/src/main.rs index 44334472..8c9b6772 100644 --- a/lightway-client/src/main.rs +++ b/lightway-client/src/main.rs @@ -169,8 +169,8 @@ async fn main() -> Result<()> { enable_expresslane: config.enable_expresslane, keepalive_interval: config.keepalive_interval.into(), keepalive_timeout: config.keepalive_timeout.into(), + continuous_keepalive: config.keepalive_continuous, tracer_packet_timeout: config.tracer_packet_timeout.into(), - continuous_keepalive: true, preferred_connection_wait_interval: config.preferred_connection_wait_interval.into(), sndbuf: config.sndbuf, rcvbuf: config.rcvbuf, diff --git a/tests/client/client_config.yaml b/tests/client/client_config.yaml index 3654769b..7921e012 100644 --- a/tests/client/client_config.yaml +++ b/tests/client/client_config.yaml @@ -16,8 +16,9 @@ enable_pqc: false enable_tun_iouring: false # iouring_sqpoll_idle_time: 100ms iouring_entry_count: 1024 -keepalive_interval: 0s -keepalive_timeout: 0s +keepalive_interval: 10s +keepalive_timeout: 30s +keepalive_continuous: true enable_expresslane: false enable_pmtud: false # sndbuf: 1.5 MiB diff --git a/tests/client/parallel_connect/client_config.tcp.yaml b/tests/client/parallel_connect/client_config.tcp.yaml index 7b5ed232..f4d3c497 100644 --- a/tests/client/parallel_connect/client_config.tcp.yaml +++ b/tests/client/parallel_connect/client_config.tcp.yaml @@ -66,8 +66,8 @@ enable_pqc: false enable_tun_iouring: false # iouring_sqpoll_idle_time: 100ms iouring_entry_count: 1024 -keepalive_interval: 0s -keepalive_timeout: 0s +keepalive_interval: 10s +keepalive_timeout: 60s enable_pmtud: false # sndbuf: 1.5 MiB # rcvbuf: 1.5 MiB diff --git a/tests/client/parallel_connect/client_config.tcp_then_udp.yaml b/tests/client/parallel_connect/client_config.tcp_then_udp.yaml index a82a8517..561a767d 100644 --- a/tests/client/parallel_connect/client_config.tcp_then_udp.yaml +++ b/tests/client/parallel_connect/client_config.tcp_then_udp.yaml @@ -21,11 +21,11 @@ enable_pqc: false enable_tun_iouring: false # iouring_sqpoll_idle_time: 100ms iouring_entry_count: 1024 -keepalive_interval: 0s -keepalive_timeout: 0s +keepalive_interval: 10s +keepalive_timeout: 60s enable_pmtud: false # sndbuf: 1.5 MiB # rcvbuf: 1.5 MiB route_mode: default dns_config_mode: noexec -preferred_connection_wait_interval: 2s \ No newline at end of file +preferred_connection_wait_interval: 2s diff --git a/tests/client/parallel_connect/client_config.udp.yaml b/tests/client/parallel_connect/client_config.udp.yaml index 0f85d76d..afa9f63a 100644 --- a/tests/client/parallel_connect/client_config.udp.yaml +++ b/tests/client/parallel_connect/client_config.udp.yaml @@ -67,8 +67,8 @@ enable_pqc: false enable_tun_iouring: false # iouring_sqpoll_idle_time: 100ms iouring_entry_count: 1024 -keepalive_interval: 0s -keepalive_timeout: 0s +keepalive_interval: 10s +keepalive_timeout: 60s enable_pmtud: false # sndbuf: 1.5 MiB # rcvbuf: 1.5 MiB diff --git a/tests/client/parallel_connect/client_config.udp_then_tcp.yaml b/tests/client/parallel_connect/client_config.udp_then_tcp.yaml index 3e0e9a29..275ba9f2 100644 --- a/tests/client/parallel_connect/client_config.udp_then_tcp.yaml +++ b/tests/client/parallel_connect/client_config.udp_then_tcp.yaml @@ -21,11 +21,11 @@ enable_pqc: false enable_tun_iouring: false # iouring_sqpoll_idle_time: 100ms iouring_entry_count: 1024 -keepalive_interval: 0s -keepalive_timeout: 0s +keepalive_interval: 10s +keepalive_timeout: 60s enable_pmtud: false # sndbuf: 1.5 MiB # rcvbuf: 1.5 MiB route_mode: default dns_config_mode: noexec -preferred_connection_wait_interval: 2s \ No newline at end of file +preferred_connection_wait_interval: 2s From 7eade75df134628a9f000898694f202abb12e75a Mon Sep 17 00:00:00 2001 From: Mariappan Ramasamy <142216110+kp-mariappan-ramasamy@users.noreply.github.com> Date: Thu, 27 Nov 2025 22:28:12 +0800 Subject: [PATCH 3/8] client: only set keepalive timeout if not already pending When try to send Keepalive immediately in Needed state, commit e129a70faf6ac65151c38eb6196d621c4f32c415 introduces a crictial bug where the timeout is reset after sending the Keepalive. This is serious because the timeout value will never be triggered if it is reset continuously. This makes keepalive timeout mechanism fail to work during Tracer timeout or NetworkChange. Commit 44efa8a637ce63ec0bcd6a971514b2afffb27263 tried to fix the bug, but instead of fixing the timeout, it introduced another method using failed_attempts counter to fix it. This is redundant since the existing timeout mechanism is supposed to do this precisely. Also it increases the timeout value to timeout * 3(MAX_FAILED_ATTEMPTS). This commit does the following: - reverts the changes related to failed keepalive counter changes - Fixes resetting the timer using FusedFuture implementation FusedFuture enables the use of is_terminated() method on OptionFuture --- lightway-client/src/keepalive.rs | 139 ++----------------------------- 1 file changed, 9 insertions(+), 130 deletions(-) diff --git a/lightway-client/src/keepalive.rs b/lightway-client/src/keepalive.rs index b546041e..ce740a28 100644 --- a/lightway-client/src/keepalive.rs +++ b/lightway-client/src/keepalive.rs @@ -1,5 +1,5 @@ //! Keepalive processing -use futures::future::OptionFuture; +use futures::{FutureExt, future::FusedFuture, future::OptionFuture}; use std::{ sync::{Arc, Mutex, Weak}, time::Duration, @@ -9,9 +9,6 @@ use tokio_util::sync::{CancellationToken, DropGuard}; use crate::ConnectionState; -// Number of consecutive keepalive timeouts before disconnecting. -const FAILED_KEEPALIVE_THRESHOLD: usize = 3; - pub trait Connection: Send { fn keepalive(&self) -> lightway_core::ConnectionResult<()>; } @@ -168,9 +165,6 @@ async fn keepalive( let timeout: OptionFuture<_> = None.into(); tokio::pin!(timeout); - // Number of consecutive keepalive timeouts observed - let mut failed_keepalives: usize = 0; - loop { tokio::select! { _ = token.cancelled() => { @@ -207,8 +201,6 @@ async fn keepalive( tracing::info!("reply received turning off network change keepalives"); State::Inactive }; - // Reset failure counter on successful reply - failed_keepalives = 0; timeout.as_mut().set(None.into()) }, Message::NetworkChange => { @@ -216,8 +208,6 @@ async fn keepalive( tracing::info!("sending keepalives because of {:?}", msg); state = State::Needed; } - // Reset failure counter on new interface - failed_keepalives = 0; }, Message::TracerDeltaExceeded => { // Do not trigger keepalive if it is suspended or waiting for reply @@ -231,7 +221,6 @@ async fn keepalive( if !matches!(state, State::Suspended) { tracing::info!("suspending keepalives"); state = State::Suspended; - failed_keepalives = 0; timeout.as_mut().set(None.into()) } }, @@ -243,8 +232,10 @@ async fn keepalive( tracing::error!("Send Keepalive failed: {e:?}"); } state = State::Pending; - let fut = config.sleep_for_timeout(); - timeout.as_mut().set(Some(fut).into()); + if timeout.is_terminated() { + let fut = config.sleep_for_timeout().fuse(); + timeout.as_mut().set(Some(fut).into()); + } } _ = config.sleep_for_interval(), if matches!(state, State::Pending | State::Waiting) => { @@ -253,7 +244,7 @@ async fn keepalive( } if matches!(state, State::Waiting) { state = State::Pending; - let fut = config.sleep_for_timeout(); + let fut = config.sleep_for_timeout().fuse(); timeout.as_mut().set(Some(fut).into()); } } @@ -261,18 +252,9 @@ async fn keepalive( // Note that `timeout` is `Some` only when state == `State::Pending` // Evaluates to `None` otherwise. Some(_) = timeout.as_mut() => { - // Keepalive timed out: increment failure counter - failed_keepalives = failed_keepalives.saturating_add(1); - tracing::info!("keepalive timed out (consecutive timeouts = {failed_keepalives})"); - - if failed_keepalives >= FAILED_KEEPALIVE_THRESHOLD { - tracing::info!("keepalive failure threshold exceeded; disconnecting"); - return KeepaliveResult::Timedout; - } - - // Immediately attempt another keepalive - state = State::Needed; - timeout.as_mut().set(None.into()); + tracing::warn!("keepalive timed out"); + // Return will exit the client + return KeepaliveResult::Timedout; } } } @@ -395,16 +377,6 @@ mod tests { } } - fn interval(mut self, interval: Duration) -> Self { - self.interval = interval; - self - } - - fn timeout(mut self, timeout: Duration) -> Self { - self.timeout = timeout; - self - } - fn continuous(mut self, continuous: bool) -> Self { self.continuous = continuous; self @@ -417,25 +389,6 @@ mod tests { } } - #[tokio::test] - async fn disabled_keepalive_does_nothing() { - let (sleep_manager, connection) = - KeepaliveTestBuilder::new().interval(Duration::ZERO).build(); - - let (keepalive, task) = Keepalive::new(sleep_manager, connection.clone()); - - // Send all possible messages - keepalive.online().await; - keepalive.outside_activity().await; - keepalive.reply_received().await; - keepalive.network_changed().await; - keepalive.suspend().await; - - // Task should be None (not started) - assert!(task.await.is_none()); - assert_eq!(connection.keepalive_count(), 0); - } - #[test_case(true, 1; "continuous")] #[test_case(false, 2; "non-continuous")] #[tokio::test] @@ -511,61 +464,12 @@ mod tests { start_keepalives(&keepalive, &sleep_manager, continuous).await; assert_eq!(connection.keepalive_count(), 1); - // Trigger timeouts up to the failure threshold - // Trigger FAILED_KEEPALIVE_THRESHOLD - 1 timeouts to cause immediate resends - for _ in 0..(FAILED_KEEPALIVE_THRESHOLD - 1) { - sleep_manager.trigger_timeout(); - // give the task a moment to process and resend - sleep(Duration::from_millis(10)).await; - } - - // At this point, we should have sent FAILED_KEEPALIVE_THRESHOLD total keepalives - assert_eq!(connection.keepalive_count(), FAILED_KEEPALIVE_THRESHOLD); - - // Final timeout should exceed the threshold and terminate the task sleep_manager.trigger_timeout(); let result = task.await.unwrap().unwrap(); assert!(matches!(result, KeepaliveResult::Timedout)); } - #[test_case(true; "continuous")] - #[test_case(false; "non-continuous")] - #[tokio::test] - async fn network_change_resets_failed_keepalive(continuous: bool) { - let (sleep_manager, connection) = - KeepaliveTestBuilder::new().continuous(continuous).build(); - - let (keepalive, task) = Keepalive::new(sleep_manager.clone(), connection.clone()); - - start_keepalives(&keepalive, &sleep_manager, continuous).await; - assert_eq!(connection.keepalive_count(), 1); - - // Trigger timeouts up to the failure threshold - // Trigger FAILED_KEEPALIVE_THRESHOLD - 1 timeouts to cause immediate resends - for _ in 0..(FAILED_KEEPALIVE_THRESHOLD - 1) { - sleep_manager.trigger_timeout(); - // give the task a moment to process and resend - sleep(Duration::from_millis(10)).await; - } - - // At this point, we should have sent FAILED_KEEPALIVE_THRESHOLD total keepalives - assert_eq!(connection.keepalive_count(), FAILED_KEEPALIVE_THRESHOLD); - - // Network change here should reset failed keepalive counter - keepalive.network_changed().await; - sleep(Duration::from_millis(10)).await; - - // New timeout and it should just send a new keepalive since the counter got reset - sleep_manager.trigger_timeout(); - sleep(Duration::from_millis(10)).await; - assert_eq!(connection.keepalive_count(), FAILED_KEEPALIVE_THRESHOLD + 1); - - drop(keepalive); - let result = task.await.unwrap().unwrap(); - assert!(matches!(result, KeepaliveResult::Cancelled)); - } - #[test_case(true, 2; "continuous")] #[test_case(false, 1; "non-continuous")] #[tokio::test] @@ -700,31 +604,6 @@ mod tests { assert!(matches!(result, KeepaliveResult::Cancelled)); } - #[test_case(true; "continuous")] - #[test_case(false; "non-continuous")] - #[tokio::test] - async fn zero_timeout_disables_timeout(continuous: bool) { - let (sleep_manager, connection) = KeepaliveTestBuilder::new() - .continuous(continuous) - .timeout(Duration::ZERO) - .build(); - - let (keepalive, task) = Keepalive::new(sleep_manager.clone(), connection.clone()); - - start_keepalives(&keepalive, &sleep_manager, continuous).await; - assert_eq!(connection.keepalive_count(), 1); - - // Continue sending keepalives without timeout - sleep_manager.trigger_interval(); - sleep(Duration::from_millis(10)).await; - - assert_eq!(connection.keepalive_count(), 2); - - drop(keepalive); - let result = task.await.unwrap().unwrap(); - assert!(matches!(result, KeepaliveResult::Cancelled)); - } - #[test_case(true; "continuous")] #[test_case(false; "non-continuous")] #[tokio::test] From 8380b46fa7c32df6b7f3732a562e4e0dd5382b27 Mon Sep 17 00:00:00 2001 From: Mariappan Ramasamy <142216110+kp-mariappan-ramasamy@users.noreply.github.com> Date: Thu, 27 Nov 2025 23:18:39 +0800 Subject: [PATCH 4/8] keepalive: remove unnecessary Option wrapper from tx field The tx field in Keepalive struct was always Some and never set to None. Removed the Option wrapper to simplify the code and eliminate unnecessary checks in all methods. --- lightway-client/src/keepalive.rs | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/lightway-client/src/keepalive.rs b/lightway-client/src/keepalive.rs index ce740a28..db0c6f79 100644 --- a/lightway-client/src/keepalive.rs +++ b/lightway-client/src/keepalive.rs @@ -68,7 +68,7 @@ pub enum KeepaliveResult { #[derive(Clone)] pub struct Keepalive { - tx: Option>, + tx: mpsc::Sender, _cancellation: Arc, } @@ -85,7 +85,7 @@ impl Keepalive { let cancel = Arc::new(cancel.drop_guard()); ( Self { - tx: Some(tx), + tx, _cancellation: cancel, }, Some(task).into(), @@ -94,48 +94,36 @@ impl Keepalive { /// Signal that the connection is now online pub async fn online(&self) { - if let Some(tx) = &self.tx { - let _ = tx.send(Message::Online).await; - } + let _ = self.tx.send(Message::Online).await; } /// Signal that outside activity was observed pub async fn outside_activity(&self) { - if let Some(tx) = &self.tx { - let _ = tx.try_send(Message::OutsideActivity); - } + let _ = self.tx.try_send(Message::OutsideActivity); } /// Signal that a pong was received pub async fn reply_received(&self) { - if let Some(tx) = &self.tx { - let _ = tx.send(Message::ReplyReceived).await; - } + let _ = self.tx.send(Message::ReplyReceived).await; } /// Signal that the network has changed. /// In the case we are offline, this will start the keepalives immediately /// Otherwise this will reset our timeouts pub async fn network_changed(&self) { - if let Some(tx) = &self.tx { - let _ = tx.send(Message::NetworkChange).await; - } + let _ = self.tx.send(Message::NetworkChange).await; } /// Signal that we haven't heard from server in a while /// This will trigger a keepalive immediately if keepalive is not suspended. pub async fn tracer_delta_exceeded(&self) { - if let Some(tx) = &self.tx { - let _ = tx.send(Message::TracerDeltaExceeded).await; - } + let _ = self.tx.send(Message::TracerDeltaExceeded).await; } /// Signal to suspend keepalives. /// Suspends the sleep interval timer if it's active. pub async fn suspend(&self) { - if let Some(tx) = &self.tx { - let _ = tx.send(Message::Suspend).await; - } + let _ = self.tx.send(Message::Suspend).await; } } From 7c0fe54a59cd6b9bf9027373890c5b1184a327a7 Mon Sep 17 00:00:00 2001 From: Mariappan Ramasamy <142216110+kp-mariappan-ramasamy@users.noreply.github.com> Date: Fri, 28 Nov 2025 00:45:13 +0800 Subject: [PATCH 5/8] client: reset keepalive timeout on OutsideActivity Consider the following case: - Client send keepalive request to server and the reply is lost. Timeout would have been started when client send request. - Now client/server starts exchanging packets continuously triggering OutsideActivity message - While handling OutsideActivity message, we reset the interval and let timeout run. So when there is continuous data exchange, we will not send any keepalive request, but we will wait for Reply which is sent at step 1. After the timeout expires, it will break the connection since it has not received reply. This commit resets the timeout, which does not have this faulty behavior. --- lightway-client/src/keepalive.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lightway-client/src/keepalive.rs b/lightway-client/src/keepalive.rs index db0c6f79..df54f3a8 100644 --- a/lightway-client/src/keepalive.rs +++ b/lightway-client/src/keepalive.rs @@ -173,13 +173,7 @@ async fn keepalive( // this branch of the select we have achieved // the aim of not sending keepalives if there // is active traffic. - // - // On the other hand the timeout timer is not - // restarted, if a ping has been sent then a - // pong is required even in the presence of - // other outside traffic. This helps to catch - // connectivity issues even if traffic is - // flowing only in one direction. + timeout.as_mut().set(None.into()); continue }, Message::ReplyReceived => { From 8e6632c8bd6c6b2c6aa8d6995f7b497c5946c27f Mon Sep 17 00:00:00 2001 From: Mariappan Ramasamy <142216110+kp-mariappan-ramasamy@users.noreply.github.com> Date: Fri, 28 Nov 2025 00:45:13 +0800 Subject: [PATCH 6/8] client: minor cosmetic changes This commit does two changes: - Remove the suspended check before setting the status to suspended - In the block where state could be waiting or pending, we move the state to pending if it is Waiting. We could effectively move the state change outside of the if loop. Also, Instead of checking for Waiting state, which implicitly mean no timeout, check the timeout status before setting the timeout. --- lightway-client/src/keepalive.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lightway-client/src/keepalive.rs b/lightway-client/src/keepalive.rs index df54f3a8..b9f54bc0 100644 --- a/lightway-client/src/keepalive.rs +++ b/lightway-client/src/keepalive.rs @@ -200,11 +200,9 @@ async fn keepalive( } Message::Suspend => { // Suspend keepalives whenever the timer is active - if !matches!(state, State::Suspended) { - tracing::info!("suspending keepalives"); - state = State::Suspended; - timeout.as_mut().set(None.into()) - } + tracing::info!("suspending keepalives"); + state = State::Suspended; + timeout.as_mut().set(None.into()) }, } } @@ -224,8 +222,8 @@ async fn keepalive( if let Err(e) = conn.keepalive() { tracing::error!("Send Keepalive failed: {e:?}"); } - if matches!(state, State::Waiting) { - state = State::Pending; + state = State::Pending; + if timeout.is_terminated() { let fut = config.sleep_for_timeout().fuse(); timeout.as_mut().set(Some(fut).into()); } From 5e4c001c5233f293d51b4fe0236d0d164e03a9dd Mon Sep 17 00:00:00 2001 From: Mariappan Ramasamy <142216110+kp-mariappan-ramasamy@users.noreply.github.com> Date: Thu, 11 Dec 2025 14:50:10 +0800 Subject: [PATCH 7/8] keepalive: reset timeout on NetworkChange message When there is a network interruption, (mobile) clients will send suspend message to prevent keepalive from disconnecting lightway session. When the network comes back up, it send NetworkChange message to trigger the UDP floating connection. So we need to reset the timeout to start fresh --- lightway-client/src/keepalive.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lightway-client/src/keepalive.rs b/lightway-client/src/keepalive.rs index b9f54bc0..35e48f6d 100644 --- a/lightway-client/src/keepalive.rs +++ b/lightway-client/src/keepalive.rs @@ -190,6 +190,12 @@ async fn keepalive( tracing::info!("sending keepalives because of {:?}", msg); state = State::Needed; } + // Reset timeout to make sure we start again + // When there is a network interruption, mobile clients may send + // suspend to avoid keepalive dropping the connection. + // Once the connection comes back up, it sends NetworkChange to + // trigger connection floating incase needed. + timeout.as_mut().set(None.into()) }, Message::TracerDeltaExceeded => { // Do not trigger keepalive if it is suspended or waiting for reply From 705bfa12af2e8eb52ad216124d0c668f32527231 Mon Sep 17 00:00:00 2001 From: Mariappan Ramasamy <142216110+kp-mariappan-ramasamy@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:06:12 +0800 Subject: [PATCH 8/8] cargo: update outdated jsonwebtoken crate jsonwebtoken has a breaking change: https://github.com/Keats/jsonwebtoken/blob/master/CHANGELOG.md#1000-2025-09-29 User has to choose now between aws_lc_rs/rust_crypto instead of default ring. `aws_lc_rs` pulls in OpenSsl license which seems to not compatible with AGPL3. So went with rust_crypto. --- Cargo.lock | 395 ++++++++++++++++++++++++++++++++++--- deny.toml | 3 +- lightway-server/Cargo.toml | 2 +- 3 files changed, 369 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cff68b94..5fad4c4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,12 +185,24 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + [[package]] name = "bindgen" version = "0.72.1" @@ -462,6 +474,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "core-foundation" version = "0.9.4" @@ -502,6 +520,18 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -533,6 +563,33 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "darling" version = "0.14.4" @@ -614,6 +671,17 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "deranged" version = "0.5.5" @@ -699,7 +767,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", + "const-oid", "crypto-common", + "subtle", ] [[package]] @@ -729,6 +799,44 @@ dependencies = [ "libm", ] +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2 0.10.9", + "subtle", + "zeroize", +] + [[package]] name = "educe" version = "0.6.0" @@ -747,6 +855,27 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encoding_rs" version = "0.8.35" @@ -824,6 +953,22 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "find-msvc-tools" version = "0.1.4" @@ -994,6 +1139,7 @@ checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1044,6 +1190,17 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1088,6 +1245,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac 0.12.1", +] + [[package]] name = "hmac" version = "0.10.1" @@ -1098,6 +1264,15 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "humantime" version = "2.3.0" @@ -1219,16 +1394,24 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "9.3.1" +version = "10.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +checksum = "c76e1c7d7df3e34443b3621b459b066a7b79644f059fc8b2db7070c825fd417e" dependencies = [ "base64", + "ed25519-dalek", + "getrandom 0.2.16", + "hmac 0.12.1", "js-sys", + "p256", + "p384", "pem", - "ring", + "rand 0.8.5", + "rsa", "serde", "serde_json", + "sha2 0.10.9", + "signature", "simple_asn1", ] @@ -1246,6 +1429,9 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] name = "lenient_semver" @@ -1745,6 +1931,22 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -1760,6 +1962,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1843,6 +2056,30 @@ dependencies = [ "num-traits", ] +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2 0.10.9", +] + +[[package]] +name = "p384" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2 0.10.9", +] + [[package]] name = "parking" version = "2.2.1" @@ -1890,6 +2127,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "petgraph" version = "0.6.5" @@ -1923,6 +2169,27 @@ dependencies = [ "futures-io", ] +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pnet" version = "0.35.0" @@ -2015,6 +2282,15 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro-crate" version = "3.4.0" @@ -2053,11 +2329,11 @@ checksum = "419a3ad8fa9f9d445e69d9b185a24878ae6e6f55c96e4512f4a0e28cd3bc5c56" dependencies = [ "blowfish", "byteorder", - "hmac", + "hmac 0.10.1", "md-5", "rand 0.8.5", "sha-1", - "sha2", + "sha2 0.9.9", ] [[package]] @@ -2227,17 +2503,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] -name = "ring" -version = "0.17.14" +name = "rfc6979" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.16", - "libc", - "untrusted", - "windows-sys 0.52.0", + "hmac 0.12.1", + "subtle", ] [[package]] @@ -2255,6 +2527,26 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "rsa" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88" +dependencies = [ + "const-oid", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rustc-demangle" version = "0.1.26" @@ -2267,6 +2559,15 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -2324,6 +2625,20 @@ version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "semver" version = "1.0.27" @@ -2480,6 +2795,17 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha3" version = "0.10.8" @@ -2505,6 +2831,16 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + [[package]] name = "simple_asn1" version = "0.6.3" @@ -2554,6 +2890,16 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "strsim" version = "0.10.0" @@ -2985,12 +3331,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - [[package]] name = "utf8parse" version = "0.2.2" @@ -3252,15 +3592,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.59.0" @@ -3501,3 +3832,9 @@ dependencies = [ "quote", "syn 2.0.110", ] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" diff --git a/deny.toml b/deny.toml index 659aa76f..93792c02 100644 --- a/deny.toml +++ b/deny.toml @@ -51,14 +51,15 @@ skip = [ { name = "hashbrown", version = "0.12.3" }, { name = "hashbrown", version = "0.15.5" }, { name = "heck", version = "0.4.1" }, + { name = "hmac", version = "0.10.1" }, { name = "indexmap", version = "1.9.3" }, { name = "serde_yaml", version = "0.8.26" }, + { name = "sha2", version = "0.9.9" }, { name = "strsim", version = "0.10.0" }, { name = "syn", version = "1.0.109" }, { name = "thiserror", version = "1.0.69" }, { name = "thiserror-impl", version = "1.0.69" }, { name = "windows-link", version = "0.1.3" }, - { name = "windows-sys", version = "0.52.0" }, { name = "windows-sys", version = "0.59.0" }, { name = "windows-sys", version = "0.60.2" }, { name = "windows-targets", version = "0.52.6" }, diff --git a/lightway-server/Cargo.toml b/lightway-server/Cargo.toml index 3cfb136b..1b7fee49 100644 --- a/lightway-server/Cargo.toml +++ b/lightway-server/Cargo.toml @@ -27,7 +27,7 @@ ctrlc.workspace = true delegate.workspace = true educe.workspace = true ipnet.workspace = true -jsonwebtoken = "9.3.0" +jsonwebtoken = { version = "10.0.0", features = ["rust_crypto"] } libc.workspace = true lightway-app-utils.workspace = true lightway-core = { workspace = true, features = ["postquantum"] }