From 25bd38fd13e7c3324b3baad90261e36aa2a13f50 Mon Sep 17 00:00:00 2001 From: Paul Lietar Date: Sun, 13 Mar 2016 20:03:09 +0000 Subject: [PATCH] Resolve access point when connecting and pick a random one. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spotify’s apresolve will return the best AP based on the user’s location. --- Cargo.lock | 113 ++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/apresolve.rs | 23 +++++++++ src/authentication.rs | 8 ++- src/connection.rs | 4 +- src/lib.in.rs | 1 + src/lib.rs | 1 + 7 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 src/apresolve.rs diff --git a/Cargo.lock b/Cargo.lock index 9b6c247e..eb5d0cff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,7 @@ dependencies = [ "dns-sd 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "eventual 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "json_macros 0.3.0 (git+https://github.com/plietar/json_macros)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "librespot-protocol 0.1.0", @@ -84,6 +85,15 @@ name = "chunked_transfer" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cookie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dns-sd" version = "0.1.3" @@ -170,6 +180,39 @@ name = "getopts" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "hpack" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "httparse" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hyper" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cookie 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "json_macros" version = "0.3.0" @@ -191,6 +234,11 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lazy_static" version = "0.1.15" @@ -227,6 +275,15 @@ name = "matches" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "mime" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num" version = "0.1.31" @@ -236,6 +293,14 @@ dependencies = [ "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num_cpus" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ogg-sys" version = "0.0.9" @@ -350,6 +415,27 @@ name = "rustc-serialize" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc_version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "shannon" version = "0.1.1" @@ -369,6 +455,15 @@ dependencies = [ "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "solicit" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syncbox" version = "0.2.4" @@ -450,6 +545,11 @@ dependencies = [ "url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "traitobject" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "tremor" version = "0.1.0" @@ -469,6 +569,19 @@ dependencies = [ "ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicase" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-bidi" version = "0.2.3" diff --git a/Cargo.toml b/Cargo.toml index 5af2f460..c9061c1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ bit-set = "~0.2.0" byteorder = "~0.4.2" eventual = "~0.1.5" getopts = "~0.2.14" +hyper = { version = "0.7.2", default-features = false } #json_macros = "~0.3.0" lazy_static = "~0.1.15" num = "~0.1.30" diff --git a/src/apresolve.rs b/src/apresolve.rs new file mode 100644 index 00000000..fd71d047 --- /dev/null +++ b/src/apresolve.rs @@ -0,0 +1,23 @@ +const APRESOLVE_ENDPOINT : &'static str = "http://apresolve.spotify.com/"; + +use hyper; +use std::io::Read; +use rustc_serialize::json; + +#[derive(RustcDecodable)] +pub struct APResolveData { + ap_list: Vec +} + +pub fn apresolve() -> Result, ()> { + let client = hyper::client::Client::new(); + let mut res = String::new(); + + client.get(APRESOLVE_ENDPOINT) + .send().unwrap() + .read_to_string(&mut res).unwrap(); + + let data : APResolveData = json::decode(&res).unwrap(); + + Ok(data.ap_list) +} diff --git a/src/authentication.rs b/src/authentication.rs index d27d7f9f..5a428508 100644 --- a/src/authentication.rs +++ b/src/authentication.rs @@ -1,3 +1,4 @@ +use apresolve::apresolve; use byteorder::{BigEndian, ByteOrder}; use crypto; use crypto::aes; @@ -8,6 +9,7 @@ use crypto::pbkdf2::pbkdf2; use crypto::sha1::Sha1; use protobuf::{self, Message, ProtobufEnum}; use rand::thread_rng; +use rand::Rng; use std::io::{self, Read, Write}; use std::result::Result; use rustc_serialize::base64::FromBase64; @@ -47,7 +49,11 @@ impl Session { pub fn connect(&self) -> CipherConnection { let local_keys = DHLocalKeys::random(&mut thread_rng()); - let mut connection = PlainConnection::connect().unwrap(); + let aps = apresolve().unwrap(); + let ap = thread_rng().choose(&aps).expect("No APs found"); + + println!("Connecting to AP {}", ap); + let mut connection = PlainConnection::connect(ap).unwrap(); let request = protobuf_init!(protocol::keyexchange::ClientHello::new(), { build_info => { diff --git a/src/connection.rs b/src/connection.rs index a81d73c8..f01164de 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -39,9 +39,9 @@ pub struct CipherConnection { } impl PlainConnection { - pub fn connect() -> Result { + pub fn connect(ap: &str) -> Result { Ok(PlainConnection { - stream: try!(TcpStream::connect("lon3-accesspoint-a26.ap.spotify.com:4070")), + stream: try!(TcpStream::connect(ap)), }) } diff --git a/src/lib.in.rs b/src/lib.in.rs index 693838f9..34320a01 100644 --- a/src/lib.in.rs +++ b/src/lib.in.rs @@ -13,4 +13,5 @@ pub mod session; pub mod spirc; pub mod link; mod stream; +pub mod apresolve; mod zeroconf; diff --git a/src/lib.rs b/src/lib.rs index 0f17c8c6..26c57966 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ extern crate bit_set; extern crate byteorder; extern crate crypto; extern crate eventual; +extern crate hyper; extern crate num; extern crate portaudio; extern crate protobuf;