diff --git a/core/build.rs b/core/build.rs index 5a2e5db8..d57d57a9 100644 --- a/core/build.rs +++ b/core/build.rs @@ -1,36 +1,35 @@ -extern crate vergen; extern crate protobuf_macros; extern crate rand; +extern crate vergen; use rand::Rng; use std::env; -use std::path::PathBuf; use std::fs::OpenOptions; use std::io::Write; +use std::path::PathBuf; fn main() { let out = PathBuf::from(env::var("OUT_DIR").unwrap()); vergen::vergen(vergen::OutputFns::all()).unwrap(); - let build_id: String = rand::thread_rng() - .gen_ascii_chars() - .take(8) - .collect(); + let build_id: String = rand::thread_rng().gen_ascii_chars().take(8).collect(); - let mut version_file = - OpenOptions::new() + let mut version_file = OpenOptions::new() .write(true) .append(true) .open(&out.join("version.rs")) .unwrap(); - let build_id_fn = format!(" + let build_id_fn = format!( + " /// Generate a random build id. pub fn build_id() -> &'static str {{ \"{}\" }} -", build_id); +", + build_id + ); if let Err(e) = version_file.write_all(build_id_fn.as_bytes()) { println!("{}", e); diff --git a/core/src/apresolve.rs b/core/src/apresolve.rs index bf3ba276..8db9a5ed 100644 --- a/core/src/apresolve.rs +++ b/core/src/apresolve.rs @@ -1,20 +1,20 @@ -const AP_FALLBACK : &'static str = "ap.spotify.com:80"; -const APRESOLVE_ENDPOINT : &'static str = "http://apresolve.spotify.com/"; +const AP_FALLBACK: &'static str = "ap.spotify.com:80"; +const APRESOLVE_ENDPOINT: &'static str = "http://apresolve.spotify.com/"; -use std::str::FromStr; use futures::{Future, Stream}; -use hyper::{self, Uri, Client}; +use hyper::{self, Client, Uri}; use serde_json; +use std::str::FromStr; use tokio_core::reactor::Handle; -error_chain! { } +error_chain!{} #[derive(Clone, Debug, Serialize, Deserialize)] pub struct APResolveData { - ap_list: Vec + ap_list: Vec, } -fn apresolve(handle: &Handle) -> Box> { +fn apresolve(handle: &Handle) -> Box> { let url = Uri::from_str(APRESOLVE_ENDPOINT).expect("invalid AP resolve URL"); let client = Client::new(handle); @@ -27,14 +27,10 @@ fn apresolve(handle: &Handle) -> Box> { }) }); let body = body.then(|result| result.chain_err(|| "HTTP error")); - let body = body.and_then(|body| { - String::from_utf8(body).chain_err(|| "invalid UTF8 in response") - }); + let body = body.and_then(|body| String::from_utf8(body).chain_err(|| "invalid UTF8 in response")); - let data = body.and_then(|body| { - serde_json::from_str::(&body) - .chain_err(|| "invalid JSON") - }); + let data = + body.and_then(|body| serde_json::from_str::(&body).chain_err(|| "invalid JSON")); let ap = data.and_then(|data| { let ap = data.ap_list.first().ok_or("empty AP List")?; @@ -44,9 +40,10 @@ fn apresolve(handle: &Handle) -> Box> { Box::new(ap) } -pub(crate) fn apresolve_or_fallback(handle: &Handle) - -> Box> - where E: 'static { +pub(crate) fn apresolve_or_fallback(handle: &Handle) -> Box> +where + E: 'static, +{ let ap = apresolve(handle).or_else(|e| { warn!("Failed to resolve Access Point: {}", e.description()); warn!("Using fallback \"{}\"", AP_FALLBACK); diff --git a/core/src/audio_key.rs b/core/src/audio_key.rs index a7a85896..2d4fb2ab 100644 --- a/core/src/audio_key.rs +++ b/core/src/audio_key.rs @@ -1,17 +1,17 @@ use byteorder::{BigEndian, ByteOrder, WriteBytesExt}; use bytes::Bytes; -use futures::sync::oneshot; use futures::{Async, Future, Poll}; +use futures::sync::oneshot; use std::collections::HashMap; use std::io::Write; +use util::{FileId, SpotifyId}; use util::SeqGenerator; -use util::{SpotifyId, FileId}; -#[derive(Debug,Hash,PartialEq,Eq,Copy,Clone)] +#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)] pub struct AudioKey(pub [u8; 16]); -#[derive(Debug,Hash,PartialEq,Eq,Copy,Clone)] +#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)] pub struct AudioKeyError; component! { @@ -35,7 +35,11 @@ impl AudioKeyManager { let _ = sender.send(Ok(AudioKey(key))); } 0xe => { - warn!("error audio key {:x} {:x}", data.as_ref()[0], data.as_ref()[1]); + warn!( + "error audio key {:x} {:x}", + data.as_ref()[0], + data.as_ref()[1] + ); let _ = sender.send(Err(AudioKeyError)); } _ => (), @@ -68,7 +72,7 @@ impl AudioKeyManager { } pub struct AudioKeyFuture(oneshot::Receiver>); -impl Future for AudioKeyFuture { +impl Future for AudioKeyFuture { type Item = T; type Error = AudioKeyError; @@ -81,4 +85,3 @@ impl Future for AudioKeyFuture { } } } - diff --git a/core/src/authentication.rs b/core/src/authentication.rs index f441a7fd..c079d543 100644 --- a/core/src/authentication.rs +++ b/core/src/authentication.rs @@ -10,23 +10,22 @@ use protobuf::ProtobufEnum; use rpassword; use serde; use serde_json; -use std::io::{self, stderr, Read, Write}; use std::fs::File; +use std::io::{self, stderr, Read, Write}; use std::path::Path; use protocol::authentication::AuthenticationType; -#[derive(Debug, Clone)] -#[derive(Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Credentials { pub username: String, - #[serde(serialize_with="serialize_protobuf_enum")] - #[serde(deserialize_with="deserialize_protobuf_enum")] + #[serde(serialize_with = "serialize_protobuf_enum")] + #[serde(deserialize_with = "deserialize_protobuf_enum")] pub auth_type: AuthenticationType, - #[serde(serialize_with="serialize_base64")] - #[serde(deserialize_with="deserialize_base64")] + #[serde(serialize_with = "serialize_base64")] + #[serde(deserialize_with = "deserialize_base64")] pub auth_data: Vec, } @@ -89,13 +88,18 @@ impl Credentials { let blob = { // Anyone know what this block mode is ? let mut data = vec![0u8; encrypted_blob.len()]; - let mut cipher = aes::ecb_decryptor(aes::KeySize::KeySize192, - &key, - crypto::blockmodes::NoPadding); - cipher.decrypt(&mut crypto::buffer::RefReadBuffer::new(&encrypted_blob), - &mut crypto::buffer::RefWriteBuffer::new(&mut data), - true) - .unwrap(); + let mut cipher = aes::ecb_decryptor( + aes::KeySize::KeySize192, + &key, + crypto::blockmodes::NoPadding, + ); + cipher + .decrypt( + &mut crypto::buffer::RefReadBuffer::new(&encrypted_blob), + &mut crypto::buffer::RefWriteBuffer::new(&mut data), + true, + ) + .unwrap(); let l = encrypted_blob.len(); for i in 0..l - 0x10 { @@ -112,7 +116,7 @@ impl Credentials { let auth_type = read_int(&mut cursor).unwrap(); let auth_type = AuthenticationType::from_i32(auth_type as i32).unwrap(); read_u8(&mut cursor).unwrap(); - let auth_data = read_bytes(&mut cursor).unwrap();; + let auth_data = read_bytes(&mut cursor).unwrap(); Credentials { username: username, @@ -144,42 +148,49 @@ impl Credentials { } fn serialize_protobuf_enum(v: &T, ser: S) -> Result - where T: ProtobufEnum, S: serde::Serializer { - +where + T: ProtobufEnum, + S: serde::Serializer, +{ serde::Serialize::serialize(&v.value(), ser) } fn deserialize_protobuf_enum(de: D) -> Result - where T: ProtobufEnum, D: serde::Deserializer { - - let v : i32 = try!(serde::Deserialize::deserialize(de)); +where + T: ProtobufEnum, + D: serde::Deserializer, +{ + let v: i32 = try!(serde::Deserialize::deserialize(de)); T::from_i32(v).ok_or_else(|| serde::de::Error::custom("Invalid enum value")) } fn serialize_base64(v: &T, ser: S) -> Result - where T: AsRef<[u8]>, S: serde::Serializer { - +where + T: AsRef<[u8]>, + S: serde::Serializer, +{ serde::Serialize::serialize(&base64::encode(v.as_ref()), ser) } fn deserialize_base64(de: D) -> Result, D::Error> - where D: serde::Deserializer { - - let v : String = try!(serde::Deserialize::deserialize(de)); +where + D: serde::Deserializer, +{ + let v: String = try!(serde::Deserialize::deserialize(de)); base64::decode(&v).map_err(|e| serde::de::Error::custom(e.to_string())) } -pub fn get_credentials(username: Option, password: Option, - cached_credentials: Option) - -> Option -{ +pub fn get_credentials( + username: Option, + password: Option, + cached_credentials: Option, +) -> Option { match (username, password, cached_credentials) { + (Some(username), Some(password), _) => Some(Credentials::with_password(username, password)), - (Some(username), Some(password), _) - => Some(Credentials::with_password(username, password)), - - (Some(ref username), _, Some(ref credentials)) - if *username == credentials.username => Some(credentials.clone()), + (Some(ref username), _, Some(ref credentials)) if *username == credentials.username => { + Some(credentials.clone()) + } (Some(username), None, _) => { write!(stderr(), "Password for {}: ", username).unwrap(); @@ -188,8 +199,7 @@ pub fn get_credentials(username: Option, password: Option, Some(Credentials::with_password(username.clone(), password)) } - (None, _, Some(credentials)) - => Some(credentials), + (None, _, Some(credentials)) => Some(credentials), (None, _, None) => None, } diff --git a/core/src/cache.rs b/core/src/cache.rs index 1a58bdc0..fb59c729 100644 --- a/core/src/cache.rs +++ b/core/src/cache.rs @@ -5,8 +5,8 @@ use std::io::Read; use std::path::Path; use std::path::PathBuf; -use util::FileId; use authentication::Credentials; +use util::FileId; #[derive(Clone)] pub struct Cache { @@ -31,7 +31,7 @@ impl Cache { Cache { root: location, - use_audio_cache: use_audio_cache + use_audio_cache: use_audio_cache, } } } diff --git a/core/src/channel.rs b/core/src/channel.rs index 19f880e7..112e6ad4 100644 --- a/core/src/channel.rs +++ b/core/src/channel.rs @@ -1,7 +1,7 @@ use byteorder::{BigEndian, ByteOrder}; use bytes::Bytes; -use futures::sync::{BiLock, mpsc}; -use futures::{Poll, Async, Stream}; +use futures::{Async, Poll, Stream}; +use futures::sync::{mpsc, BiLock}; use std::collections::HashMap; use util::SeqGenerator; @@ -13,7 +13,7 @@ component! { } } -#[derive(Debug,Hash,PartialEq,Eq,Copy,Clone)] +#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)] pub struct ChannelError; pub struct Channel { diff --git a/core/src/component.rs b/core/src/component.rs index 1a887e77..923e72ec 100644 --- a/core/src/component.rs +++ b/core/src/component.rs @@ -36,15 +36,15 @@ macro_rules! component { } } -use std::sync::Mutex; use std::cell::UnsafeCell; +use std::sync::Mutex; pub struct Lazy(Mutex, UnsafeCell>); -unsafe impl Sync for Lazy {} -unsafe impl Send for Lazy {} +unsafe impl Sync for Lazy {} +unsafe impl Send for Lazy {} #[cfg_attr(feature = "cargo-clippy", allow(mutex_atomic))] -impl Lazy { +impl Lazy { pub fn new() -> Lazy { Lazy(Mutex::new(false), UnsafeCell::new(None)) } diff --git a/core/src/config.rs b/core/src/config.rs index 46b22e41..297c04f4 100644 --- a/core/src/config.rs +++ b/core/src/config.rs @@ -1,10 +1,10 @@ -use uuid::Uuid; -use std::str::FromStr; use std::fmt; +use std::str::FromStr; +use uuid::Uuid; use version; -#[derive(Clone,Debug)] +#[derive(Clone, Debug)] pub struct SessionConfig { pub user_agent: String, pub device_id: String, @@ -20,7 +20,6 @@ impl Default for SessionConfig { } } - #[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] pub enum Bitrate { Bitrate96, @@ -100,7 +99,7 @@ impl Default for DeviceType { } } -#[derive(Clone,Debug)] +#[derive(Clone, Debug)] pub struct PlayerConfig { pub bitrate: Bitrate, pub onstart: Option, @@ -117,7 +116,7 @@ impl Default for PlayerConfig { } } -#[derive(Clone,Debug)] +#[derive(Clone, Debug)] pub struct ConnectConfig { pub name: String, pub device_type: DeviceType, diff --git a/core/src/connection/codec.rs b/core/src/connection/codec.rs index 6fbede13..4a8fd208 100644 --- a/core/src/connection/codec.rs +++ b/core/src/connection/codec.rs @@ -1,5 +1,5 @@ use byteorder::{BigEndian, ByteOrder}; -use bytes::{Bytes, BytesMut, BufMut}; +use bytes::{BufMut, Bytes, BytesMut}; use shannon::Shannon; use std::io; use tokio_io::codec::{Decoder, Encoder}; @@ -88,7 +88,8 @@ impl Decoder for APCodec { let mut payload = buf.split_to(size + MAC_SIZE); - self.decode_cipher.decrypt(&mut payload.get_mut(..size).unwrap()); + self.decode_cipher + .decrypt(&mut payload.get_mut(..size).unwrap()); let mac = payload.split_off(size); self.decode_cipher.check_mac(mac.as_ref())?; @@ -96,7 +97,6 @@ impl Decoder for APCodec { } } - Ok(None) } } diff --git a/core/src/connection/handshake.rs b/core/src/connection/handshake.rs index 5b94f709..c47364b4 100644 --- a/core/src/connection/handshake.rs +++ b/core/src/connection/handshake.rs @@ -1,20 +1,21 @@ -use crypto::sha1::Sha1; +use byteorder::{BigEndian, ByteOrder, WriteBytesExt}; use crypto::hmac::Hmac; -use crypto::mac::Mac;use byteorder::{BigEndian, ByteOrder, WriteBytesExt}; +use crypto::mac::Mac; +use crypto::sha1::Sha1; +use futures::{Async, Future, Poll}; use protobuf::{self, Message, MessageStatic}; use rand::thread_rng; use std::io::{self, Read}; use std::marker::PhantomData; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; -use tokio_io::io::{write_all, WriteAll, read_exact, ReadExact, Window}; -use futures::{Poll, Async, Future}; +use tokio_io::io::{read_exact, write_all, ReadExact, Window, WriteAll}; +use super::codec::APCodec; use diffie_hellman::DHLocalKeys; use protocol; -use protocol::keyexchange::{ClientHello, APResponseMessage, ClientResponsePlaintext}; +use protocol::keyexchange::{APResponseMessage, ClientHello, ClientResponsePlaintext}; use util; -use super::codec::APCodec; pub struct Handshake { keys: DHLocalKeys, @@ -37,7 +38,7 @@ pub fn handshake(connection: T) -> Handshake { } } -impl Future for Handshake { +impl Future for Handshake { type Item = Framed; type Error = io::Error; @@ -47,22 +48,22 @@ impl Future for Handshake { self.state = match self.state { ClientHello(ref mut write) => { let (connection, accumulator) = try_ready!(write.poll()); - + let read = recv_packet(connection, accumulator); APResponse(read) } APResponse(ref mut read) => { let (connection, message, accumulator) = try_ready!(read.poll()); - let remote_key = message.get_challenge() + let remote_key = message + .get_challenge() .get_login_crypto_challenge() .get_diffie_hellman() .get_gs() .to_owned(); let shared_secret = self.keys.shared_secret(&remote_key); - let (challenge, send_key, recv_key) = compute_keys(&shared_secret, - &accumulator); + let (challenge, send_key, recv_key) = compute_keys(&shared_secret, &accumulator); let codec = APCodec::new(&send_key, &recv_key); let write = client_response(connection, challenge); @@ -129,15 +130,17 @@ enum RecvPacket { } fn recv_packet(connection: T, acc: Vec) -> RecvPacket - where T: Read, - M: MessageStatic +where + T: Read, + M: MessageStatic, { RecvPacket::Header(read_into_accumulator(connection, 4, acc), PhantomData) } -impl Future for RecvPacket - where T: Read, - M: MessageStatic +impl Future for RecvPacket +where + T: Read, + M: MessageStatic, { type Item = (T, M, Vec); type Error = io::Error; @@ -167,7 +170,11 @@ impl Future for RecvPacket } } -fn read_into_accumulator(connection: T, size: usize, mut acc: Vec) -> ReadExact>> { +fn read_into_accumulator( + connection: T, + size: usize, + mut acc: Vec, +) -> ReadExact>> { let offset = acc.len(); acc.resize(offset + size, 0); @@ -191,5 +198,9 @@ fn compute_keys(shared_secret: &[u8], packets: &[u8]) -> (Vec, Vec, Vec< mac = Hmac::new(Sha1::new(), &data[..0x14]); mac.input(packets); - (mac.result().code().to_vec(), data[0x14..0x34].to_vec(), data[0x34..0x54].to_vec()) + ( + mac.result().code().to_vec(), + data[0x14..0x34].to_vec(), + data[0x34..0x54].to_vec(), + ) } diff --git a/core/src/connection/mod.rs b/core/src/connection/mod.rs index 91c220b6..fae4092a 100644 --- a/core/src/connection/mod.rs +++ b/core/src/connection/mod.rs @@ -5,31 +5,34 @@ pub use self::codec::APCodec; pub use self::handshake::handshake; use futures::{Future, Sink, Stream}; +use protobuf::{self, Message}; use std::io; use std::net::ToSocketAddrs; use tokio_core::net::TcpStream; use tokio_core::reactor::Handle; use tokio_io::codec::Framed; -use protobuf::{self, Message}; use authentication::Credentials; use version; pub type Transport = Framed; -pub fn connect(addr: A, handle: &Handle) -> Box> { +pub fn connect( + addr: A, + handle: &Handle, +) -> Box> { let addr = addr.to_socket_addrs().unwrap().next().unwrap(); let socket = TcpStream::connect(&addr, handle); - let connection = socket.and_then(|socket| { - handshake(socket) - }); + let connection = socket.and_then(|socket| handshake(socket)); Box::new(connection) } -pub fn authenticate(transport: Transport, credentials: Credentials, device_id: String) - -> Box> -{ +pub fn authenticate( + transport: Transport, + credentials: Credentials, + device_id: String, +) -> Box> { use protocol::authentication::{APWelcome, ClientResponseEncrypted, CpuFamily, Os}; let packet = protobuf_init!(ClientResponseEncrypted::new(), { @@ -50,26 +53,26 @@ pub fn authenticate(transport: Transport, credentials: Credentials, device_id: S let cmd = 0xab; let data = packet.write_to_bytes().unwrap(); - Box::new(transport.send((cmd, data)).and_then(|transport| { - transport.into_future().map_err(|(err, _stream)| err) - }).and_then(|(packet, transport)| { - match packet { - Some((0xac, data)) => { - let welcome_data: APWelcome = - protobuf::parse_from_bytes(data.as_ref()).unwrap(); + Box::new( + transport + .send((cmd, data)) + .and_then(|transport| transport.into_future().map_err(|(err, _stream)| err)) + .and_then(|(packet, transport)| match packet { + Some((0xac, data)) => { + let welcome_data: APWelcome = protobuf::parse_from_bytes(data.as_ref()).unwrap(); - let reusable_credentials = Credentials { - username: welcome_data.get_canonical_username().to_owned(), - auth_type: welcome_data.get_reusable_auth_credentials_type(), - auth_data: welcome_data.get_reusable_auth_credentials().to_owned(), - }; + let reusable_credentials = Credentials { + username: welcome_data.get_canonical_username().to_owned(), + auth_type: welcome_data.get_reusable_auth_credentials_type(), + auth_data: welcome_data.get_reusable_auth_credentials().to_owned(), + }; - Ok((transport, reusable_credentials)) - } + Ok((transport, reusable_credentials)) + } - Some((0xad, _)) => panic!("Authentication failed"), - Some((cmd, _)) => panic!("Unexpected packet {:?}", cmd), - None => panic!("EOF"), - } - })) + Some((0xad, _)) => panic!("Authentication failed"), + Some((cmd, _)) => panic!("Unexpected packet {:?}", cmd), + None => panic!("EOF"), + }), + ) } diff --git a/core/src/diffie_hellman.rs b/core/src/diffie_hellman.rs index 2f6572e1..2200399f 100644 --- a/core/src/diffie_hellman.rs +++ b/core/src/diffie_hellman.rs @@ -43,9 +43,11 @@ impl DHLocalKeys { } pub fn shared_secret(&self, remote_key: &[u8]) -> Vec { - let shared_key = util::powm(&BigUint::from_bytes_be(remote_key), - &self.private_key, - &DH_PRIME); + let shared_key = util::powm( + &BigUint::from_bytes_be(remote_key), + &self.private_key, + &DH_PRIME, + ); shared_key.to_bytes_be() } } diff --git a/core/src/keymaster.rs b/core/src/keymaster.rs index a4e0c169..4d82ae07 100644 --- a/core/src/keymaster.rs +++ b/core/src/keymaster.rs @@ -13,13 +13,19 @@ pub struct Token { pub scope: Vec, } -pub fn get_token(session: &Session, client_id: &str, scopes: &str) -> Box> { - let url = format!("hm://keymaster/token/authenticated?client_id={}&scope={}", - client_id, scopes); +pub fn get_token( + session: &Session, + client_id: &str, + scopes: &str, +) -> Box> { + let url = format!( + "hm://keymaster/token/authenticated?client_id={}&scope={}", + client_id, scopes + ); Box::new(session.mercury().get(url).map(move |response| { let data = response.payload.first().expect("Empty payload"); let data = String::from_utf8(data.clone()).unwrap(); - let token : Token = serde_json::from_str(&data).unwrap(); + let token: Token = serde_json::from_str(&data).unwrap(); token })) diff --git a/core/src/lib.rs b/core/src/lib.rs index ab7a556f..4cc44448 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,10 +1,15 @@ #![cfg_attr(feature = "cargo-clippy", allow(unused_io_amount))] -#[macro_use] extern crate error_chain; -#[macro_use] extern crate futures; -#[macro_use] extern crate lazy_static; -#[macro_use] extern crate log; -#[macro_use] extern crate serde_derive; +#[macro_use] +extern crate error_chain; +#[macro_use] +extern crate futures; +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate log; +#[macro_use] +extern crate serde_derive; extern crate base64; extern crate byteorder; @@ -26,7 +31,8 @@ extern crate uuid; extern crate librespot_protocol as protocol; -#[macro_use] mod component; +#[macro_use] +mod component; mod apresolve; pub mod audio_key; pub mod authentication; diff --git a/core/src/mercury/mod.rs b/core/src/mercury/mod.rs index 6309d0f4..9a607061 100644 --- a/core/src/mercury/mod.rs +++ b/core/src/mercury/mod.rs @@ -1,7 +1,7 @@ use byteorder::{BigEndian, ByteOrder}; use bytes::Bytes; -use futures::sync::{oneshot, mpsc}; -use futures::{Async, Poll, Future}; +use futures::{Async, Future, Poll}; +use futures::sync::{mpsc, oneshot}; use protobuf; use protocol; use std::collections::HashMap; @@ -30,7 +30,7 @@ pub struct MercuryPending { } pub struct MercuryFuture(oneshot::Receiver>); -impl Future for MercuryFuture { +impl Future for MercuryFuture { type Item = T; type Error = MercuryError; @@ -51,9 +51,7 @@ impl MercuryManager { seq } - pub fn request(&self, req: MercuryRequest) - -> MercuryFuture - { + pub fn request(&self, req: MercuryRequest) -> MercuryFuture { let (tx, rx) = oneshot::channel(); let pending = MercuryPending { @@ -72,9 +70,7 @@ impl MercuryManager { MercuryFuture(rx) } - pub fn get>(&self, uri: T) - -> MercuryFuture - { + pub fn get>(&self, uri: T) -> MercuryFuture { self.request(MercuryRequest { method: MercuryMethod::GET, uri: uri.into(), @@ -83,9 +79,7 @@ impl MercuryManager { }) } - pub fn send>(&self, uri: T, data: Vec) - -> MercuryFuture - { + pub fn send>(&self, uri: T, data: Vec) -> MercuryFuture { self.request(MercuryRequest { method: MercuryMethod::SEND, uri: uri.into(), @@ -98,9 +92,10 @@ impl MercuryManager { MercurySender::new(self.clone(), uri.into()) } - pub fn subscribe>(&self, uri: T) - -> Box, Error = MercuryError>> - { + pub fn subscribe>( + &self, + uri: T, + ) -> Box, Error = MercuryError>> { let uri = uri.into(); let request = self.request(MercuryRequest { method: MercuryMethod::SUB, @@ -118,8 +113,8 @@ impl MercuryManager { if response.payload.len() > 0 { // Old subscription protocol, watch the provided list of URIs for sub in response.payload { - let mut sub : protocol::pubsub::Subscription - = protobuf::parse_from_bytes(&sub).unwrap(); + let mut sub: protocol::pubsub::Subscription = + protobuf::parse_from_bytes(&sub).unwrap(); let sub_uri = sub.take_uri(); debug!("subscribed sub_uri={}", sub_uri); @@ -147,13 +142,11 @@ impl MercuryManager { let mut pending = match pending { Some(pending) => pending, - None if cmd == 0xb5 => { - MercuryPending { - parts: Vec::new(), - partial: None, - callback: None, - } - } + None if cmd == 0xb5 => MercuryPending { + parts: Vec::new(), + partial: None, + callback: None, + }, None => { warn!("Ignore seq {:?} cmd {:x}", seq, cmd); return; diff --git a/core/src/mercury/sender.rs b/core/src/mercury/sender.rs index 359e6907..f00235ef 100644 --- a/core/src/mercury/sender.rs +++ b/core/src/mercury/sender.rs @@ -1,5 +1,5 @@ +use futures::{Async, AsyncSink, Future, Poll, Sink, StartSend}; use std::collections::VecDeque; -use futures::{Async, Poll, Future, Sink, StartSend, AsyncSink}; use super::*; diff --git a/core/src/mercury/types.rs b/core/src/mercury/types.rs index 9952b533..23f64c45 100644 --- a/core/src/mercury/types.rs +++ b/core/src/mercury/types.rs @@ -27,18 +27,17 @@ pub struct MercuryResponse { pub payload: Vec>, } -#[derive(Debug,Hash,PartialEq,Eq,Copy,Clone)] +#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)] pub struct MercuryError; impl ToString for MercuryMethod { fn to_string(&self) -> String { match *self { - MercuryMethod::GET => "GET", - MercuryMethod::SUB => "SUB", - MercuryMethod::UNSUB => "UNSUB", - MercuryMethod::SEND => "SEND", - } - .to_owned() + MercuryMethod::GET => "GET", + MercuryMethod::SUB => "SUB", + MercuryMethod::UNSUB => "UNSUB", + MercuryMethod::SEND => "SEND", + }.to_owned() } } @@ -58,7 +57,9 @@ impl MercuryRequest { packet.write_u16::(seq.len() as u16).unwrap(); packet.write_all(seq).unwrap(); packet.write_u8(1).unwrap(); // Flags: FINAL - packet.write_u16::(1 + self.payload.len() as u16).unwrap(); // Part count + packet + .write_u16::(1 + self.payload.len() as u16) + .unwrap(); // Part count let mut header = protocol::mercury::Header::new(); header.set_uri(self.uri.clone()); @@ -68,7 +69,9 @@ impl MercuryRequest { header.set_content_type(content_type.clone()); } - packet.write_u16::(header.compute_size() as u16).unwrap(); + packet + .write_u16::(header.compute_size() as u16) + .unwrap(); header.write_to_writer(&mut packet).unwrap(); for p in &self.payload { diff --git a/core/src/session.rs b/core/src/session.rs index 9fe785ed..628e0377 100644 --- a/core/src/session.rs +++ b/core/src/session.rs @@ -1,19 +1,19 @@ use bytes::Bytes; use crypto::digest::Digest; use crypto::sha1::Sha1; +use futures::{Async, Future, IntoFuture, Poll, Stream}; use futures::sync::mpsc; -use futures::{Future, Stream, IntoFuture, Poll, Async}; use std::io; -use std::sync::{RwLock, Arc, Weak}; +use std::sync::{Arc, RwLock, Weak}; +use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; use tokio_core::reactor::{Handle, Remote}; -use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use apresolve::apresolve_or_fallback; use authentication::Credentials; use cache::Cache; use component::Lazy; -use connection; use config::SessionConfig; +use connection; use audio_key::AudioKeyManager; use channel::ChannelManager; @@ -40,7 +40,7 @@ pub struct SessionInternal { session_id: usize, } -static SESSION_COUNTER : AtomicUsize = ATOMIC_USIZE_INIT; +static SESSION_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; #[derive(Clone)] pub struct Session(pub Arc); @@ -52,13 +52,14 @@ pub fn device_id(name: &str) -> String { } impl Session { - pub fn connect(config: SessionConfig, credentials: Credentials, - cache: Option, handle: Handle) - -> Box> - { + pub fn connect( + config: SessionConfig, + credentials: Credentials, + cache: Option, + handle: Handle, + ) -> Box> { let access_point = apresolve_or_fallback::(&handle); - let handle_ = handle.clone(); let connection = access_point.and_then(move |addr| { info!("Connecting to AP \"{}\"", addr); @@ -66,9 +67,8 @@ impl Session { }); let device_id = config.device_id.clone(); - let authentication = connection.and_then(move |connection| { - connection::authenticate(connection, credentials, device_id) - }); + let authentication = connection + .and_then(move |connection| connection::authenticate(connection, credentials, device_id)); let result = authentication.map(move |(transport, reusable_credentials)| { info!("Authenticated as \"{}\" !", reusable_credentials.username); @@ -77,21 +77,28 @@ impl Session { } let (session, task) = Session::create( - &handle, transport, config, cache, reusable_credentials.username.clone() + &handle, + transport, + config, + cache, + reusable_credentials.username.clone(), ); handle.spawn(task.map_err(|e| panic!(e))); session }); - + Box::new(result) } - fn create(handle: &Handle, transport: connection::Transport, - config: SessionConfig, cache: Option, username: String) - -> (Session, Box>) - { + fn create( + handle: &Handle, + transport: connection::Transport, + config: SessionConfig, + cache: Option, + username: String, + ) -> (Session, Box>) { let (sink, stream) = transport.split(); let (sender_tx, sender_rx) = mpsc::unbounded(); @@ -121,11 +128,15 @@ impl Session { let sender_task = sender_rx .map_err(|e| -> io::Error { panic!(e) }) - .forward(sink).map(|_| ()); + .forward(sink) + .map(|_| ()); let receiver_task = DispatchTask(stream, session.weak()); - let task = Box::new((receiver_task, sender_task).into_future() - .map(|((), ())| ())); + let task = Box::new( + (receiver_task, sender_task) + .into_future() + .map(|((), ())| ()), + ); (session, task) } @@ -143,16 +154,21 @@ impl Session { } pub fn spawn(&self, f: F) - where F: FnOnce(&Handle) -> R + Send + 'static, - R: IntoFuture, - R::Future: 'static + where + F: FnOnce(&Handle) -> R + Send + 'static, + R: IntoFuture, + R::Future: 'static, { self.0.handle.spawn(f) } fn debug_info(&self) { - debug!("Session[{}] strong={} weak={}", - self.0.session_id, Arc::strong_count(&self.0), Arc::weak_count(&self.0)); + debug!( + "Session[{}] strong={} weak={}", + self.0.session_id, + Arc::strong_count(&self.0), + Arc::weak_count(&self.0) + ); } #[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))] @@ -161,7 +177,7 @@ impl Session { 0x4 => { self.debug_info(); self.send_packet(0x49, data.as_ref().to_owned()); - }, + } 0x4a => (), 0x1b => { let country = String::from_utf8(data.as_ref().to_owned()).unwrap(); @@ -229,10 +245,12 @@ impl Drop for SessionInternal { } struct DispatchTask(S, SessionWeak) - where S: Stream; +where + S: Stream; -impl Future for DispatchTask - where S: Stream +impl Future for DispatchTask +where + S: Stream, { type Item = (); type Error = S::Error; @@ -240,9 +258,7 @@ impl Future for DispatchTask fn poll(&mut self) -> Poll { let session = match self.1.try_upgrade() { Some(session) => session, - None => { - return Ok(Async::Ready(())) - }, + None => return Ok(Async::Ready(())), }; loop { @@ -252,8 +268,9 @@ impl Future for DispatchTask } } -impl Drop for DispatchTask - where S: Stream +impl Drop for DispatchTask +where + S: Stream, { fn drop(&mut self) { debug!("drop Dispatch"); diff --git a/core/src/util/int128.rs b/core/src/util/int128.rs index 9cfbaf3b..f79692ca 100644 --- a/core/src/util/int128.rs +++ b/core/src/util/int128.rs @@ -1,6 +1,6 @@ use std; -#[derive(Debug,Copy,Clone,PartialEq,Eq,Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[allow(non_camel_case_types)] pub struct u128 { high: u64, @@ -28,12 +28,7 @@ impl std::ops::Add for u128 { type Output = u128; fn add(self, rhs: u128) -> u128 { let low = self.low + rhs.low; - let high = self.high + rhs.high + - if low < self.low { - 1 - } else { - 0 - }; + let high = self.high + rhs.high + if low < self.low { 1 } else { 0 }; u128::from_parts(high, low) } @@ -43,12 +38,7 @@ impl<'a> std::ops::Add<&'a u128> for u128 { type Output = u128; fn add(self, rhs: &'a u128) -> u128 { let low = self.low + rhs.low; - let high = self.high + rhs.high + - if low < self.low { - 1 - } else { - 0 - }; + let high = self.high + rhs.high + if low < self.low { 1 } else { 0 }; u128::from_parts(high, low) } @@ -60,20 +50,23 @@ impl std::convert::From for u128 { } } - impl std::ops::Mul for u128 { type Output = u128; fn mul(self, rhs: u128) -> u128 { - let top: [u64; 4] = [self.high >> 32, - self.high & 0xFFFFFFFF, - self.low >> 32, - self.low & 0xFFFFFFFF]; + let top: [u64; 4] = [ + self.high >> 32, + self.high & 0xFFFFFFFF, + self.low >> 32, + self.low & 0xFFFFFFFF, + ]; - let bottom: [u64; 4] = [rhs.high >> 32, - rhs.high & 0xFFFFFFFF, - rhs.low >> 32, - rhs.low & 0xFFFFFFFF]; + let bottom: [u64; 4] = [ + rhs.high >> 32, + rhs.high & 0xFFFFFFFF, + rhs.low >> 32, + rhs.low & 0xFFFFFFFF, + ]; let mut rows = [u128::zero(); 16]; for i in 0..4 { diff --git a/core/src/util/mod.rs b/core/src/util/mod.rs index 6e21a0f2..66f2fe3f 100644 --- a/core/src/util/mod.rs +++ b/core/src/util/mod.rs @@ -1,7 +1,7 @@ use num_bigint::BigUint; -use num_traits::{Zero, One}; use num_integer::Integer; -use rand::{Rng, Rand}; +use num_traits::{One, Zero}; +use rand::{Rand, Rng}; use std::mem; use std::ops::{Mul, Rem, Shr}; @@ -9,7 +9,7 @@ mod int128; mod spotify_id; pub use util::int128::u128; -pub use util::spotify_id::{SpotifyId, FileId}; +pub use util::spotify_id::{FileId, SpotifyId}; pub fn rand_vec(rng: &mut G, size: usize) -> Vec { rng.gen_iter().take(size).collect() @@ -57,8 +57,8 @@ impl<'s> Iterator for StrChunks<'s> { } } -pub trait ReadSeek : ::std::io::Read + ::std::io::Seek { } -impl ReadSeek for T { } +pub trait ReadSeek: ::std::io::Read + ::std::io::Seek {} +impl ReadSeek for T {} pub trait Seq { fn next(&self) -> Self; @@ -77,7 +77,7 @@ impl_seq!(u8 u16 u32 u64 usize); #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Default)] pub struct SeqGenerator(T); -impl SeqGenerator { +impl SeqGenerator { pub fn new(value: T) -> Self { SeqGenerator(value) } diff --git a/core/src/util/spotify_id.rs b/core/src/util/spotify_id.rs index 8ebd5a84..5d99cb67 100644 --- a/core/src/util/spotify_id.rs +++ b/core/src/util/spotify_id.rs @@ -1,16 +1,15 @@ +use byteorder::{BigEndian, ByteOrder}; use std; use std::fmt; use util::u128; -use byteorder::{BigEndian, ByteOrder}; // Unneeded since 1.21 #[allow(unused_imports)] use std::ascii::AsciiExt; -#[derive(Debug,Copy,Clone,PartialEq,Eq,Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct SpotifyId(u128); -const BASE62_DIGITS: &'static [u8] = - b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +const BASE62_DIGITS: &'static [u8] = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; const BASE16_DIGITS: &'static [u8] = b"0123456789abcdef"; impl SpotifyId { @@ -79,7 +78,7 @@ impl SpotifyId { } } -#[derive(Copy,Clone,PartialEq,Eq,PartialOrd,Ord,Hash)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct FileId(pub [u8; 20]); impl FileId {