1
0
Fork 0
mirror of https://github.com/librespot-org/librespot.git synced 2025-10-03 01:39:28 +02:00

feat: add configurable TLS backend selection with native-tls as default (#1541)

Add support for choosing between native-tls and rustls-tls backends
through feature flags, with native-tls as the default for maximum
platform compatibility.

Key changes:
- Add mutually exclusive native-tls and rustls-tls feature flags
- Use conditional compilation to select TLS implementation
- Configure rustls-tls with platform certificate verifier
- Refactor to workspace-based dependency management
- Update CI workflows with improved cross-compilation support
- Add comprehensive TLS backend documentation

The native-tls backend uses system TLS libraries (OpenSSL on Linux,
Secure Transport on macOS, SChannel on Windows) while rustls-tls
provides a pure Rust implementation with platform certificate stores.
This commit is contained in:
Roderick van Domburg 2025-08-19 23:06:28 +02:00 committed by GitHub
parent 03bcdc6bda
commit 0a4969ffe2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 928 additions and 577 deletions

View file

@ -1,27 +1,43 @@
[package]
name = "librespot-core"
version = "0.6.0-dev"
version.workspace = true
rust-version.workspace = true
authors = ["Paul Lietar <paul@lietar.net>"]
build = "build.rs"
license.workspace = true
description = "The core functionality provided by librespot"
license = "MIT"
repository = "https://github.com/librespot-org/librespot"
edition = "2021"
repository.workspace = true
edition.workspace = true
build = "build.rs"
[dependencies.librespot-oauth]
path = "../oauth"
version = "0.6.0-dev"
[features]
# Refer to the workspace Cargo.toml for the list of features
default = ["native-tls"]
[dependencies.librespot-protocol]
path = "../protocol"
version = "0.6.0-dev"
# TLS backends (mutually exclusive - see oauth/src/lib.rs for compile-time checks)
# Note: Validation is in oauth since it's compiled first in the dependency tree.
native-tls = [
"dep:hyper-tls",
"hyper-proxy2/tls",
"librespot-oauth/native-tls",
"tokio-tungstenite/native-tls",
]
rustls-tls = [
"dep:hyper-rustls",
"hyper-proxy2/rustls",
"librespot-oauth/rustls-tls",
"tokio-tungstenite/__rustls-tls",
]
[dependencies]
librespot-oauth.workspace = true
librespot-protocol.workspace = true
aes = "0.8"
base64 = "0.22"
byteorder = "1.5"
bytes = "1"
data-encoding = "2.9"
flate2 = "1.1"
form_urlencoded = "1.2"
futures-core = "0.3"
futures-util = { version = "0.3", features = [
@ -37,9 +53,22 @@ governor = { version = "0.10", default-features = false, features = [
hmac = "0.12"
httparse = "1.10"
http = "1.3"
hyper = { version = "1.6", features = ["http1", "http2"] }
hyper-util = { version = "0.1", features = ["client"] }
http-body-util = "0.1"
hyper = { version = "1.6", features = ["http1", "http2"] }
hyper-proxy2 = { version = "0.1", default-features = false }
hyper-rustls = { version = "0.27", default-features = false, features = [
"http1",
"http2",
"ring",
"rustls-platform-verifier",
"tls12",
], optional = true }
hyper-tls = { version = "0.6", optional = true }
hyper-util = { version = "0.1", default-features = false, features = [
"client",
"http1",
"http2",
] }
log = "0.4"
nonzero_ext = "0.3"
num-bigint = "0.4"
@ -51,6 +80,7 @@ pbkdf2 = { version = "0.12", default-features = false, features = ["hmac"] }
pin-project-lite = "0.2"
priority-queue = "2.5"
protobuf = "3.7"
protobuf-json-mapping = "3.7"
quick-xml = { version = "0.38", features = ["serialize"] }
rand = "0.9"
rsa = "0.9"
@ -71,28 +101,10 @@ tokio = { version = "1", features = [
"time",
] }
tokio-stream = "0.1"
tokio-tungstenite = { version = "0.27", default-features = false }
tokio-util = { version = "0.7", features = ["codec"] }
url = "2"
uuid = { version = "1", default-features = false, features = ["v4"] }
data-encoding = "2.9"
flate2 = "1.1"
protobuf-json-mapping = "3.7"
rustls = { version = "0.23", default-features = false, features = ["ring"] }
hyper-proxy2 = { version = "0.1", default-features = false, features = [
"rustls-webpki",
] }
hyper-rustls = { version = "0.27", default-features = false, features = [
"ring",
"http1",
"logging",
"tls12",
"webpki-tokio",
"http2",
] }
tokio-tungstenite = { version = "0.27", default-features = false, features = [
"rustls-tls-webpki-roots",
] }
[build-dependencies]
rand = "0.9"

View file

@ -13,7 +13,6 @@ use http::{Uri, header::HeaderValue};
use http_body_util::{BodyExt, Full};
use hyper::{HeaderMap, Request, Response, StatusCode, body::Incoming, header::USER_AGENT};
use hyper_proxy2::{Intercept, Proxy, ProxyConnector};
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
use hyper_util::{
client::legacy::{Client, ResponseFuture, connect::HttpConnector},
rt::TokioExecutor,
@ -23,6 +22,11 @@ use parking_lot::Mutex;
use thiserror::Error;
use url::Url;
#[cfg(all(feature = "rustls-tls", not(feature = "native-tls")))]
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
#[cfg(all(feature = "native-tls", not(feature = "rustls-tls")))]
use hyper_tls::HttpsConnector;
use crate::{
Error,
config::{OS, os_version},
@ -145,14 +149,15 @@ impl HttpClient {
fn try_create_hyper_client(proxy_url: Option<&Url>) -> Result<HyperClient, Error> {
// configuring TLS is expensive and should be done once per process
let _ = rustls::crypto::ring::default_provider()
.install_default()
.map_err(|e| {
Error::internal(format!("unable to install default crypto provider: {e:?}"))
});
let tls = HttpsConnectorBuilder::new().with_webpki_roots();
let https_connector = tls.https_or_http().enable_http1().enable_http2().build();
#[cfg(all(feature = "rustls-tls", not(feature = "native-tls")))]
let https_connector = {
let tls = HttpsConnectorBuilder::new().with_platform_verifier();
tls.https_or_http().enable_http1().enable_http2().build()
};
#[cfg(all(feature = "native-tls", not(feature = "rustls-tls")))]
let https_connector = HttpsConnector::new();
// When not using a proxy a dummy proxy is configured that will not intercept any traffic.
// This prevents needing to carry the Client Connector generics through the whole project