Resolve access point when connecting and pick a random one.

Spotify’s apresolve will return the best AP based on the user’s location.
This commit is contained in:
Paul Lietar 2016-03-13 20:03:09 +00:00
parent 60db12ee9e
commit 25bd38fd13
7 changed files with 148 additions and 3 deletions

113
Cargo.lock generated
View file

@ -7,6 +7,7 @@ dependencies = [
"dns-sd 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"librespot-protocol 0.1.0", "librespot-protocol 0.1.0",
@ -84,6 +85,15 @@ name = "chunked_transfer"
version = "0.3.1" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "dns-sd" name = "dns-sd"
version = "0.1.3" version = "0.1.3"
@ -170,6 +180,39 @@ name = "getopts"
version = "0.2.14" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "json_macros" name = "json_macros"
version = "0.3.0" version = "0.3.0"
@ -191,6 +234,11 @@ dependencies = [
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "0.1.15" version = "0.1.15"
@ -227,6 +275,15 @@ name = "matches"
version = "0.1.2" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "num" name = "num"
version = "0.1.31" version = "0.1.31"
@ -236,6 +293,14 @@ dependencies = [
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "ogg-sys" name = "ogg-sys"
version = "0.0.9" version = "0.0.9"
@ -350,6 +415,27 @@ name = "rustc-serialize"
version = "0.3.18" version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "shannon" name = "shannon"
version = "0.1.1" version = "0.1.1"
@ -369,6 +455,15 @@ dependencies = [
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "syncbox" name = "syncbox"
version = "0.2.4" version = "0.2.4"
@ -450,6 +545,11 @@ dependencies = [
"url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "tremor" name = "tremor"
version = "0.1.0" version = "0.1.0"
@ -469,6 +569,19 @@ dependencies = [
"ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
version = "0.2.3" version = "0.2.3"

View file

@ -20,6 +20,7 @@ bit-set = "~0.2.0"
byteorder = "~0.4.2" byteorder = "~0.4.2"
eventual = "~0.1.5" eventual = "~0.1.5"
getopts = "~0.2.14" getopts = "~0.2.14"
hyper = { version = "0.7.2", default-features = false }
#json_macros = "~0.3.0" #json_macros = "~0.3.0"
lazy_static = "~0.1.15" lazy_static = "~0.1.15"
num = "~0.1.30" num = "~0.1.30"

23
src/apresolve.rs Normal file
View file

@ -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<String>
}
pub fn apresolve() -> Result<Vec<String>, ()> {
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)
}

View file

@ -1,3 +1,4 @@
use apresolve::apresolve;
use byteorder::{BigEndian, ByteOrder}; use byteorder::{BigEndian, ByteOrder};
use crypto; use crypto;
use crypto::aes; use crypto::aes;
@ -8,6 +9,7 @@ use crypto::pbkdf2::pbkdf2;
use crypto::sha1::Sha1; use crypto::sha1::Sha1;
use protobuf::{self, Message, ProtobufEnum}; use protobuf::{self, Message, ProtobufEnum};
use rand::thread_rng; use rand::thread_rng;
use rand::Rng;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::result::Result; use std::result::Result;
use rustc_serialize::base64::FromBase64; use rustc_serialize::base64::FromBase64;
@ -47,7 +49,11 @@ impl Session {
pub fn connect(&self) -> CipherConnection { pub fn connect(&self) -> CipherConnection {
let local_keys = DHLocalKeys::random(&mut thread_rng()); 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(), { let request = protobuf_init!(protocol::keyexchange::ClientHello::new(), {
build_info => { build_info => {

View file

@ -39,9 +39,9 @@ pub struct CipherConnection {
} }
impl PlainConnection { impl PlainConnection {
pub fn connect() -> Result<PlainConnection> { pub fn connect(ap: &str) -> Result<PlainConnection> {
Ok(PlainConnection { Ok(PlainConnection {
stream: try!(TcpStream::connect("lon3-accesspoint-a26.ap.spotify.com:4070")), stream: try!(TcpStream::connect(ap)),
}) })
} }

View file

@ -13,4 +13,5 @@ pub mod session;
pub mod spirc; pub mod spirc;
pub mod link; pub mod link;
mod stream; mod stream;
pub mod apresolve;
mod zeroconf; mod zeroconf;

View file

@ -11,6 +11,7 @@ extern crate bit_set;
extern crate byteorder; extern crate byteorder;
extern crate crypto; extern crate crypto;
extern crate eventual; extern crate eventual;
extern crate hyper;
extern crate num; extern crate num;
extern crate portaudio; extern crate portaudio;
extern crate protobuf; extern crate protobuf;