qbzd: install the rustls process-level CryptoProvider
The rustls crypto provider was not installed for `qbzd`, which caused the process to panic: > thread 'tokio-rt-worker' (15737) panicked at [...]/rustls-0.23.37/src/crypto/mod.rs:249:14: > > Could not automatically determine the process-level CryptoProvider from > Rustls crate features. > Call CryptoProvider::install_default() before this point to select a > provider manually, or make sure exactly one of the 'aws-lc-rs' and 'ring' > features is enabled. > See the documentation of the CryptoProvider type for more information. The function `ensure_crypto_provider()` was defined in the `qbz-cast` crate which is obviously not a dependency of `qbzd`. This commit moves `ensure_crypto_provider()` to `qbz-app`, calls it from `qbzd` and updates `qbz` accordingly.
This commit is contained in:
1 parent
6fff4aae31
commit
a01097708e
9 files changed
+26
-46
No files matched your search
Generated
+1
-1
@@ -5943,6 +5943,7 @@ dependencies = [
|
||||
"rand 0.10.1",
|
||||
"reqwest",
|
||||
"rusqlite",
|
||||
"rustls",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
@@ -5998,7 +5999,6 @@ dependencies = [
|
||||
"mdns-sd",
|
||||
"rupnp",
|
||||
"rust_cast",
|
||||
"rustls",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.18",
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
});
|
||||
}
|
||||
+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