mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
spirc: Don’t hardcode stuff
This commit is contained in:
parent
45491925de
commit
df11960946
4 changed files with 118 additions and 115 deletions
|
@ -13,11 +13,11 @@ message ClientResponseEncrypted {
|
||||||
|
|
||||||
message LoginCredentials {
|
message LoginCredentials {
|
||||||
optional string username = 0xa;
|
optional string username = 0xa;
|
||||||
required Type typ = 0x14;
|
required AuthenticationType typ = 0x14;
|
||||||
optional bytes auth_data = 0x1e;
|
optional bytes auth_data = 0x1e;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Type {
|
enum AuthenticationType {
|
||||||
AUTHENTICATION_USER_PASS = 0x0;
|
AUTHENTICATION_USER_PASS = 0x0;
|
||||||
AUTHENTICATION_STORED_SPOTIFY_CREDENTIALS = 0x1;
|
AUTHENTICATION_STORED_SPOTIFY_CREDENTIALS = 0x1;
|
||||||
AUTHENTICATION_STORED_FACEBOOK_CREDENTIALS = 0x2;
|
AUTHENTICATION_STORED_FACEBOOK_CREDENTIALS = 0x2;
|
||||||
|
@ -134,21 +134,31 @@ message ClientInfoFacebook {
|
||||||
optional string machine_id = 0x1;
|
optional string machine_id = 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AuthSuccess {
|
message APWelcome {
|
||||||
required string username = 0x0a;
|
required string canonical_username = 0xa;
|
||||||
required uint32 data1 = 0x14;
|
required AccountType account_type_logged_in = 0x14;
|
||||||
required uint32 data2 = 0x19;
|
required AccountType credentials_type_logged_in = 0x19;
|
||||||
required uint32 data3 = 0x1e;
|
required AuthenticationType reusable_auth_credentials_type = 0x1e;
|
||||||
required bytes data4 = 0x28;
|
required bytes reusable_auth_credentials = 0x28;
|
||||||
required bytes data5 = 0x32;
|
optional bytes lfs_secret = 0x32;
|
||||||
|
optional AccountInfo account_info = 0x3c;
|
||||||
|
optional AccountInfoFacebook fb = 0x46;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AuthFailure {
|
enum AccountType {
|
||||||
required uint32 code = 0x0a;
|
Spotify = 0x0;
|
||||||
required Data1 data1 = 0x32;
|
Facebook = 0x1;
|
||||||
|
|
||||||
message Data1 {
|
|
||||||
required string data0 = 0x01;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AccountInfo {
|
||||||
|
optional AccountInfoSpotify spotify = 0x1;
|
||||||
|
optional AccountInfoFacebook facebook = 0x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AccountInfoSpotify {
|
||||||
|
}
|
||||||
|
|
||||||
|
message AccountInfoFacebook {
|
||||||
|
optional string access_token = 0x1;
|
||||||
|
optional string machine_id = 0x2;
|
||||||
|
}
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
// size=80
|
|
||||||
message ClientHello {
|
message ClientHello {
|
||||||
required BuildInfo build_info = 0xa; // idx=0 offset=c
|
required BuildInfo build_info = 0xa;
|
||||||
repeated Fingerprint fingerprints_supported = 0x14; // idx=ffff offset=10
|
repeated Fingerprint fingerprints_supported = 0x14;
|
||||||
repeated Cryptosuite cryptosuites_supported = 0x1e; // idx=ffff offset=2c
|
repeated Cryptosuite cryptosuites_supported = 0x1e;
|
||||||
repeated Powscheme powschemes_supported = 0x28; // idx=ffff offset=48
|
repeated Powscheme powschemes_supported = 0x28;
|
||||||
required LoginCryptoHelloUnion login_crypto_hello = 0x32; // idx=1 offset=64
|
required LoginCryptoHelloUnion login_crypto_hello = 0x32;
|
||||||
required bytes client_nonce = 0x3c; // idx=2 offset=68 size=f
|
required bytes client_nonce = 0x3c;
|
||||||
optional bytes padding = 0x46; // idx=3 offset=78
|
optional bytes padding = 0x46;
|
||||||
optional FeatureSet feature_set = 0x50; // idx=4 offset=7c
|
optional FeatureSet feature_set = 0x50;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=38
|
|
||||||
message BuildInfo {
|
message BuildInfo {
|
||||||
required Product product = 0xa; // idx=0 offset=c
|
required Product product = 0xa;
|
||||||
repeated ProductFlags product_flags = 0x14; // idx=ffff offset=10
|
repeated ProductFlags product_flags = 0x14;
|
||||||
required Platform platform = 0x1e; // idx=1 offset=2c
|
required Platform platform = 0x1e;
|
||||||
required uint64 version = 0x28; // idx=2 offset=30 extra=246558
|
required uint64 version = 0x28;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Product {
|
enum Product {
|
||||||
|
@ -72,108 +72,101 @@ enum Powscheme {
|
||||||
POW_HASH_CASH = 0x0;
|
POW_HASH_CASH = 0x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=10
|
|
||||||
message LoginCryptoHelloUnion {
|
message LoginCryptoHelloUnion {
|
||||||
optional LoginCryptoDiffieHellmanHello diffie_hellman = 0xa; // idx=0 offset=c
|
optional LoginCryptoDiffieHellmanHello diffie_hellman = 0xa;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=70
|
|
||||||
message LoginCryptoDiffieHellmanHello {
|
message LoginCryptoDiffieHellmanHello {
|
||||||
required bytes gc = 0xa; // idx=0 offset=c size=5f
|
required bytes gc = 0xa;
|
||||||
required uint32 server_keys_known = 0x14; // idx=1 offset=6c
|
required uint32 server_keys_known = 0x14;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=10
|
|
||||||
message FeatureSet {
|
message FeatureSet {
|
||||||
optional bool autoupdate2 = 0x1; // idx=0 offset=c
|
optional bool autoupdate2 = 0x1;
|
||||||
optional bool current_location = 0x2; // idx=1 offset=d
|
optional bool current_location = 0x2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// size=18
|
|
||||||
message APResponseMessage {
|
message APResponseMessage {
|
||||||
optional APChallenge challenge = 0xa; // idx=0 offset=c
|
optional APChallenge challenge = 0xa;
|
||||||
optional UpgradeRequiredMessage upgrade = 0x14; // idx=1 offset=10
|
optional UpgradeRequiredMessage upgrade = 0x14;
|
||||||
optional APLoginFailed login_failed = 0x1e; // idx=2 offset=14
|
optional APLoginFailed login_failed = 0x1e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=30
|
|
||||||
message APChallenge {
|
message APChallenge {
|
||||||
required LoginCryptoChallengeUnion login_crypto_challenge = 0xa; // idx=0 offset=c
|
required LoginCryptoChallengeUnion login_crypto_challenge = 0xa;
|
||||||
required FingerprintChallengeUnion fingerprint_challenge = 0x14; // idx=1 offset=10
|
required FingerprintChallengeUnion fingerprint_challenge = 0x14;
|
||||||
required PoWChallengeUnion pow_challenge = 0x1e; // idx=2 offset=14
|
required PoWChallengeUnion pow_challenge = 0x1e;
|
||||||
required CryptoChallengeUnion crypto_challenge = 0x28; // idx=3 offset=18
|
required CryptoChallengeUnion crypto_challenge = 0x28;
|
||||||
required bytes server_nonce = 0x32; // idx=4 offset=1c size=f
|
required bytes server_nonce = 0x32;
|
||||||
optional bytes padding = 0x3c; // idx=5 offset=2c
|
optional bytes padding = 0x3c;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=10
|
|
||||||
message LoginCryptoChallengeUnion {
|
message LoginCryptoChallengeUnion {
|
||||||
optional LoginCryptoDiffieHellmanChallenge diffie_hellman = 0xa; // idx=0 offset=c
|
optional LoginCryptoDiffieHellmanChallenge diffie_hellman = 0xa;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=170
|
|
||||||
message LoginCryptoDiffieHellmanChallenge {
|
message LoginCryptoDiffieHellmanChallenge {
|
||||||
required bytes gs = 0xa; // idx=0 offset=c size=5f
|
required bytes gs = 0xa;
|
||||||
required int32 server_signature_key = 0x14; // idx=1 offset=6c type=int8
|
required int32 server_signature_key = 0x14;
|
||||||
required bytes gs_signature = 0x1e; // idx=2 offset=6d size=ff
|
required bytes gs_signature = 0x1e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=14
|
|
||||||
message FingerprintChallengeUnion {
|
message FingerprintChallengeUnion {
|
||||||
optional FingerprintGrainChallenge grain = 0xa; // idx=0 offset=c
|
optional FingerprintGrainChallenge grain = 0xa;
|
||||||
optional FingerprintHmacRipemdChallenge hmac_ripemd = 0x14; // idx=1 offset=10
|
optional FingerprintHmacRipemdChallenge hmac_ripemd = 0x14;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=1c
|
|
||||||
message FingerprintGrainChallenge {
|
message FingerprintGrainChallenge {
|
||||||
required bytes kek = 0xa; // idx=0 offset=c size=f
|
required bytes kek = 0xa;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=20
|
|
||||||
message FingerprintHmacRipemdChallenge {
|
message FingerprintHmacRipemdChallenge {
|
||||||
required bytes challenge = 0xa; // idx=0 offset=c size=13
|
required bytes challenge = 0xa;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=10
|
|
||||||
message PoWChallengeUnion {
|
message PoWChallengeUnion {
|
||||||
optional PoWHashCashChallenge hash_cash = 0xa; // idx=0 offset=c
|
optional PoWHashCashChallenge hash_cash = 0xa;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=24
|
|
||||||
message PoWHashCashChallenge {
|
message PoWHashCashChallenge {
|
||||||
optional bytes prefix = 0xa; // idx=0 offset=c size=f
|
optional bytes prefix = 0xa;
|
||||||
optional int32 length = 0x14; // idx=1 offset=1c type=int8
|
optional int32 length = 0x14;
|
||||||
optional int32 target = 0x1e; // idx=2 offset=20
|
optional int32 target = 0x1e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=14
|
|
||||||
message CryptoChallengeUnion {
|
message CryptoChallengeUnion {
|
||||||
optional CryptoShannonChallenge shannon = 0xa; // idx=0 offset=c
|
optional CryptoShannonChallenge shannon = 0xa;
|
||||||
optional CryptoRc4Sha1HmacChallenge rc4_sha1_hmac = 0x14; // idx=1 offset=10
|
optional CryptoRc4Sha1HmacChallenge rc4_sha1_hmac = 0x14;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=8
|
|
||||||
message CryptoShannonChallenge {
|
message CryptoShannonChallenge {
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=8
|
|
||||||
message CryptoRc4Sha1HmacChallenge {
|
message CryptoRc4Sha1HmacChallenge {
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=18
|
|
||||||
message UpgradeRequiredMessage {
|
message UpgradeRequiredMessage {
|
||||||
required bytes upgrade_signed_part = 0xa; // idx=0 offset=c
|
required bytes upgrade_signed_part = 0xa;
|
||||||
required bytes signature = 0x14; // idx=1 offset=10
|
required bytes signature = 0x14;
|
||||||
optional string http_suffix = 0x1e; // idx=2 offset=14
|
optional string http_suffix = 0x1e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=1c
|
|
||||||
message APLoginFailed {
|
message APLoginFailed {
|
||||||
required ErrorCode error_code = 0xa; // idx=0 offset=c
|
required ErrorCode error_code = 0xa;
|
||||||
optional int32 retry_delay = 0x14; // idx=1 offset=10
|
optional int32 retry_delay = 0x14;
|
||||||
optional int32 expiry = 0x1e; // idx=2 offset=14
|
optional int32 expiry = 0x1e;
|
||||||
optional string error_description = 0x28; // idx=3 offset=18
|
optional string error_description = 0x28;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ErrorCode {
|
enum ErrorCode {
|
||||||
|
@ -190,50 +183,45 @@ enum ErrorCode {
|
||||||
ApplicationBanned = 0x11;
|
ApplicationBanned = 0x11;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// size=18
|
|
||||||
message ClientResponsePlaintext {
|
message ClientResponsePlaintext {
|
||||||
required LoginCryptoResponseUnion login_crypto_response = 0xa; // idx=0 offset=c
|
required LoginCryptoResponseUnion login_crypto_response = 0xa;
|
||||||
required PoWResponseUnion pow_response = 0x14; // idx=1 offset=10
|
required PoWResponseUnion pow_response = 0x14;
|
||||||
required CryptoResponseUnion crypto_response = 0x1e; // idx=2 offset=14
|
required CryptoResponseUnion crypto_response = 0x1e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=10
|
|
||||||
message LoginCryptoResponseUnion {
|
message LoginCryptoResponseUnion {
|
||||||
optional LoginCryptoDiffieHellmanResponse diffie_hellman = 0xa; // idx=0 offset=c
|
optional LoginCryptoDiffieHellmanResponse diffie_hellman = 0xa;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=20
|
|
||||||
message LoginCryptoDiffieHellmanResponse {
|
message LoginCryptoDiffieHellmanResponse {
|
||||||
required bytes hmac = 0xa; // idx=0 offset=c size=13
|
required bytes hmac = 0xa;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=10
|
|
||||||
message PoWResponseUnion {
|
message PoWResponseUnion {
|
||||||
optional PoWHashCashResponse hash_cash = 0xa; // idx=0 offset=c
|
optional PoWHashCashResponse hash_cash = 0xa;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=1c
|
|
||||||
message PoWHashCashResponse {
|
message PoWHashCashResponse {
|
||||||
required bytes hash_suffix = 0xa; // idx=0 offset=c size=f
|
required bytes hash_suffix = 0xa;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=14
|
|
||||||
message CryptoResponseUnion {
|
message CryptoResponseUnion {
|
||||||
optional CryptoShannonResponse shannon = 0xa; // idx=0 offset=c
|
optional CryptoShannonResponse shannon = 0xa;
|
||||||
optional CryptoRc4Sha1HmacResponse rc4_sha1_hmac = 0x14; // idx=1 offset=10
|
optional CryptoRc4Sha1HmacResponse rc4_sha1_hmac = 0x14;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=10
|
|
||||||
message CryptoShannonResponse {
|
message CryptoShannonResponse {
|
||||||
optional int32 dummy = 0x1; // idx=0 offset=c type=uint8
|
optional int32 dummy = 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size=10
|
|
||||||
message CryptoRc4Sha1HmacResponse {
|
message CryptoRc4Sha1HmacResponse {
|
||||||
optional int32 dummy = 0x1; // idx=0 offset=c type=uint8
|
optional int32 dummy = 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -44,6 +44,7 @@ use protobuf::core::Message;
|
||||||
use metadata::{MetadataCache, AlbumRef, ArtistRef, TrackRef};
|
use metadata::{MetadataCache, AlbumRef, ArtistRef, TrackRef};
|
||||||
use session::{Config, Session};
|
use session::{Config, Session};
|
||||||
use util::SpotifyId;
|
use util::SpotifyId;
|
||||||
|
use util::version::version_string;
|
||||||
use player::Player;
|
use player::Player;
|
||||||
use mercury::{MercuryRequest, MercuryMethod};
|
use mercury::{MercuryRequest, MercuryMethod};
|
||||||
use librespot_protocol as protocol;
|
use librespot_protocol as protocol;
|
||||||
|
@ -53,28 +54,31 @@ fn main() {
|
||||||
let mut appkey_file = File::open(Path::new(&args.next().unwrap())).unwrap();
|
let mut appkey_file = File::open(Path::new(&args.next().unwrap())).unwrap();
|
||||||
let username = args.next().unwrap();
|
let username = args.next().unwrap();
|
||||||
let password = args.next().unwrap();
|
let password = args.next().unwrap();
|
||||||
|
let name = args.next().unwrap();
|
||||||
|
|
||||||
let mut appkey = Vec::new();
|
let mut appkey = Vec::new();
|
||||||
appkey_file.read_to_end(&mut appkey).unwrap();
|
appkey_file.read_to_end(&mut appkey).unwrap();
|
||||||
|
|
||||||
let config = Config {
|
let config = Config {
|
||||||
application_key: appkey,
|
application_key: appkey,
|
||||||
user_agent: "ABC".to_string(),
|
user_agent: version_string(),
|
||||||
device_id: "ABC".to_string()
|
device_id: name.to_string()
|
||||||
};
|
};
|
||||||
let session = Session::new(config);
|
let session = Session::new(config);
|
||||||
session.login(username, password);
|
session.login(username.clone(), password);
|
||||||
session.poll();
|
session.poll();
|
||||||
|
|
||||||
let ident = session.config.device_id.clone();
|
let ident = session.config.device_id.clone();
|
||||||
SpircManager{
|
SpircManager{
|
||||||
session: session,
|
session: session,
|
||||||
|
username: username.clone(),
|
||||||
|
name: name.clone(),
|
||||||
|
ident: ident,
|
||||||
|
device_type: 5,
|
||||||
|
|
||||||
state_update_id: 0,
|
state_update_id: 0,
|
||||||
seq_nr: 0,
|
seq_nr: 0,
|
||||||
|
|
||||||
name: "BlaBla".to_string(),
|
|
||||||
ident: ident,
|
|
||||||
device_type: 5,
|
|
||||||
volume: 0x8000,
|
volume: 0x8000,
|
||||||
can_play: true,
|
can_play: true,
|
||||||
is_active: false,
|
is_active: false,
|
||||||
|
@ -116,6 +120,7 @@ fn print_track(cache: &mut MetadataCache, track_id: SpotifyId) {
|
||||||
|
|
||||||
struct SpircManager {
|
struct SpircManager {
|
||||||
session: Session,
|
session: Session,
|
||||||
|
username: String,
|
||||||
state_update_id: i64,
|
state_update_id: i64,
|
||||||
seq_nr: u32,
|
seq_nr: u32,
|
||||||
|
|
||||||
|
@ -135,7 +140,7 @@ impl SpircManager {
|
||||||
|
|
||||||
self.session.mercury.send(MercuryRequest{
|
self.session.mercury.send(MercuryRequest{
|
||||||
method: MercuryMethod::SUB,
|
method: MercuryMethod::SUB,
|
||||||
uri: "hm://remote/user/lietar/v23".to_string(),
|
uri: format!("hm://remote/user/{}/v23", self.username).to_string(),
|
||||||
content_type: None,
|
content_type: None,
|
||||||
callback: Some(tx),
|
callback: Some(tx),
|
||||||
payload: Vec::new()
|
payload: Vec::new()
|
||||||
|
@ -185,7 +190,7 @@ impl SpircManager {
|
||||||
let device_state = self.device_state();
|
let device_state = self.device_state();
|
||||||
self.session.mercury.send(MercuryRequest{
|
self.session.mercury.send(MercuryRequest{
|
||||||
method: MercuryMethod::SEND,
|
method: MercuryMethod::SEND,
|
||||||
uri: "hm://remote/user/lietar".to_string(),
|
uri: format!("hm://remote/user/{}", self.username).to_string(),
|
||||||
content_type: None,
|
content_type: None,
|
||||||
callback: None,
|
callback: None,
|
||||||
payload: vec![
|
payload: vec![
|
||||||
|
@ -206,7 +211,7 @@ impl SpircManager {
|
||||||
|
|
||||||
fn device_state(&mut self) -> protocol::spirc::DeviceState {
|
fn device_state(&mut self) -> protocol::spirc::DeviceState {
|
||||||
protobuf_init!(protocol::spirc::DeviceState::new(), {
|
protobuf_init!(protocol::spirc::DeviceState::new(), {
|
||||||
sw_version: "librespot-0.1.0".to_string(),
|
sw_version: version_string(),
|
||||||
is_active: self.is_active,
|
is_active: self.is_active,
|
||||||
can_play: self.can_play,
|
can_play: self.can_play,
|
||||||
volume: self.volume as u32,
|
volume: self.volume as u32,
|
||||||
|
|
|
@ -147,7 +147,7 @@ impl Session {
|
||||||
let packet = protobuf_init!(protocol::authentication::ClientResponseEncrypted::new(), {
|
let packet = protobuf_init!(protocol::authentication::ClientResponseEncrypted::new(), {
|
||||||
login_credentials => {
|
login_credentials => {
|
||||||
username: username,
|
username: username,
|
||||||
typ: protocol::authentication::Type::AUTHENTICATION_USER_PASS,
|
typ: protocol::authentication::AuthenticationType::AUTHENTICATION_USER_PASS,
|
||||||
auth_data: password.into_bytes(),
|
auth_data: password.into_bytes(),
|
||||||
},
|
},
|
||||||
system_info => {
|
system_info => {
|
||||||
|
|
Loading…
Reference in a new issue