Merge pull request #663 from fengalin/fix/external/qbzd-add-tls-provider
fix(qbzd): add tls provider
This commit is contained in:
11 files changed
+28
-116
No files matched your search
Generated
+1
-69
@@ -2615,10 +2615,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2628,11 +2626,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"r-efi 5.3.0",
|
||||
"wasip2",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4212,12 +4208,6 @@ dependencies = [
|
||||
"hashbrown 0.17.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lru-slab"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
||||
|
||||
[[package]]
|
||||
name = "lyon_algorithms"
|
||||
version = "1.0.20"
|
||||
@@ -5943,6 +5933,7 @@ dependencies = [
|
||||
"rand 0.10.1",
|
||||
"reqwest",
|
||||
"rusqlite",
|
||||
"rustls",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
@@ -5998,7 +5989,6 @@ dependencies = [
|
||||
"mdns-sd",
|
||||
"rupnp",
|
||||
"rust_cast",
|
||||
"rustls",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.18",
|
||||
@@ -6526,61 +6516,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn"
|
||||
version = "0.11.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"cfg_aliases",
|
||||
"pin-project-lite",
|
||||
"quinn-proto",
|
||||
"quinn-udp",
|
||||
"rustc-hash 2.1.1",
|
||||
"rustls",
|
||||
"socket2 0.6.3",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn-proto"
|
||||
version = "0.11.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"getrandom 0.3.4",
|
||||
"lru-slab",
|
||||
"rand 0.9.3",
|
||||
"ring",
|
||||
"rustc-hash 2.1.1",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"slab",
|
||||
"thiserror 2.0.18",
|
||||
"tinyvec",
|
||||
"tracing",
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn-udp"
|
||||
version = "0.5.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"socket2 0.6.3",
|
||||
"tracing",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
@@ -7001,7 +6936,6 @@ dependencies = [
|
||||
"log",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"quinn",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"serde",
|
||||
@@ -7280,7 +7214,6 @@ dependencies = [
|
||||
"aws-lc-rs",
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
@@ -7305,7 +7238,6 @@ version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
|
||||
dependencies = [
|
||||
"web-time",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
# HTTP
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "cookies", "stream"] }
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls-webpki-roots-no-provider", "cookies", "stream"] }
|
||||
|
||||
# Logging
|
||||
log = "0.4"
|
||||
|
||||
@@ -24,3 +24,6 @@ chrono = { workspace = true }
|
||||
md-5 = { workspace = true }
|
||||
base64 = { workspace = true }
|
||||
rand = "0.10"
|
||||
|
||||
# TLS provider selection
|
||||
rustls = { version = "0.23", features = ["aws_lc_rs"] }
|
||||
@@ -10,3 +10,20 @@ pub mod session_store;
|
||||
pub mod shell;
|
||||
pub mod settings;
|
||||
pub mod user_data;
|
||||
|
||||
/// Install the rustls process-level `CryptoProvider` (aws-lc-rs) exactly once.
|
||||
///
|
||||
/// Idempotent (a second call is a no-op); harmless if some other component
|
||||
/// already installed a default (`install_default` then returns Err, ignored).
|
||||
pub fn ensure_crypto_provider() {
|
||||
use std::sync::Once;
|
||||
static INIT: Once = Once::new();
|
||||
INIT.call_once(|| {
|
||||
if rustls::crypto::aws_lc_rs::default_provider()
|
||||
.install_default()
|
||||
.is_err()
|
||||
{
|
||||
log::debug!("[app] rustls CryptoProvider already installed");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -8,12 +8,6 @@ description = "Casting support for QBZ - Chromecast, DLNA"
|
||||
# Chromecast
|
||||
rust_cast = "0.21"
|
||||
|
||||
# TLS provider selection. rust_cast uses rustls; in the multi-crate binary both
|
||||
# the aws-lc-rs and ring providers end up enabled (reqwest pulls ring), so
|
||||
# rustls can't auto-pick one and panics on connect. We install aws-lc-rs
|
||||
# explicitly before connecting (see `ensure_crypto_provider`).
|
||||
rustls = { version = "0.23", features = ["aws_lc_rs"] }
|
||||
|
||||
# mDNS discovery
|
||||
mdns-sd = "0.11"
|
||||
|
||||
|
||||
@@ -75,9 +75,6 @@ impl ChromecastHandle {
|
||||
|
||||
/// Connect to a Chromecast device
|
||||
pub fn connect(&self, ip: String, port: u16) -> Result<(), CastError> {
|
||||
// rust_cast opens a rustls TLS channel; make sure a CryptoProvider is
|
||||
// installed first (the worker thread would otherwise panic).
|
||||
crate::ensure_crypto_provider();
|
||||
let (reply_tx, reply_rx) = mpsc::channel();
|
||||
self.sender
|
||||
.send(CastCommand::Connect {
|
||||
|
||||
@@ -60,9 +60,6 @@ pub struct DlnaConnection {
|
||||
impl DlnaConnection {
|
||||
/// Connect to a DLNA device and discover service URLs
|
||||
pub async fn connect(device: DiscoveredDlnaDevice) -> Result<Self, DlnaError> {
|
||||
// Defensive: the device-description fetch may go over TLS in some
|
||||
// setups; ensure a rustls CryptoProvider is installed (idempotent).
|
||||
crate::ensure_crypto_provider();
|
||||
let device_url: Uri = device
|
||||
.url
|
||||
.parse()
|
||||
|
||||
@@ -38,25 +38,3 @@ pub use dlna::{
|
||||
/// Cast device type alias for backwards compatibility
|
||||
pub type CastDevice = CastDeviceConnection;
|
||||
|
||||
/// Install the rustls process-level `CryptoProvider` (aws-lc-rs) exactly once.
|
||||
///
|
||||
/// `rust_cast` opens a TLS control channel to the Chromecast via rustls. In the
|
||||
/// full QBZ binary BOTH the `aws-lc-rs` and `ring` providers are enabled (reqwest
|
||||
/// pulls `ring`, rust_cast pulls `aws-lc-rs`), so rustls can't auto-select one
|
||||
/// and panics with "Could not automatically determine the process-level
|
||||
/// CryptoProvider". Installing one explicitly before any TLS use fixes it.
|
||||
///
|
||||
/// Idempotent (a second call is a no-op); harmless if some other component
|
||||
/// already installed a default (`install_default` then returns Err, ignored).
|
||||
pub fn ensure_crypto_provider() {
|
||||
use std::sync::Once;
|
||||
static INIT: Once = Once::new();
|
||||
INIT.call_once(|| {
|
||||
if rustls::crypto::aws_lc_rs::default_provider()
|
||||
.install_default()
|
||||
.is_err()
|
||||
{
|
||||
log::debug!("[cast] rustls CryptoProvider already installed");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -10,7 +10,7 @@ license = "MIT"
|
||||
tokio = { version = "1", features = ["sync", "time"] }
|
||||
|
||||
# HTTP client
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
|
||||
reqwest = { workspace = true, default-features = false, features = ["json", "rustls-tls-webpki-roots-no-provider"] }
|
||||
|
||||
# Serialization
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
+2
-11
@@ -8120,17 +8120,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Large/XL (and shrink RAM at Small). Set before any artwork job runs.
|
||||
crate::artwork::set_ui_scale_factor(ui_scale_factor);
|
||||
|
||||
// Install the rustls process-level CryptoProvider ONCE, before ANY TLS use.
|
||||
// The full binary compiles BOTH rustls providers (aws-lc-rs via qbz-cast's
|
||||
// rust_cast, ring via reqwest), so rustls cannot auto-select one and panics
|
||||
// ("Could not automatically determine the process-level CryptoProvider") the
|
||||
// first time a TLS connection opens. Previously this was only installed lazily
|
||||
// on the cast paths, so QConnect's tokio-tungstenite WebSocket (it opens a
|
||||
// rustls TLS channel on its own worker thread) panicked when the user joined a
|
||||
// session WITHOUT ever casting. Installing here at startup covers every TLS
|
||||
// consumer — QConnect, cast, reqwest — regardless of which connects first.
|
||||
// Idempotent (the cast paths still call it; the second call is a no-op).
|
||||
qbz_cast::ensure_crypto_provider();
|
||||
// Install the rustls process-level `CryptoProvider`
|
||||
qbz_app::ensure_crypto_provider();
|
||||
|
||||
let tokio_rt = tokio::runtime::Runtime::new()?;
|
||||
let _enter = tokio_rt.enter();
|
||||
|
||||
@@ -256,6 +256,9 @@ enum ConfigCmd { Path, Show { #[arg(long)] json: bool } }
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// Install the rustls process-level `CryptoProvider`
|
||||
qbz_app::ensure_crypto_provider();
|
||||
|
||||
let cli = Cli::parse();
|
||||
let code = match cli.cmd {
|
||||
Cmd::Version { json } => {
|
||||
|
||||
Reference in new issue
Block a user