diff --git a/Cargo.toml b/Cargo.toml index 123ff3f1..d6bce3c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,7 +73,7 @@ desktop = [ ] [dependencies] # Async runtime -tokio = { version = "1", features = ["full"], optional = true } +tokio = { version = "1", features = ["fs", "io-util", "macros", "net", "process", "rt-multi-thread", "signal", "sync", "time"], optional = true } tokio-util = { version = "0.7", features = ["rt"], optional = true } # Web framework @@ -82,7 +82,7 @@ axum-extra = { version = "0.12", features = ["cookie"], optional = true } tower-http = { version = "0.6", features = ["cors", "trace", "set-header"], optional = true } # Database - Use bundled SQLite for static linking -sqlx = { version = "0.8", features = ["runtime-tokio", "sqlite"], optional = true } +sqlx = { version = "0.9", default-features = false, features = ["runtime-tokio", "sqlite-bundled"], optional = true } # Serialization serde = { version = "1", features = ["derive"], optional = true } @@ -91,7 +91,6 @@ toml_edit = { version = "0.25", optional = true } # Logging tracing = { version = "0.1", optional = true } -tracing-log = { version = "0.2", optional = true } tracing-subscriber = { version = "0.3", features = ["env-filter", "json", "tracing-log"], optional = true } # Error handling @@ -100,7 +99,7 @@ anyhow = { version = "1", optional = true } # Authentication argon2 = { version = "0.5", optional = true } -rand = { version = "0.9", optional = true } +rand = { version = "0.10", optional = true } # Utilities uuid = { version = "1", features = ["v4", "serde"], optional = true } @@ -109,7 +108,7 @@ tempfile = { version = "3", optional = true } # HTTP client (for URL downloads) # Use rustls by default, but allow native-tls for systems with older GLIBC -reqwest = { version = "0.13", features = ["stream", "rustls", "json"], default-features = false, optional = true } +reqwest = { version = "0.13", features = ["stream", "rustls-no-provider", "json"], default-features = false, optional = true } urlencoding = { version = "2", optional = true } # Static file embedding @@ -117,9 +116,9 @@ rust-embed = { version = "8", features = ["compression", "debug-embed"], optiona mime_guess = { version = "2", optional = true } # TLS/HTTPS -rustls = { version = "0.23", features = ["ring"], optional = true } +rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"], optional = true } rcgen = { version = "0.14", optional = true } -axum-server = { version = "0.8", features = ["tls-rustls"], optional = true } +axum-server = { version = "0.8", features = ["tls-rustls-no-provider"], optional = true } # CLI argument parsing clap = { version = "4", features = ["derive"], optional = true } @@ -139,15 +138,15 @@ async-stream = { version = "0.3", optional = true } futures = { version = "0.3", optional = true } # WebSocket client (for ttyd proxy) -tokio-tungstenite = { version = "0.28", optional = true } +tokio-tungstenite = { version = "0.29", optional = true } # High-performance synchronization parking_lot = { version = "0.12", optional = true } arc-swap = { version = "1.8", optional = true } # WebRTC -webrtc = { version = "0.14", optional = true } -rtp = { version = "0.14", optional = true } +webrtc = { version = "0.17", optional = true } +rtp = { version = "0.17", optional = true } rtsp-types = { version = "0.1", optional = true } sdp-types = { version = "0.1", optional = true } @@ -162,8 +161,8 @@ ventoy-img = { path = "libs/ventoy-img-rs", optional = true } # RustDesk protocol support protobuf = { version = "3.7", features = ["with-bytes"], optional = true } sodiumoxide = { version = "0.2", optional = true } -des = { version = "0.8", optional = true } -sha2 = { version = "0.10", optional = true } +des = { version = "0.9", optional = true } +sha2 = { version = "0.11", optional = true } # TypeScript type generation typeshare = { version = "1.0", optional = true } @@ -177,7 +176,7 @@ audiopus = { version = "0.2", optional = true } [target.'cfg(target_os = "linux")'.dependencies] # Utilities -nix = { version = "0.30", default-features = false, features = ["fs", "socket", "net", "hostname", "poll"], optional = true } +nix = { version = "0.31", default-features = false, features = ["fs", "socket", "net", "hostname", "poll"], optional = true } # Video capture (V4L2) v4l2r = { path = "libs/v4l2r", optional = true } @@ -189,7 +188,7 @@ alsa = { version = "0.11", optional = true } gpio-cdev = { version = "0.6", optional = true } [target.'cfg(windows)'.dependencies] -cpal = { version = "0.17", default-features = false, optional = true } +cpal = { version = "0.18", default-features = false, optional = true } windows-sys = { version = "0.61", features = [ "Win32_Foundation", "Win32_NetworkManagement_IpHelper", @@ -199,9 +198,6 @@ windows-sys = { version = "0.61", features = [ "Win32_System_Threading", ], optional = true } -[dev-dependencies] -tempfile = "3" - [build-dependencies] protobuf-codegen = "3.7" diff --git a/libs/hwcodec/Cargo.toml b/libs/hwcodec/Cargo.toml index eeb1282e..ef8efc29 100644 --- a/libs/hwcodec/Cargo.toml +++ b/libs/hwcodec/Cargo.toml @@ -21,4 +21,4 @@ serde_json = "1.0" [build-dependencies] cc = "1.0" -bindgen = "0.70.1" +bindgen = "0.72" diff --git a/libs/hwcodec/src/ffmpeg_ram/encode.rs b/libs/hwcodec/src/ffmpeg_ram/encode.rs index 23a3b0dc..de99b9cd 100644 --- a/libs/hwcodec/src/ffmpeg_ram/encode.rs +++ b/libs/hwcodec/src/ffmpeg_ram/encode.rs @@ -1,11 +1,12 @@ +#[cfg(feature = "bytes")] +use crate::ffmpeg_ram::{ffmpeg_ram_encode_packet, ffmpeg_ram_free_packet}; use crate::{ common::DataFormat::{self, *}, ffmpeg::{init_av_log, AVPixelFormat}, ffmpeg_ram::{ - ffmpeg_linesize_offset_length, ffmpeg_ram_encode, ffmpeg_ram_encode_packet, - ffmpeg_ram_encoder_last_error, ffmpeg_ram_free_encoder, ffmpeg_ram_free_packet, - ffmpeg_ram_new_encoder, ffmpeg_ram_request_keyframe, ffmpeg_ram_set_bitrate, CodecInfo, - AV_NUM_DATA_POINTERS, + ffmpeg_linesize_offset_length, ffmpeg_ram_encode, ffmpeg_ram_encoder_last_error, + ffmpeg_ram_free_encoder, ffmpeg_ram_new_encoder, ffmpeg_ram_request_keyframe, + ffmpeg_ram_set_bitrate, CodecInfo, AV_NUM_DATA_POINTERS, }, }; #[cfg(feature = "bytes")] diff --git a/libs/v4l2r/Cargo.toml b/libs/v4l2r/Cargo.toml index 176813ec..8bf4b715 100644 --- a/libs/v4l2r/Cargo.toml +++ b/libs/v4l2r/Cargo.toml @@ -49,7 +49,7 @@ version = "0.1.6" version = "0.4.14" [dependencies.nix] -version = "0.28" +version = "0.31" features = [ "ioctl", "mman", @@ -59,7 +59,7 @@ features = [ ] [dependencies.thiserror] -version = "1.0" +version = "2" [build-dependencies.bindgen] -version = "0.70.1" +version = "0.72" diff --git a/libs/v4l2r/Cargo.toml.orig b/libs/v4l2r/Cargo.toml.orig index 019e1386..4065ed24 100644 --- a/libs/v4l2r/Cargo.toml.orig +++ b/libs/v4l2r/Cargo.toml.orig @@ -18,11 +18,11 @@ arch64 = [] arch32 = [] [dependencies] -nix = { version = "0.28", features = ["ioctl", "mman", "poll", "fs", "event"] } +nix = { version = "0.31", features = ["ioctl", "mman", "poll", "fs", "event"] } bitflags = "2.4" -thiserror = "1.0" +thiserror = "2" log = "0.4.14" enumn = "0.1.6" [build-dependencies] -bindgen = "0.70.1" +bindgen = "0.72" diff --git a/libs/v4l2r/bindgen.rs b/libs/v4l2r/bindgen.rs index edb73a21..91ac7ca9 100644 --- a/libs/v4l2r/bindgen.rs +++ b/libs/v4l2r/bindgen.rs @@ -8,8 +8,8 @@ pub struct Fix753; impl bindgen::callbacks::ParseCallbacks for Fix753 { - fn item_name(&self, original_item_name: &str) -> Option { - Some(original_item_name.trim_start_matches("Fix753_").to_owned()) + fn item_name(&self, item_info: bindgen::callbacks::ItemInfo<'_>) -> Option { + Some(item_info.name.trim_start_matches("Fix753_").to_owned()) } } diff --git a/libs/ventoy-img-rs/Cargo.toml b/libs/ventoy-img-rs/Cargo.toml index ea878394..1f301d90 100644 --- a/libs/ventoy-img-rs/Cargo.toml +++ b/libs/ventoy-img-rs/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-2.0" clap = { version = "4", features = ["derive"] } # Error handling -thiserror = "1" +thiserror = "2" [dev-dependencies] tempfile = "3" diff --git a/res/vcpkg/libyuv/Cargo.toml b/res/vcpkg/libyuv/Cargo.toml index 6ec2b467..03a9b9e2 100644 --- a/res/vcpkg/libyuv/Cargo.toml +++ b/res/vcpkg/libyuv/Cargo.toml @@ -8,4 +8,4 @@ license = "BSD-3-Clause" [dependencies] [build-dependencies] -bindgen = "0.70.1" +bindgen = "0.72" diff --git a/src/audio/capture_windows.rs b/src/audio/capture_windows.rs index 36429dc3..ab283cf0 100644 --- a/src/audio/capture_windows.rs +++ b/src/audio/capture_windows.rs @@ -220,7 +220,7 @@ fn run_capture( let stream = match sample_format { SampleFormat::F32 => build_stream::( &device, - &stream_config, + stream_config, input_channels, input_rate, tx.clone(), @@ -229,7 +229,7 @@ fn run_capture( ), SampleFormat::I16 => build_stream::( &device, - &stream_config, + stream_config, input_channels, input_rate, tx.clone(), @@ -238,7 +238,7 @@ fn run_capture( ), SampleFormat::U16 => build_stream::( &device, - &stream_config, + stream_config, input_channels, input_rate, tx.clone(), @@ -361,7 +361,7 @@ fn select_input_config( fn build_stream( device: &cpal::Device, - config: &StreamConfig, + config: StreamConfig, input_channels: u32, input_rate: u32, tx: mpsc::SyncSender>, diff --git a/src/audio/device_windows.rs b/src/audio/device_windows.rs index 8840aa5b..c73305a8 100644 --- a/src/audio/device_windows.rs +++ b/src/audio/device_windows.rs @@ -130,11 +130,11 @@ fn device_labels(device: &cpal::Device) -> DeviceLabels { let formatted = desc.to_string(); let display = desc .extended() - .first() - .cloned() + .next() + .map(str::to_owned) .unwrap_or_else(|| formatted.clone()); let mut parts = vec![formatted, desc.name().to_string(), display.clone()]; - parts.extend(desc.extended().iter().cloned()); + parts.extend(desc.extended().map(str::to_owned)); DeviceLabels { display, diff --git a/src/rtsp/streaming.rs b/src/rtsp/streaming.rs index c1b71b73..9bbbc4df 100644 --- a/src/rtsp/streaming.rs +++ b/src/rtsp/streaming.rs @@ -1,5 +1,5 @@ use bytes::Bytes; -use rand::Rng; +use rand::RngExt; use rtp::packet::Packet; use rtp::packetizer::Payloader; use rtsp_types as rtsp; diff --git a/src/rtsp/types.rs b/src/rtsp/types.rs index 2572156d..00c28b9e 100644 --- a/src/rtsp/types.rs +++ b/src/rtsp/types.rs @@ -1,4 +1,4 @@ -use rand::Rng; +use rand::RngExt; use rtsp_types as rtsp; use std::collections::HashMap; use std::fmt; diff --git a/src/rustdesk/config.rs b/src/rustdesk/config.rs index 8c44c143..0e0868b3 100644 --- a/src/rustdesk/config.rs +++ b/src/rustdesk/config.rs @@ -130,14 +130,14 @@ impl RustDeskConfig { } pub fn generate_device_id() -> String { - use rand::Rng; + use rand::RngExt; let mut rng = rand::rng(); let id: u32 = rng.random_range(100_000_000..999_999_999); id.to_string() } pub fn generate_random_password() -> String { - use rand::Rng; + use rand::RngExt; const CHARSET: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; let mut rng = rand::rng(); (0..8) diff --git a/src/update/mod.rs b/src/update/mod.rs index cec38e0c..80fe69e7 100644 --- a/src/update/mod.rs +++ b/src/update/mod.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::fmt::Write as _; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -552,7 +553,12 @@ async fn compute_file_sha256(path: &Path) -> Result { hasher.update(&buffer[..bytes_read]); } - Ok(format!("{:x}", hasher.finalize())) + let digest = hasher.finalize(); + let mut checksum = String::with_capacity(digest.len() * 2); + for byte in digest { + write!(&mut checksum, "{byte:02x}").expect("writing to a String cannot fail"); + } + Ok(checksum) } fn normalize_sha256(input: &str) -> Option { @@ -578,3 +584,20 @@ fn current_target_triple() -> Result { }; Ok(triple.to_string()) } + +#[cfg(test)] +mod tests { + use super::compute_file_sha256; + + #[tokio::test] + async fn file_sha256_is_lowercase_hex() { + let dir = tempfile::tempdir().unwrap(); + let path = dir.path().join("payload"); + tokio::fs::write(&path, b"one-kvm").await.unwrap(); + + assert_eq!( + compute_file_sha256(&path).await.unwrap(), + "f62202e0a47f1ebb56427006019524c680f15d769d70479b9dbc35f550e86e5e" + ); + } +} diff --git a/src/vnc/rfb.rs b/src/vnc/rfb.rs index 1063b1da..c43f917b 100644 --- a/src/vnc/rfb.rs +++ b/src/vnc/rfb.rs @@ -1,7 +1,7 @@ use std::net::SocketAddr; use bytes::{Bytes, BytesMut}; -use des::cipher::{BlockEncrypt, KeyInit}; +use des::cipher::{Block, BlockCipherEncrypt, KeyInit}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::TcpStream; use tokio::sync::broadcast; @@ -703,7 +703,10 @@ fn encrypt_vnc_challenge(challenge: &[u8; 16], password: &str) -> Result<[u8; 16 .map_err(|_| AppError::BadRequest("Invalid VNC DES key".to_string()))?; let mut out = *challenge; for chunk in out.chunks_exact_mut(8) { - cipher.encrypt_block(chunk.into()); + let block: &mut Block = chunk + .try_into() + .expect("VNC challenge chunks are exactly one DES block"); + cipher.encrypt_block(block); } Ok(out) }