Browse Source

spirc: Don’t hardcode stuff

Paul Lietar 9 years ago
parent
commit
df11960946
4 changed files with 117 additions and 114 deletions
  1. 25 15
      protocol/proto/authentication.proto
  2. 77 89
      protocol/proto/keyexchange.proto
  3. 14 9
      src/main.rs
  4. 1 1
      src/session.rs

+ 25 - 15
protocol/proto/authentication.proto

@@ -13,11 +13,11 @@ message ClientResponseEncrypted {
 
 message LoginCredentials {
     optional string username = 0xa; 
-    required Type typ = 0x14; 
+    required AuthenticationType typ = 0x14; 
     optional bytes auth_data = 0x1e; 
 }
 
-enum Type {
+enum AuthenticationType {
     AUTHENTICATION_USER_PASS = 0x0;
     AUTHENTICATION_STORED_SPOTIFY_CREDENTIALS = 0x1;
     AUTHENTICATION_STORED_FACEBOOK_CREDENTIALS = 0x2;
@@ -134,21 +134,31 @@ message ClientInfoFacebook {
     optional string machine_id = 0x1; 
 }
 
-message AuthSuccess {
-    required string username = 0x0a;
-    required uint32 data1 = 0x14;
-    required uint32 data2 = 0x19;
-    required uint32 data3 = 0x1e;
-    required bytes  data4 = 0x28;
-    required bytes  data5 = 0x32;
+message APWelcome {
+    required string canonical_username = 0xa;
+    required AccountType account_type_logged_in = 0x14;
+    required AccountType credentials_type_logged_in = 0x19;
+    required AuthenticationType reusable_auth_credentials_type = 0x1e;
+    required bytes reusable_auth_credentials = 0x28;
+    optional bytes lfs_secret = 0x32; 
+    optional AccountInfo account_info = 0x3c;
+    optional AccountInfoFacebook fb = 0x46;
 }
 
-message AuthFailure {
-    required uint32 code = 0x0a;
-    required Data1 data1 = 0x32;
+enum AccountType {
+    Spotify = 0x0;
+    Facebook = 0x1;
+}
+
+message AccountInfo {
+    optional AccountInfoSpotify spotify = 0x1;
+    optional AccountInfoFacebook facebook = 0x2;
+}
 
-    message Data1 {
-        required string data0 = 0x01;
-    }
+message AccountInfoSpotify {
 }
 
+message AccountInfoFacebook {
+    optional string access_token = 0x1;
+    optional string machine_id = 0x2;
+}

+ 77 - 89
protocol/proto/keyexchange.proto

@@ -1,21 +1,21 @@
-//  size=80
+
 message ClientHello {
-    required BuildInfo build_info = 0xa; // idx=0 offset=c
-    repeated Fingerprint fingerprints_supported = 0x14; // idx=ffff offset=10
-    repeated Cryptosuite cryptosuites_supported = 0x1e; // idx=ffff offset=2c
-    repeated Powscheme powschemes_supported = 0x28; // idx=ffff offset=48
-    required LoginCryptoHelloUnion login_crypto_hello = 0x32; // idx=1 offset=64
-    required bytes client_nonce = 0x3c; // idx=2 offset=68 size=f
-    optional bytes padding = 0x46; // idx=3 offset=78
-    optional FeatureSet feature_set = 0x50; // idx=4 offset=7c
+    required BuildInfo build_info = 0xa; 
+    repeated Fingerprint fingerprints_supported = 0x14; 
+    repeated Cryptosuite cryptosuites_supported = 0x1e; 
+    repeated Powscheme powschemes_supported = 0x28; 
+    required LoginCryptoHelloUnion login_crypto_hello = 0x32; 
+    required bytes client_nonce = 0x3c; 
+    optional bytes padding = 0x46; 
+    optional FeatureSet feature_set = 0x50; 
 }
 
-//  size=38
+
 message BuildInfo {
-    required Product product = 0xa; // idx=0 offset=c
-    repeated ProductFlags product_flags = 0x14; // idx=ffff offset=10
-    required Platform platform = 0x1e; // idx=1 offset=2c
-    required uint64 version = 0x28; // idx=2 offset=30 extra=246558
+    required Product product = 0xa; 
+    repeated ProductFlags product_flags = 0x14; 
+    required Platform platform = 0x1e; 
+    required uint64 version = 0x28; 
 }
 
 enum Product {
@@ -72,108 +72,101 @@ enum Powscheme {
     POW_HASH_CASH = 0x0;
 }
 
-//  size=10
+
 message LoginCryptoHelloUnion {
-    optional LoginCryptoDiffieHellmanHello diffie_hellman = 0xa; // idx=0 offset=c
+    optional LoginCryptoDiffieHellmanHello diffie_hellman = 0xa; 
 }
 
-//  size=70
+
 message LoginCryptoDiffieHellmanHello {
-    required bytes gc = 0xa; // idx=0 offset=c size=5f
-    required uint32 server_keys_known = 0x14; // idx=1 offset=6c
+    required bytes gc = 0xa; 
+    required uint32 server_keys_known = 0x14; 
 }
 
-//  size=10
+
 message FeatureSet {
-    optional bool autoupdate2 = 0x1; // idx=0 offset=c
-    optional bool current_location = 0x2; // idx=1 offset=d
+    optional bool autoupdate2 = 0x1; 
+    optional bool current_location = 0x2; 
 }
 
 
-//  size=18
 message APResponseMessage {
-    optional APChallenge challenge = 0xa; // idx=0 offset=c
-    optional UpgradeRequiredMessage upgrade = 0x14; // idx=1 offset=10
-    optional APLoginFailed login_failed = 0x1e; // idx=2 offset=14
+    optional APChallenge challenge = 0xa; 
+    optional UpgradeRequiredMessage upgrade = 0x14; 
+    optional APLoginFailed login_failed = 0x1e; 
 }
 
-//  size=30
 message APChallenge {
-    required LoginCryptoChallengeUnion login_crypto_challenge = 0xa; // idx=0 offset=c
-    required FingerprintChallengeUnion fingerprint_challenge = 0x14; // idx=1 offset=10
-    required PoWChallengeUnion pow_challenge = 0x1e; // idx=2 offset=14
-    required CryptoChallengeUnion crypto_challenge = 0x28; // idx=3 offset=18
-    required bytes server_nonce = 0x32; // idx=4 offset=1c size=f
-    optional bytes padding = 0x3c; // idx=5 offset=2c
+    required LoginCryptoChallengeUnion login_crypto_challenge = 0xa; 
+    required FingerprintChallengeUnion fingerprint_challenge = 0x14; 
+    required PoWChallengeUnion pow_challenge = 0x1e; 
+    required CryptoChallengeUnion crypto_challenge = 0x28; 
+    required bytes server_nonce = 0x32; 
+    optional bytes padding = 0x3c; 
 }
 
-//  size=10
 message LoginCryptoChallengeUnion {
-    optional LoginCryptoDiffieHellmanChallenge diffie_hellman = 0xa; // idx=0 offset=c
+    optional LoginCryptoDiffieHellmanChallenge diffie_hellman = 0xa; 
 }
 
-//  size=170
 message LoginCryptoDiffieHellmanChallenge {
-    required bytes gs = 0xa; // idx=0 offset=c size=5f
-    required int32 server_signature_key = 0x14; // idx=1 offset=6c type=int8
-    required bytes gs_signature = 0x1e; // idx=2 offset=6d size=ff
+    required bytes gs = 0xa; 
+    required int32 server_signature_key = 0x14; 
+    required bytes gs_signature = 0x1e; 
 }
 
-//  size=14
 message FingerprintChallengeUnion {
-    optional FingerprintGrainChallenge grain = 0xa; // idx=0 offset=c
-    optional FingerprintHmacRipemdChallenge hmac_ripemd = 0x14; // idx=1 offset=10
+    optional FingerprintGrainChallenge grain = 0xa; 
+    optional FingerprintHmacRipemdChallenge hmac_ripemd = 0x14; 
 }
 
-//  size=1c
+
 message FingerprintGrainChallenge {
-    required bytes kek = 0xa; // idx=0 offset=c size=f
+    required bytes kek = 0xa; 
 }
 
-//  size=20
+
 message FingerprintHmacRipemdChallenge {
-    required bytes challenge = 0xa; // idx=0 offset=c size=13
+    required bytes challenge = 0xa; 
 }
 
-//  size=10
+
 message PoWChallengeUnion {
-    optional PoWHashCashChallenge hash_cash = 0xa; // idx=0 offset=c
+    optional PoWHashCashChallenge hash_cash = 0xa; 
 }
 
-//  size=24
 message PoWHashCashChallenge {
-    optional bytes prefix = 0xa; // idx=0 offset=c size=f
-    optional int32 length = 0x14; // idx=1 offset=1c type=int8
-    optional int32 target = 0x1e; // idx=2 offset=20
+    optional bytes prefix = 0xa; 
+    optional int32 length = 0x14; 
+    optional int32 target = 0x1e; 
 }
 
-//  size=14
+
 message CryptoChallengeUnion {
-    optional CryptoShannonChallenge shannon = 0xa; // idx=0 offset=c
-    optional CryptoRc4Sha1HmacChallenge rc4_sha1_hmac = 0x14; // idx=1 offset=10
+    optional CryptoShannonChallenge shannon = 0xa; 
+    optional CryptoRc4Sha1HmacChallenge rc4_sha1_hmac = 0x14; 
 }
 
-//  size=8
+
 message CryptoShannonChallenge {
 }
 
-//  size=8
+
 message CryptoRc4Sha1HmacChallenge {
 }
 
-//  size=18
+
 message UpgradeRequiredMessage {
-    required bytes upgrade_signed_part = 0xa; // idx=0 offset=c
-    required bytes signature = 0x14; // idx=1 offset=10
-    optional string http_suffix = 0x1e; // idx=2 offset=14
+    required bytes upgrade_signed_part = 0xa; 
+    required bytes signature = 0x14; 
+    optional string http_suffix = 0x1e; 
 }
 
-//  size=1c
 message APLoginFailed {
-    required ErrorCode error_code = 0xa; // idx=0 offset=c
-    optional int32 retry_delay = 0x14; // idx=1 offset=10
-    optional int32 expiry = 0x1e; // idx=2 offset=14
-    optional string error_description = 0x28; // idx=3 offset=18
+    required ErrorCode error_code = 0xa; 
+    optional int32 retry_delay = 0x14; 
+    optional int32 expiry = 0x1e; 
+    optional string error_description = 0x28; 
 }
 
 enum ErrorCode {
@@ -190,50 +183,45 @@ enum ErrorCode {
     ApplicationBanned = 0x11;
 }
 
-
-
-//  size=18
 message ClientResponsePlaintext {
-    required LoginCryptoResponseUnion login_crypto_response = 0xa; // idx=0 offset=c
-    required PoWResponseUnion pow_response = 0x14; // idx=1 offset=10
-    required CryptoResponseUnion crypto_response = 0x1e; // idx=2 offset=14
+    required LoginCryptoResponseUnion login_crypto_response = 0xa; 
+    required PoWResponseUnion pow_response = 0x14; 
+    required CryptoResponseUnion crypto_response = 0x1e; 
 }
 
-//  size=10
+
 message LoginCryptoResponseUnion {
-    optional LoginCryptoDiffieHellmanResponse diffie_hellman = 0xa; // idx=0 offset=c
+    optional LoginCryptoDiffieHellmanResponse diffie_hellman = 0xa; 
 }
 
-//  size=20
+
 message LoginCryptoDiffieHellmanResponse {
-    required bytes hmac = 0xa; // idx=0 offset=c size=13
+    required bytes hmac = 0xa; 
 }
 
-//  size=10
+
 message PoWResponseUnion {
-    optional PoWHashCashResponse hash_cash = 0xa; // idx=0 offset=c
+    optional PoWHashCashResponse hash_cash = 0xa; 
 }
 
-//  size=1c
+
 message PoWHashCashResponse {
-    required bytes hash_suffix = 0xa; // idx=0 offset=c size=f
+    required bytes hash_suffix = 0xa; 
 }
 
-//  size=14
+
 message CryptoResponseUnion {
-    optional CryptoShannonResponse shannon = 0xa; // idx=0 offset=c
-    optional CryptoRc4Sha1HmacResponse rc4_sha1_hmac = 0x14; // idx=1 offset=10
+    optional CryptoShannonResponse shannon = 0xa; 
+    optional CryptoRc4Sha1HmacResponse rc4_sha1_hmac = 0x14; 
 }
 
-//  size=10
+
 message CryptoShannonResponse {
-    optional int32 dummy = 0x1; // idx=0 offset=c type=uint8
+    optional int32 dummy = 0x1; 
 }
 
-//  size=10
+
 message CryptoRc4Sha1HmacResponse {
-    optional int32 dummy = 0x1; // idx=0 offset=c type=uint8
+    optional int32 dummy = 0x1; 
 }
 
-
-

+ 14 - 9
src/main.rs

@@ -44,6 +44,7 @@ use protobuf::core::Message;
 use metadata::{MetadataCache, AlbumRef, ArtistRef, TrackRef};
 use session::{Config, Session};
 use util::SpotifyId;
+use util::version::version_string;
 use player::Player;
 use mercury::{MercuryRequest, MercuryMethod};
 use librespot_protocol as protocol;
@@ -53,28 +54,31 @@ fn main() {
     let mut appkey_file = File::open(Path::new(&args.next().unwrap())).unwrap();
     let username = args.next().unwrap();
     let password = args.next().unwrap();
+    let name = args.next().unwrap();
 
     let mut appkey = Vec::new();
     appkey_file.read_to_end(&mut appkey).unwrap();
 
     let config = Config {
         application_key: appkey,
-        user_agent: "ABC".to_string(),
-        device_id: "ABC".to_string()
+        user_agent: version_string(),
+        device_id: name.to_string()
     };
     let session = Session::new(config);
-    session.login(username, password);
+    session.login(username.clone(), password);
     session.poll();
 
     let ident = session.config.device_id.clone();
     SpircManager{
         session: session,
+        username: username.clone(),
+        name: name.clone(),
+        ident: ident,
+        device_type: 5,
+
         state_update_id: 0,
         seq_nr: 0,
 
-        name: "BlaBla".to_string(),
-        ident: ident,
-        device_type: 5,
         volume: 0x8000,
         can_play: true,
         is_active: false,
@@ -116,6 +120,7 @@ fn print_track(cache: &mut MetadataCache, track_id: SpotifyId) {
 
 struct SpircManager {
     session: Session,
+    username: String,
     state_update_id: i64,
     seq_nr: u32,
 
@@ -135,7 +140,7 @@ impl SpircManager {
 
         self.session.mercury.send(MercuryRequest{
             method: MercuryMethod::SUB,
-            uri: "hm://remote/user/lietar/v23".to_string(),
+            uri: format!("hm://remote/user/{}/v23", self.username).to_string(),
             content_type: None,
             callback: Some(tx),
             payload: Vec::new()
@@ -185,7 +190,7 @@ impl SpircManager {
         let device_state = self.device_state();
         self.session.mercury.send(MercuryRequest{
             method: MercuryMethod::SEND,
-            uri: "hm://remote/user/lietar".to_string(),
+            uri: format!("hm://remote/user/{}", self.username).to_string(),
             content_type: None,
             callback: None,
             payload: vec![
@@ -206,7 +211,7 @@ impl SpircManager {
 
     fn device_state(&mut self) -> protocol::spirc::DeviceState {
         protobuf_init!(protocol::spirc::DeviceState::new(), {
-            sw_version: "librespot-0.1.0".to_string(),
+            sw_version: version_string(),
             is_active: self.is_active,
             can_play: self.can_play,
             volume: self.volume as u32,

+ 1 - 1
src/session.rs

@@ -147,7 +147,7 @@ impl Session {
         let packet = protobuf_init!(protocol::authentication::ClientResponseEncrypted::new(), {
             login_credentials => {
                 username: username,
-                typ: protocol::authentication::Type::AUTHENTICATION_USER_PASS,
+                typ: protocol::authentication::AuthenticationType::AUTHENTICATION_USER_PASS,
                 auth_data: password.into_bytes(),
             },
             system_info => {