fix(cast): install rustls CryptoProvider before TLS connect
rust_cast opens a rustls TLS channel to the Chromecast. In the full 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 the worker thread panicked with "Could not automatically determine the process-level CryptoProvider" — surfacing as "Connection error: Thread response error". Add qbz_cast::ensure_crypto_provider() (installs aws-lc-rs once, idempotent) and call it at the top of ChromecastHandle::connect and DlnaConnection::connect. cc
This commit is contained in:
5 files changed
+36
No files matched your search
Generated
+1
@@ -5451,6 +5451,7 @@ dependencies = [
|
|||||||
"mdns-sd",
|
"mdns-sd",
|
||||||
"rupnp",
|
"rupnp",
|
||||||
"rust_cast",
|
"rust_cast",
|
||||||
|
"rustls",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ description = "Casting support for QBZ - Chromecast, DLNA"
|
|||||||
# Chromecast
|
# Chromecast
|
||||||
rust_cast = "0.21"
|
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 discovery
|
||||||
mdns-sd = "0.11"
|
mdns-sd = "0.11"
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ impl ChromecastHandle {
|
|||||||
|
|
||||||
/// Connect to a Chromecast device
|
/// Connect to a Chromecast device
|
||||||
pub fn connect(&self, ip: String, port: u16) -> Result<(), CastError> {
|
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();
|
let (reply_tx, reply_rx) = mpsc::channel();
|
||||||
self.sender
|
self.sender
|
||||||
.send(CastCommand::Connect {
|
.send(CastCommand::Connect {
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ pub struct DlnaConnection {
|
|||||||
impl DlnaConnection {
|
impl DlnaConnection {
|
||||||
/// Connect to a DLNA device and discover service URLs
|
/// Connect to a DLNA device and discover service URLs
|
||||||
pub async fn connect(device: DiscoveredDlnaDevice) -> Result<Self, DlnaError> {
|
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
|
let device_url: Uri = device
|
||||||
.url
|
.url
|
||||||
.parse()
|
.parse()
|
||||||
|
|||||||
@@ -37,3 +37,26 @@ pub use dlna::{
|
|||||||
|
|
||||||
/// Cast device type alias for backwards compatibility
|
/// Cast device type alias for backwards compatibility
|
||||||
pub type CastDevice = CastDeviceConnection;
|
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");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in new issue
Block a user