mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Report actual CPU, OS, platform and librespot version
This commit is contained in:
parent
f3bb679ab1
commit
4f51c1e810
5 changed files with 95 additions and 12 deletions
|
@ -108,7 +108,7 @@ fn initial_state() -> State {
|
||||||
fn initial_device_state(config: ConnectConfig) -> DeviceState {
|
fn initial_device_state(config: ConnectConfig) -> DeviceState {
|
||||||
{
|
{
|
||||||
let mut msg = DeviceState::new();
|
let mut msg = DeviceState::new();
|
||||||
msg.set_sw_version(version::VERSION_STRING.to_string());
|
msg.set_sw_version(version::SEMVER.to_string());
|
||||||
msg.set_is_active(false);
|
msg.set_is_active(false);
|
||||||
msg.set_can_play(true);
|
msg.set_can_play(true);
|
||||||
msg.set_volume(0);
|
msg.set_volume(0);
|
||||||
|
|
|
@ -3,6 +3,7 @@ use hmac::{Hmac, Mac, NewMac};
|
||||||
use protobuf::{self, Message};
|
use protobuf::{self, Message};
|
||||||
use rand::{thread_rng, RngCore};
|
use rand::{thread_rng, RngCore};
|
||||||
use sha1::Sha1;
|
use sha1::Sha1;
|
||||||
|
use std::env::consts::ARCH;
|
||||||
use std::io;
|
use std::io;
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||||
use tokio_util::codec::{Decoder, Framed};
|
use tokio_util::codec::{Decoder, Framed};
|
||||||
|
@ -10,7 +11,9 @@ use tokio_util::codec::{Decoder, Framed};
|
||||||
use super::codec::ApCodec;
|
use super::codec::ApCodec;
|
||||||
use crate::diffie_hellman::DhLocalKeys;
|
use crate::diffie_hellman::DhLocalKeys;
|
||||||
use crate::protocol;
|
use crate::protocol;
|
||||||
use crate::protocol::keyexchange::{APResponseMessage, ClientHello, ClientResponsePlaintext};
|
use crate::protocol::keyexchange::{
|
||||||
|
APResponseMessage, ClientHello, ClientResponsePlaintext, Platform, ProductFlags,
|
||||||
|
};
|
||||||
|
|
||||||
pub async fn handshake<T: AsyncRead + AsyncWrite + Unpin>(
|
pub async fn handshake<T: AsyncRead + AsyncWrite + Unpin>(
|
||||||
mut connection: T,
|
mut connection: T,
|
||||||
|
@ -42,13 +45,51 @@ where
|
||||||
let mut client_nonce = vec![0; 0x10];
|
let mut client_nonce = vec![0; 0x10];
|
||||||
thread_rng().fill_bytes(&mut client_nonce);
|
thread_rng().fill_bytes(&mut client_nonce);
|
||||||
|
|
||||||
|
let platform = match std::env::consts::OS {
|
||||||
|
"android" => Platform::PLATFORM_ANDROID_ARM,
|
||||||
|
"freebsd" | "netbsd" | "openbsd" => match ARCH {
|
||||||
|
"x86_64" => Platform::PLATFORM_FREEBSD_X86_64,
|
||||||
|
_ => Platform::PLATFORM_FREEBSD_X86,
|
||||||
|
},
|
||||||
|
"ios" => match ARCH {
|
||||||
|
"arm64" => Platform::PLATFORM_IPHONE_ARM64,
|
||||||
|
_ => Platform::PLATFORM_IPHONE_ARM,
|
||||||
|
},
|
||||||
|
"linux" => match ARCH {
|
||||||
|
"arm" | "arm64" => Platform::PLATFORM_LINUX_ARM,
|
||||||
|
"blackfin" => Platform::PLATFORM_LINUX_BLACKFIN,
|
||||||
|
"mips" => Platform::PLATFORM_LINUX_MIPS,
|
||||||
|
"sh" => Platform::PLATFORM_LINUX_SH,
|
||||||
|
"x86_64" => Platform::PLATFORM_LINUX_X86_64,
|
||||||
|
_ => Platform::PLATFORM_LINUX_X86,
|
||||||
|
},
|
||||||
|
"macos" => match ARCH {
|
||||||
|
"ppc" | "ppc64" => Platform::PLATFORM_OSX_PPC,
|
||||||
|
"x86_64" => Platform::PLATFORM_OSX_X86_64,
|
||||||
|
_ => Platform::PLATFORM_OSX_X86,
|
||||||
|
},
|
||||||
|
"windows" => match ARCH {
|
||||||
|
"arm" => Platform::PLATFORM_WINDOWS_CE_ARM,
|
||||||
|
"x86_64" => Platform::PLATFORM_WIN32_X86_64,
|
||||||
|
_ => Platform::PLATFORM_WIN32_X86,
|
||||||
|
},
|
||||||
|
_ => Platform::PLATFORM_LINUX_X86,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
const PRODUCT_FLAGS: ProductFlags = ProductFlags::PRODUCT_FLAG_DEV_BUILD;
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
const PRODUCT_FLAGS: ProductFlags = ProductFlags::PRODUCT_FLAG_NONE;
|
||||||
|
|
||||||
let mut packet = ClientHello::new();
|
let mut packet = ClientHello::new();
|
||||||
packet
|
packet
|
||||||
.mut_build_info()
|
.mut_build_info()
|
||||||
.set_product(protocol::keyexchange::Product::PRODUCT_PARTNER);
|
.set_product(protocol::keyexchange::Product::PRODUCT_LIBSPOTIFY);
|
||||||
packet
|
packet
|
||||||
.mut_build_info()
|
.mut_build_info()
|
||||||
.set_platform(protocol::keyexchange::Platform::PLATFORM_LINUX_X86);
|
.mut_product_flags()
|
||||||
|
.push(PRODUCT_FLAGS);
|
||||||
|
packet.mut_build_info().set_platform(platform);
|
||||||
packet.mut_build_info().set_version(999999999);
|
packet.mut_build_info().set_version(999999999);
|
||||||
packet
|
packet
|
||||||
.mut_cryptosuites_supported()
|
.mut_cryptosuites_supported()
|
||||||
|
|
|
@ -71,6 +71,29 @@ pub async fn authenticate(
|
||||||
) -> Result<Credentials, AuthenticationError> {
|
) -> Result<Credentials, AuthenticationError> {
|
||||||
use crate::protocol::authentication::{APWelcome, ClientResponseEncrypted, CpuFamily, Os};
|
use crate::protocol::authentication::{APWelcome, ClientResponseEncrypted, CpuFamily, Os};
|
||||||
|
|
||||||
|
let cpu_family = match std::env::consts::ARCH {
|
||||||
|
"blackfin" => CpuFamily::CPU_BLACKFIN,
|
||||||
|
"arm" | "arm64" => CpuFamily::CPU_ARM,
|
||||||
|
"ia64" => CpuFamily::CPU_IA64,
|
||||||
|
"mips" => CpuFamily::CPU_MIPS,
|
||||||
|
"ppc" => CpuFamily::CPU_PPC,
|
||||||
|
"ppc64" => CpuFamily::CPU_PPC_64,
|
||||||
|
"sh" => CpuFamily::CPU_SH,
|
||||||
|
"x86" => CpuFamily::CPU_X86,
|
||||||
|
"x86_64" => CpuFamily::CPU_X86_64,
|
||||||
|
_ => CpuFamily::CPU_UNKNOWN,
|
||||||
|
};
|
||||||
|
|
||||||
|
let os = match std::env::consts::OS {
|
||||||
|
"android" => Os::OS_ANDROID,
|
||||||
|
"freebsd" | "netbsd" | "openbsd" => Os::OS_FREEBSD,
|
||||||
|
"ios" => Os::OS_IPHONE,
|
||||||
|
"linux" => Os::OS_LINUX,
|
||||||
|
"macos" => Os::OS_OSX,
|
||||||
|
"windows" => Os::OS_WINDOWS,
|
||||||
|
_ => Os::OS_UNKNOWN,
|
||||||
|
};
|
||||||
|
|
||||||
let mut packet = ClientResponseEncrypted::new();
|
let mut packet = ClientResponseEncrypted::new();
|
||||||
packet
|
packet
|
||||||
.mut_login_credentials()
|
.mut_login_credentials()
|
||||||
|
@ -81,21 +104,19 @@ pub async fn authenticate(
|
||||||
packet
|
packet
|
||||||
.mut_login_credentials()
|
.mut_login_credentials()
|
||||||
.set_auth_data(credentials.auth_data);
|
.set_auth_data(credentials.auth_data);
|
||||||
packet
|
packet.mut_system_info().set_cpu_family(cpu_family);
|
||||||
.mut_system_info()
|
packet.mut_system_info().set_os(os);
|
||||||
.set_cpu_family(CpuFamily::CPU_UNKNOWN);
|
|
||||||
packet.mut_system_info().set_os(Os::OS_UNKNOWN);
|
|
||||||
packet
|
packet
|
||||||
.mut_system_info()
|
.mut_system_info()
|
||||||
.set_system_information_string(format!(
|
.set_system_information_string(format!(
|
||||||
"librespot_{}_{}",
|
"librespot-{}-{}",
|
||||||
version::SHA_SHORT,
|
version::SHA_SHORT,
|
||||||
version::BUILD_ID
|
version::BUILD_ID
|
||||||
));
|
));
|
||||||
packet
|
packet
|
||||||
.mut_system_info()
|
.mut_system_info()
|
||||||
.set_device_id(device_id.to_string());
|
.set_device_id(device_id.to_string());
|
||||||
packet.set_version_string(version::VERSION_STRING.to_string());
|
packet.set_version_string(format!("librespot {}", version::SEMVER));
|
||||||
|
|
||||||
let cmd = PacketType::Login;
|
let cmd = PacketType::Login;
|
||||||
let data = packet.write_to_bytes().unwrap();
|
let data = packet.write_to_bytes().unwrap();
|
||||||
|
|
|
@ -5,9 +5,12 @@ use hyper::header::InvalidHeaderValue;
|
||||||
use hyper::{Body, Client, Request, Response, StatusCode};
|
use hyper::{Body, Client, Request, Response, StatusCode};
|
||||||
use hyper_proxy::{Intercept, Proxy, ProxyConnector};
|
use hyper_proxy::{Intercept, Proxy, ProxyConnector};
|
||||||
use hyper_rustls::HttpsConnector;
|
use hyper_rustls::HttpsConnector;
|
||||||
|
use std::env::consts::OS;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::version;
|
||||||
|
|
||||||
pub struct HttpClient {
|
pub struct HttpClient {
|
||||||
proxy: Option<Url>,
|
proxy: Option<Url>,
|
||||||
}
|
}
|
||||||
|
@ -50,11 +53,29 @@ impl HttpClient {
|
||||||
|
|
||||||
let connector = HttpsConnector::with_native_roots();
|
let connector = HttpsConnector::with_native_roots();
|
||||||
|
|
||||||
|
let spotify_version = match OS {
|
||||||
|
"android" | "ios" => "8.6.84",
|
||||||
|
_ => "117300517",
|
||||||
|
};
|
||||||
|
|
||||||
|
let spotify_platform = match OS {
|
||||||
|
"android" => "Android/31",
|
||||||
|
"ios" => "iOS/15.1.1",
|
||||||
|
"macos" => "OSX/0",
|
||||||
|
"windows" => "Win32/0",
|
||||||
|
_ => "Linux/0",
|
||||||
|
};
|
||||||
|
|
||||||
let headers_mut = req.headers_mut();
|
let headers_mut = req.headers_mut();
|
||||||
headers_mut.insert(
|
headers_mut.insert(
|
||||||
"User-Agent",
|
"User-Agent",
|
||||||
// Some features like lyrics are version-gated and require an official version string.
|
// Some features like lyrics are version-gated and require an official version string.
|
||||||
HeaderValue::from_str("Spotify/8.6.80 iOS/13.5 (iPhone11,2)")?,
|
HeaderValue::from_str(&format!(
|
||||||
|
"Spotify/{} {} ({})",
|
||||||
|
spotify_version,
|
||||||
|
spotify_platform,
|
||||||
|
version::VERSION_STRING
|
||||||
|
))?,
|
||||||
);
|
);
|
||||||
|
|
||||||
let response = if let Some(url) = &self.proxy {
|
let response = if let Some(url) = &self.proxy {
|
||||||
|
|
|
@ -57,7 +57,7 @@ impl RequestHandler {
|
||||||
"status": 101,
|
"status": 101,
|
||||||
"statusString": "ERROR-OK",
|
"statusString": "ERROR-OK",
|
||||||
"spotifyError": 0,
|
"spotifyError": 0,
|
||||||
"version": "2.7.1",
|
"version": crate::core::version::SEMVER,
|
||||||
"deviceID": (self.config.device_id),
|
"deviceID": (self.config.device_id),
|
||||||
"remoteName": (self.config.name),
|
"remoteName": (self.config.name),
|
||||||
"activeUser": "",
|
"activeUser": "",
|
||||||
|
|
Loading…
Reference in a new issue