Paul Lietar 9 лет назад
Родитель
Сommit
90eeed3f80
22 измененных файлов с 380 добавлено и 342 удалено
  1. 10 17
      src/audio_decrypt.rs
  2. 35 32
      src/audio_file.rs
  3. 36 33
      src/audio_key.rs
  4. 18 11
      src/authentication.rs
  5. 6 8
      src/connection.rs
  6. 0 1
      src/diffie_hellman.rs
  7. 13 11
      src/discovery.rs
  8. 3 3
      src/lib.rs
  9. 18 22
      src/main.rs
  10. 31 27
      src/mercury.rs
  11. 51 44
      src/metadata.rs
  12. 31 26
      src/player.rs
  13. 14 17
      src/session.rs
  14. 28 19
      src/spirc.rs
  15. 24 18
      src/stream.rs
  16. 4 5
      src/util/arcvec.rs
  17. 26 16
      src/util/int128.rs
  18. 10 10
      src/util/mod.rs
  19. 10 9
      src/util/spotify_id.rs
  20. 8 9
      src/util/subfile.rs
  21. 2 3
      src/util/zerofile.rs
  22. 2 1
      src/zeroconf.rs

+ 10 - 17
src/audio_decrypt.rs

@@ -6,21 +6,18 @@ use std::ops::Add;
 
 use audio_key::AudioKey;
 
-const AUDIO_AESIV : &'static [u8] = &[
-    0x72,0xe0,0x67,0xfb,0xdd,0xcb,0xcf,0x77,0xeb,0xe8,0xbc,0x64,0x3f,0x63,0x0d,0x93,
-];
+const AUDIO_AESIV: &'static [u8] = &[0x72, 0xe0, 0x67, 0xfb, 0xdd, 0xcb, 0xcf, 0x77, 0xeb, 0xe8,
+                                     0xbc, 0x64, 0x3f, 0x63, 0x0d, 0x93];
 
-pub struct AudioDecrypt<T : io::Read> {
+pub struct AudioDecrypt<T: io::Read> {
     cipher: Box<SynchronousStreamCipher + 'static>,
     key: AudioKey,
     reader: T,
 }
 
-impl <T : io::Read> AudioDecrypt<T> {
+impl<T: io::Read> AudioDecrypt<T> {
     pub fn new(key: AudioKey, reader: T) -> AudioDecrypt<T> {
-        let cipher = aes::ctr(aes::KeySize::KeySize128,
-                              &key,
-                              AUDIO_AESIV);
+        let cipher = aes::ctr(aes::KeySize::KeySize128, &key, AUDIO_AESIV);
         AudioDecrypt {
             cipher: cipher,
             key: key,
@@ -29,7 +26,7 @@ impl <T : io::Read> AudioDecrypt<T> {
     }
 }
 
-impl <T : io::Read> io::Read for AudioDecrypt<T> {
+impl<T: io::Read> io::Read for AudioDecrypt<T> {
     fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
         let mut buffer = vec![0u8; output.len()];
         let len = try!(self.reader.read(&mut buffer));
@@ -40,17 +37,15 @@ impl <T : io::Read> io::Read for AudioDecrypt<T> {
     }
 }
 
-impl <T : io::Read + io::Seek> io::Seek for AudioDecrypt<T> {
+impl<T: io::Read + io::Seek> io::Seek for AudioDecrypt<T> {
     fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
         let newpos = try!(self.reader.seek(pos));
         let skip = newpos % 16;
 
         let iv = BigUint::from_bytes_be(AUDIO_AESIV)
-                    .add(BigUint::from_u64(newpos / 16).unwrap())
-                    .to_bytes_be();
-        self.cipher = aes::ctr(aes::KeySize::KeySize128,
-                               &self.key,
-                               &iv);
+                     .add(BigUint::from_u64(newpos / 16).unwrap())
+                     .to_bytes_be();
+        self.cipher = aes::ctr(aes::KeySize::KeySize128, &self.key, &iv);
 
         let buf = vec![0u8; skip as usize];
         let mut buf2 = vec![0u8; skip as usize];
@@ -59,5 +54,3 @@ impl <T : io::Read + io::Seek> io::Seek for AudioDecrypt<T> {
         Ok(newpos as u64)
     }
 }
-
-

+ 35 - 32
src/audio_file.rs

@@ -13,11 +13,11 @@ use util::{FileId, IgnoreExt, ZeroFile, mkdir_existing};
 use session::Session;
 use stream::StreamEvent;
 
-const CHUNK_SIZE : usize = 0x20000;
+const CHUNK_SIZE: usize = 0x20000;
 
 pub enum AudioFile {
     Direct(fs::File),
-    Loading(AudioFileLoading)
+    Loading(AudioFileLoading),
 }
 
 pub struct AudioFileLoading {
@@ -43,15 +43,18 @@ impl AudioFileLoading {
         let read_file = files_iter.next().unwrap();
         let mut write_file = files_iter.next().unwrap();
 
-        let size = session.stream(file_id, 0, 1).into_iter()
-            .filter_map(|event| {
-                match event {
-                    StreamEvent::Header(id, ref data) if id == 0x3 => {
-                        Some(BigEndian::read_u32(data) as usize * 4)
-                    }
-                    _ => None
-                }
-            }).next().unwrap();
+        let size = session.stream(file_id, 0, 1)
+                          .into_iter()
+                          .filter_map(|event| {
+                              match event {
+                                  StreamEvent::Header(id, ref data) if id == 0x3 => {
+                                      Some(BigEndian::read_u32(data) as usize * 4)
+                                  }
+                                  _ => None,
+                              }
+                          })
+                          .next()
+                          .unwrap();
 
         let chunk_count = (size + CHUNK_SIZE - 1) / CHUNK_SIZE;
 
@@ -70,9 +73,7 @@ impl AudioFileLoading {
         let _shared = shared.clone();
         let _session = session.clone();
 
-        thread::spawn(move || {
-            AudioFileLoading::fetch(&_session, _shared, write_file, seek_rx)
-        });
+        thread::spawn(move || AudioFileLoading::fetch(&_session, _shared, write_file, seek_rx));
 
         AudioFileLoading {
             read_file: read_file,
@@ -80,12 +81,14 @@ impl AudioFileLoading {
             position: 0,
             seek: seek_tx,
 
-            shared: shared
+            shared: shared,
         }
     }
 
-    fn fetch(session: &Session, shared: Arc<AudioFileShared>,
-             mut write_file: TempFile, seek_rx: mpsc::Receiver<u64>) {
+    fn fetch(session: &Session,
+             shared: Arc<AudioFileShared>,
+             mut write_file: TempFile,
+             seek_rx: mpsc::Receiver<u64>) {
         let mut index = 0;
 
         loop {
@@ -113,12 +116,14 @@ impl AudioFileLoading {
         }
     }
 
-    fn fetch_chunk(session: &Session, shared: &Arc<AudioFileShared>,
-                   write_file: &mut TempFile, index: usize) {
+    fn fetch_chunk(session: &Session,
+                   shared: &Arc<AudioFileShared>,
+                   write_file: &mut TempFile,
+                   index: usize) {
 
         let rx = session.stream(shared.file_id,
-                     (index * CHUNK_SIZE / 4) as u32,
-                     (CHUNK_SIZE / 4) as u32);
+                                (index * CHUNK_SIZE / 4) as u32,
+                                (CHUNK_SIZE / 4) as u32);
 
         println!("Chunk {}", index);
 
@@ -133,7 +138,7 @@ impl AudioFileLoading {
 
                     size += data.len();
                     if size >= CHUNK_SIZE {
-                        break
+                        break;
                     }
                 }
             }
@@ -150,7 +155,8 @@ impl AudioFileLoading {
 
         mkdir_existing(&AudioFileManager::cache_dir(session, shared.file_id)).unwrap();
 
-        let mut f = fs::File::create(AudioFileManager::cache_path(session, shared.file_id)).unwrap();
+        let mut f = fs::File::create(AudioFileManager::cache_path(session, shared.file_id))
+                        .unwrap();
         io::copy(write_file, &mut f).unwrap();
     }
 }
@@ -159,7 +165,7 @@ impl Read for AudioFileLoading {
     fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
         let index = self.position as usize / CHUNK_SIZE;
         let offset = self.position as usize % CHUNK_SIZE;
-        let len = min(output.len(), CHUNK_SIZE-offset);
+        let len = min(output.len(), CHUNK_SIZE - offset);
 
         let mut bitmap = self.shared.bitmap.lock().unwrap();
         while !bitmap.contains(&index) {
@@ -179,11 +185,9 @@ impl Seek for AudioFileLoading {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
         self.position = try!(self.read_file.seek(pos));
 
-        /*
-         * Notify the fetch thread to get the correct block
-         * This can fail if fetch thread has completed, in which case the
-         * block is ready. Just ignore the error.
-         */
+        // Notify the fetch thread to get the correct block
+        // This can fail if fetch thread has completed, in which case the
+        // block is ready. Just ignore the error.
         self.seek.send(self.position).ignore();
         Ok(self.position as u64)
     }
@@ -223,11 +227,10 @@ impl AudioFileManager {
         AudioFileManager::cache_dir(session, file_id).join(&name[2..])
     }
 
-    pub fn request (&mut self, session: &Session, file_id: FileId) -> AudioFile {
+    pub fn request(&mut self, session: &Session, file_id: FileId) -> AudioFile {
         match fs::File::open(AudioFileManager::cache_path(session, file_id)) {
             Ok(f) => AudioFile::Direct(f),
-            Err(..) => AudioFile::Loading(AudioFileLoading::new(session, file_id))
+            Err(..) => AudioFile::Loading(AudioFileLoading::new(session, file_id)),
         }
     }
 }
-

+ 36 - 33
src/audio_key.rs

@@ -18,12 +18,12 @@ struct AudioKeyId(SpotifyId, FileId);
 enum AudioKeyStatus {
     Loading(Vec<eventual::Complete<AudioKey, AudioKeyError>>),
     Loaded(AudioKey),
-    Failed(AudioKeyError)
+    Failed(AudioKeyError),
 }
 
 pub struct AudioKeyManager {
     next_seq: u32,
-    pending: HashMap<u32, AudioKeyId>, 
+    pending: HashMap<u32, AudioKeyId>,
     cache: HashMap<AudioKeyId, AudioKeyStatus>,
 }
 
@@ -32,44 +32,48 @@ impl AudioKeyManager {
         AudioKeyManager {
             next_seq: 1,
             pending: HashMap::new(),
-            cache: HashMap::new()
+            cache: HashMap::new(),
         }
     }
 
-    pub fn request(&mut self, session: &Session, track: SpotifyId, file: FileId)
-        -> eventual::Future<AudioKey, AudioKeyError> {
+    pub fn request(&mut self,
+                   session: &Session,
+                   track: SpotifyId,
+                   file: FileId)
+                   -> eventual::Future<AudioKey, AudioKeyError> {
 
         let id = AudioKeyId(track, file);
-        self.cache.get_mut(&id).map(|status| match *status {
-            AudioKeyStatus::Failed(error) => {
-                eventual::Future::error(error)
-            }
-            AudioKeyStatus::Loaded(key) => {
-                eventual::Future::of(key)
-            }
-            AudioKeyStatus::Loading(ref mut req) => {
-                let (tx, rx) = eventual::Future::pair();
-                req.push(tx);
-                rx
-            }
-        }).unwrap_or_else(|| {
-            let seq = self.next_seq;
-            self.next_seq += 1;
+        self.cache
+            .get_mut(&id)
+            .map(|status| {
+                match *status {
+                    AudioKeyStatus::Failed(error) => eventual::Future::error(error),
+                    AudioKeyStatus::Loaded(key) => eventual::Future::of(key),
+                    AudioKeyStatus::Loading(ref mut req) => {
+                        let (tx, rx) = eventual::Future::pair();
+                        req.push(tx);
+                        rx
+                    }
+                }
+            })
+            .unwrap_or_else(|| {
+                let seq = self.next_seq;
+                self.next_seq += 1;
 
-            let mut data : Vec<u8> = Vec::new();
-            data.write(&file.0).unwrap();
-            data.write(&track.to_raw()).unwrap();
-            data.write_u32::<BigEndian>(seq).unwrap();
-            data.write_u16::<BigEndian>(0x0000).unwrap();
+                let mut data: Vec<u8> = Vec::new();
+                data.write(&file.0).unwrap();
+                data.write(&track.to_raw()).unwrap();
+                data.write_u32::<BigEndian>(seq).unwrap();
+                data.write_u16::<BigEndian>(0x0000).unwrap();
 
-            session.send_packet(0xc, &data).unwrap();
+                session.send_packet(0xc, &data).unwrap();
 
-            self.pending.insert(seq, id.clone());
+                self.pending.insert(seq, id.clone());
 
-            let (tx, rx) = eventual::Future::pair();
-            self.cache.insert(id, AudioKeyStatus::Loading(vec!{ tx }));
-            rx
-        })
+                let (tx, rx) = eventual::Future::pair();
+                self.cache.insert(id, AudioKeyStatus::Loading(vec![tx]));
+                rx
+            })
     }
 }
 
@@ -78,7 +82,7 @@ impl PacketHandler for AudioKeyManager {
         let mut data = Cursor::new(data);
         let seq = data.read_u32::<BigEndian>().unwrap();
 
-        if let Some(status) = self.pending.remove(&seq).and_then(|id| { self.cache.get_mut(&id) }) {
+        if let Some(status) = self.pending.remove(&seq).and_then(|id| self.cache.get_mut(&id)) {
             if cmd == 0xd {
                 let mut key = [0u8; 16];
                 data.read_exact(&mut key).unwrap();
@@ -103,4 +107,3 @@ impl PacketHandler for AudioKeyManager {
         }
     }
 }
-

+ 18 - 11
src/authentication.rs

@@ -24,7 +24,7 @@ fn read_u8<R: Read>(stream: &mut R) -> io::Result<u8> {
 fn read_int<R: Read>(stream: &mut R) -> io::Result<u32> {
     let lo = try!(read_u8(stream)) as u32;
     if lo & 0x80 == 0 {
-        return Ok(lo)
+        return Ok(lo);
     }
 
     let hi = try!(read_u8(stream)) as u32;
@@ -40,7 +40,11 @@ fn read_bytes<R: Read>(stream: &mut R) -> io::Result<Vec<u8>> {
 }
 
 impl Session {
-    fn login(&self, username: String, auth_data: Vec<u8>, typ: AuthenticationType) -> Result<(), ()> {
+    fn login(&self,
+             username: String,
+             auth_data: Vec<u8>,
+             typ: AuthenticationType)
+             -> Result<(), ()> {
         let packet = protobuf_init!(protocol::authentication::ClientResponseEncrypted::new(), {
             login_credentials => {
                 username: username,
@@ -68,9 +72,9 @@ impl Session {
         let (cmd, data) = self.recv();
         match cmd {
             0xac => {
-                let welcome_data : protocol::authentication::APWelcome = 
+                let welcome_data: protocol::authentication::APWelcome =
                     protobuf::parse_from_bytes(&data).unwrap();
-                self.0.data.write().unwrap().canonical_username = 
+                self.0.data.write().unwrap().canonical_username =
                     welcome_data.get_canonical_username().to_string();
 
                 eprintln!("Authenticated !");
@@ -78,8 +82,8 @@ impl Session {
             }
 
             0xad => {
-                let msg : protocol::keyexchange::APLoginFailed = 
-                    protobuf::parse_from_bytes(&data).unwrap();
+                let msg: protocol::keyexchange::APLoginFailed = protobuf::parse_from_bytes(&data)
+                                                                    .unwrap();
                 eprintln!("Authentication failed, {:?}", msg);
                 Err(())
             }
@@ -91,7 +95,8 @@ impl Session {
     }
 
     pub fn login_password(&self, username: String, password: String) -> Result<(), ()> {
-        self.login(username, password.into_bytes(),
+        self.login(username,
+                   password.into_bytes(),
                    AuthenticationType::AUTHENTICATION_USER_PASS)
     }
 
@@ -121,14 +126,16 @@ impl Session {
         let blob = {
             // Anyone know what this block mode is ?
             let mut data = vec![0u8; blob.len()];
-            let mut cipher = aes::ecb_decryptor(
-                aes::KeySize::KeySize192, &key, crypto::blockmodes::NoPadding);
+            let mut cipher = aes::ecb_decryptor(aes::KeySize::KeySize192,
+                                                &key,
+                                                crypto::blockmodes::NoPadding);
             cipher.decrypt(&mut crypto::buffer::RefReadBuffer::new(&blob),
                            &mut crypto::buffer::RefWriteBuffer::new(&mut data),
-                           true).unwrap();
+                           true)
+                  .unwrap();
 
             let l = blob.len();
-            for i in 0..l-0x10 {
+            for i in 0..l - 0x10 {
                 data[l - i - 1] ^= data[l - i - 0x11];
             }
 

+ 6 - 8
src/connection.rs

@@ -9,7 +9,7 @@ use std::result;
 #[derive(Debug)]
 pub enum Error {
     IoError(io::Error),
-    Other
+    Other,
 }
 
 pub type Result<T> = result::Result<T, Error>;
@@ -24,13 +24,13 @@ impl convert::From<byteorder::Error> for Error {
     fn from(err: byteorder::Error) -> Error {
         match err {
             byteorder::Error::Io(e) => Error::IoError(e),
-            _ => Error::Other
+            _ => Error::Other,
         }
     }
 }
 
 pub struct PlainConnection {
-    stream: TcpStream
+    stream: TcpStream,
 }
 
 #[derive(Clone)]
@@ -79,13 +79,12 @@ impl PlainConnection {
 
 impl CipherConnection {
     pub fn new(stream: TcpStream, recv_key: &[u8], send_key: &[u8]) -> CipherConnection {
-        CipherConnection {
-            stream: ShannonStream::new(stream, recv_key, send_key)
-        }
+        CipherConnection { stream: ShannonStream::new(stream, recv_key, send_key) }
     }
 
     pub fn send_packet(&mut self, cmd: u8, data: &[u8]) -> Result<()> {
-        try!(self.stream.write_u8(cmd)); try!(self.stream.write_u16::<BigEndian>(data.len() as u16));
+        try!(self.stream.write_u8(cmd));
+        try!(self.stream.write_u16::<BigEndian>(data.len() as u16));
         try!(self.stream.write(data));
 
         try!(self.stream.finish_send());
@@ -110,4 +109,3 @@ impl CipherConnection {
 pub trait PacketHandler {
     fn handle(&mut self, cmd: u8, data: Vec<u8>);
 }
-

+ 0 - 1
src/diffie_hellman.rs

@@ -48,4 +48,3 @@ impl DHLocalKeys {
         shared_key.to_bytes_be()
     }
 }
-

+ 13 - 11
src/discovery.rs

@@ -15,7 +15,7 @@ use util;
 pub struct DiscoveryManager {
     session: Session,
     private_key: BigUint,
-    public_key: BigUint
+    public_key: BigUint,
 }
 
 fn not_found() -> ResponseBox {
@@ -55,10 +55,10 @@ impl DiscoveryManager {
     }
 
     fn add_user(&self, params: &[(String, String)]) -> ResponseBox {
-        let &(_, ref username) = params.iter().find(|& &(ref key, _)| key == "userName").unwrap();
-        let &(_, ref encrypted_blob) = params.iter().find(|& &(ref key, _)| key == "blob").unwrap();
-        let &(_, ref client_key) = params.iter().find(|& &(ref key, _)| key == "clientKey").unwrap();
-        
+        let &(_, ref username) = params.iter().find(|&&(ref key, _)| key == "userName").unwrap();
+        let &(_, ref encrypted_blob) = params.iter().find(|&&(ref key, _)| key == "blob").unwrap();
+        let &(_, ref client_key) = params.iter().find(|&&(ref key, _)| key == "clientKey").unwrap();
+
         let encrypted_blob = encrypted_blob.from_base64().unwrap();
 
         let client_key = client_key.from_base64().unwrap();
@@ -67,8 +67,8 @@ impl DiscoveryManager {
         let shared_key = util::powm(&client_key, &self.private_key, &DH_PRIME);
 
         let iv = &encrypted_blob[0..16];
-        let encrypted = &encrypted_blob[16..encrypted_blob.len()-20];
-        let cksum = &encrypted_blob[encrypted_blob.len()-20..encrypted_blob.len()];
+        let encrypted = &encrypted_blob[16..encrypted_blob.len() - 20];
+        let cksum = &encrypted_blob[encrypted_blob.len() - 20..encrypted_blob.len()];
 
         let base_key = {
             let mut data = [0u8; 20];
@@ -100,7 +100,9 @@ impl DiscoveryManager {
 
         let decrypted = {
             let mut data = vec![0u8; encrypted.len()];
-            let mut cipher = crypto::aes::ctr(crypto::aes::KeySize::KeySize128, &encryption_key[0..16], &iv);
+            let mut cipher = crypto::aes::ctr(crypto::aes::KeySize::KeySize128,
+                                              &encryption_key[0..16],
+                                              &iv);
             cipher.process(&encrypted, &mut data);
             String::from_utf8(data).unwrap()
         };
@@ -126,7 +128,8 @@ impl DiscoveryManager {
 
         for mut request in server.incoming_requests() {
             let (_, query, _) = url::parse_path(request.url()).unwrap();
-            let mut params = query.map(|q| url::form_urlencoded::parse(q.as_bytes())).unwrap_or(Vec::new());
+            let mut params = query.map(|q| url::form_urlencoded::parse(q.as_bytes()))
+                                  .unwrap_or(Vec::new());
 
             if *request.method() == Method::Post {
                 let mut body = Vec::new();
@@ -137,7 +140,7 @@ impl DiscoveryManager {
 
             println!("{:?}", params);
 
-            let &(_, ref action) = params.iter().find(|& &(ref key, _)| key == "action").unwrap();
+            let &(_, ref action) = params.iter().find(|&&(ref key, _)| key == "action").unwrap();
             match action.as_ref() {
                 "getInfo" => request.respond(self.get_info()).unwrap(),
                 "addUser" => {
@@ -151,4 +154,3 @@ impl DiscoveryManager {
         drop(svc);
     }
 }
-

+ 3 - 3
src/lib.rs

@@ -4,7 +4,8 @@
 
 #![plugin(protobuf_macros)]
 #![plugin(json_macros)]
-#[macro_use] extern crate lazy_static;
+#[macro_use]
+extern crate lazy_static;
 
 extern crate bit_set;
 extern crate byteorder;
@@ -27,7 +28,7 @@ extern crate dns_sd;
 
 extern crate librespot_protocol;
 
-#[macro_use] pub mod util;
+#[macro_use]pub mod util;
 mod audio_decrypt;
 mod audio_file;
 mod audio_key;
@@ -42,4 +43,3 @@ pub mod session;
 pub mod spirc;
 mod stream;
 mod zeroconf;
-

+ 18 - 22
src/main.rs

@@ -36,17 +36,16 @@ fn main() {
         .optopt("b", "bitrate", "Bitrate (96, 160 or 320). Defaults to 160", "BITRATE");
 
     let matches = match opts.parse(&args[1..]) {
-        Ok(m) => { m },
-        Err(f) => { 
-                print!("Error: {}\n{}", f.to_string(), usage(&*program, &opts));
-                return;
+        Ok(m) => m,
+        Err(f) => {
+            print!("Error: {}\n{}", f.to_string(), usage(&*program, &opts));
+            return;
         }
     };
 
     let appkey = {
-        let mut file = File::open(
-            Path::new(&*matches.opt_str("a").unwrap())
-        ).expect("Could not open app key.");
+        let mut file = File::open(Path::new(&*matches.opt_str("a").unwrap()))
+                           .expect("Could not open app key.");
 
         let mut data = Vec::new();
         file.read_to_end(&mut data).unwrap();
@@ -59,25 +58,25 @@ fn main() {
     let name = matches.opt_str("n").unwrap();
 
     let credentials = username.map(|u| {
-        let password = matches.opt_str("p").or_else(|| {
-            std::env::var(PASSWORD_ENV_NAME).ok()
-        }).unwrap_or_else(|| {
-            print!("Password: ");
-            stdout().flush().unwrap();
-            read_password().unwrap()
-        });
+        let password = matches.opt_str("p")
+                              .or_else(|| std::env::var(PASSWORD_ENV_NAME).ok())
+                              .unwrap_or_else(|| {
+                                  print!("Password: ");
+                                  stdout().flush().unwrap();
+                                  read_password().unwrap()
+                              });
 
         (u, password)
     });
     std::env::remove_var(PASSWORD_ENV_NAME);
 
     let bitrate = match matches.opt_str("b").as_ref().map(String::as_ref) {
-        None        => Bitrate::Bitrate160, // default value
+        None => Bitrate::Bitrate160, // default value
 
-        Some("96")  => Bitrate::Bitrate96,
+        Some("96") => Bitrate::Bitrate96,
         Some("160") => Bitrate::Bitrate160,
         Some("320") => Bitrate::Bitrate320,
-        Some(b)     => panic!("Invalid bitrate {}", b),
+        Some(b) => panic!("Invalid bitrate {}", b),
     };
 
     let config = Config {
@@ -85,7 +84,7 @@ fn main() {
         user_agent: version_string(),
         device_name: name,
         cache_location: PathBuf::from(cache_location),
-        bitrate: bitrate
+        bitrate: bitrate,
     };
 
     let session = Session::new(config);
@@ -99,12 +98,9 @@ fn main() {
 
     let player = Player::new(session.clone());
     let mut spirc = SpircManager::new(session.clone(), player);
-    thread::spawn(move || {
-        spirc.run()
-    });
+    thread::spawn(move || spirc.run());
 
     loop {
         session.poll();
     }
 }
-

+ 31 - 27
src/mercury.rs

@@ -22,13 +22,13 @@ pub struct MercuryRequest {
     pub method: MercuryMethod,
     pub uri: String,
     pub content_type: Option<String>,
-    pub payload: Vec<Vec<u8>>
+    pub payload: Vec<Vec<u8>>,
 }
 
 #[derive(Debug)]
 pub struct MercuryResponse {
     pub uri: String,
-    pub payload: Vec<Vec<u8>>
+    pub payload: Vec<Vec<u8>>,
 }
 
 enum MercuryCallback {
@@ -40,7 +40,7 @@ enum MercuryCallback {
 pub struct MercuryPending {
     parts: Vec<Vec<u8>>,
     partial: Option<Vec<u8>>,
-    callback: MercuryCallback
+    callback: MercuryCallback,
 }
 
 pub struct MercuryManager {
@@ -55,8 +55,9 @@ impl ToString for MercuryMethod {
             MercuryMethod::GET => "GET",
             MercuryMethod::SUB => "SUB",
             MercuryMethod::UNSUB => "UNSUB",
-            MercuryMethod::SEND => "SEND"
-        }.to_owned()
+            MercuryMethod::SEND => "SEND",
+        }
+        .to_owned()
     }
 }
 
@@ -71,7 +72,7 @@ impl MercuryManager {
 
     fn request_with_callback(&mut self,
                              session: &Session,
-                             req: MercuryRequest, 
+                             req: MercuryRequest,
                              cb: MercuryCallback) {
         let mut seq = [0u8; 4];
         BigEndian::write_u32(&mut seq, self.next_seq);
@@ -86,30 +87,34 @@ impl MercuryManager {
 
         session.send_packet(cmd, &data).unwrap();
 
-        self.pending.insert(seq.to_vec(), MercuryPending{
-            parts: Vec::new(),
-            partial: None,
-            callback: cb,
-        });
+        self.pending.insert(seq.to_vec(),
+                            MercuryPending {
+                                parts: Vec::new(),
+                                partial: None,
+                                callback: cb,
+                            });
     }
 
-    pub fn request(&mut self, session: &Session, req: MercuryRequest)
-            -> eventual::Future<MercuryResponse, ()> {
+    pub fn request(&mut self,
+                   session: &Session,
+                   req: MercuryRequest)
+                   -> eventual::Future<MercuryResponse, ()> {
         let (tx, rx) = eventual::Future::pair();
         self.request_with_callback(session, req, MercuryCallback::Future(tx));
         rx
     }
 
-    pub fn subscribe(&mut self, session: &Session, uri: String)
-        -> mpsc::Receiver<MercuryResponse> {
+    pub fn subscribe(&mut self, session: &Session, uri: String) -> mpsc::Receiver<MercuryResponse> {
         let (tx, rx) = mpsc::channel();
 
-        self.request_with_callback(session, MercuryRequest{
-            method: MercuryMethod::SUB,
-            uri: uri,
-            content_type: None,
-            payload: Vec::new()
-        }, MercuryCallback::Subscription(tx));
+        self.request_with_callback(session,
+                                   MercuryRequest {
+                                       method: MercuryMethod::SUB,
+                                       uri: uri,
+                                       content_type: None,
+                                       payload: Vec::new(),
+                                   },
+                                   MercuryCallback::Subscription(tx));
 
         rx
     }
@@ -126,7 +131,8 @@ impl MercuryManager {
                              response: MercuryResponse,
                              tx: mpsc::Sender<MercuryResponse>) {
         for sub_data in response.payload {
-            if let Ok(mut sub) = protobuf::parse_from_bytes::<protocol::pubsub::Subscription>(&sub_data) {
+            if let Ok(mut sub) =
+                   protobuf::parse_from_bytes::<protocol::pubsub::Subscription>(&sub_data) {
                 self.subscriptions.insert(sub.take_uri(), tx.clone());
             }
         }
@@ -134,12 +140,11 @@ impl MercuryManager {
 
     fn complete_request(&mut self, mut pending: MercuryPending) {
         let header_data = pending.parts.remove(0);
-        let header : protocol::mercury::Header =
-            protobuf::parse_from_bytes(&header_data).unwrap();
+        let header: protocol::mercury::Header = protobuf::parse_from_bytes(&header_data).unwrap();
 
         let response = MercuryResponse {
             uri: header.get_uri().to_owned(),
-            payload: pending.parts
+            payload: pending.parts,
         };
 
         match pending.callback {
@@ -203,7 +208,7 @@ impl PacketHandler for MercuryManager {
             }
         } else {
             println!("Ignore seq {:?} cmd {}", seq, cmd);
-            return
+            return;
         };
 
         for i in 0..count {
@@ -227,4 +232,3 @@ impl PacketHandler for MercuryManager {
         }
     }
 }
-

+ 51 - 44
src/metadata.rs

@@ -13,12 +13,14 @@ fn countrylist_contains(list: &str, country: &str) -> bool {
 }
 
 fn parse_restrictions<'s, I>(restrictions: I, country: &str, catalogue: &str) -> bool
-        where I : Iterator<Item=&'s protocol::metadata::Restriction> {
-    restrictions
-        .filter(|r| r.get_catalogue_str().contains(&catalogue.to_owned()))
-        .all(|r| !countrylist_contains(r.get_countries_forbidden(), country)
-             && (!r.has_countries_allowed()
-                 || countrylist_contains(r.get_countries_allowed(), country)))
+    where I: Iterator<Item = &'s protocol::metadata::Restriction>
+{
+    restrictions.filter(|r| r.get_catalogue_str().contains(&catalogue.to_owned()))
+                .all(|r| {
+                    !countrylist_contains(r.get_countries_forbidden(), country) &&
+                    (!r.has_countries_allowed() ||
+                     countrylist_contains(r.get_countries_allowed(), country))
+                })
 }
 
 pub trait MetadataTrait : Send + 'static {
@@ -43,7 +45,7 @@ pub struct Album {
     pub id: SpotifyId,
     pub name: String,
     pub artists: Vec<SpotifyId>,
-    pub covers: Vec<FileId>
+    pub covers: Vec<FileId>,
 }
 
 #[derive(Debug)]
@@ -69,20 +71,21 @@ impl MetadataTrait for Track {
             id: SpotifyId::from_raw(msg.get_gid()),
             name: msg.get_name().to_owned(),
             album: SpotifyId::from_raw(msg.get_album().get_gid()),
-            files: msg.get_file().iter()
-                .map(|file| {
-                    let mut dst = [0u8; 20];
-                    dst.clone_from_slice(&file.get_file_id());
-                    (FileId(dst), file.get_format())
-                })
-                .collect(),
-            alternatives: msg.get_alternative().iter()
-                .map(|alt| SpotifyId::from_raw(alt.get_gid()))
-                .collect(),
-            available: parse_restrictions(
-                msg.get_restriction().iter(),
-                &session.0.data.read().unwrap().country,
-                "premium"),
+            files: msg.get_file()
+                      .iter()
+                      .map(|file| {
+                          let mut dst = [0u8; 20];
+                          dst.clone_from_slice(&file.get_file_id());
+                          (FileId(dst), file.get_format())
+                      })
+                      .collect(),
+            alternatives: msg.get_alternative()
+                             .iter()
+                             .map(|alt| SpotifyId::from_raw(alt.get_gid()))
+                             .collect(),
+            available: parse_restrictions(msg.get_restriction().iter(),
+                                          &session.0.data.read().unwrap().country,
+                                          "premium"),
         }
     }
 }
@@ -98,16 +101,19 @@ impl MetadataTrait for Album {
         Album {
             id: SpotifyId::from_raw(msg.get_gid()),
             name: msg.get_name().to_owned(),
-            artists: msg.get_artist().iter()
-                .map(|a| SpotifyId::from_raw(a.get_gid()))
-                .collect(),
-            covers: msg.get_cover_group().get_image().iter()
-                .map(|image| {
-                    let mut dst = [0u8; 20];
-                    dst.clone_from_slice(&image.get_file_id());
-                    FileId(dst)
-                })
-                .collect(),
+            artists: msg.get_artist()
+                        .iter()
+                        .map(|a| SpotifyId::from_raw(a.get_gid()))
+                        .collect(),
+            covers: msg.get_cover_group()
+                       .get_image()
+                       .iter()
+                       .map(|image| {
+                           let mut dst = [0u8; 20];
+                           dst.clone_from_slice(&image.get_file_id());
+                           FileId(dst)
+                       })
+                       .collect(),
         }
     }
 }
@@ -135,21 +141,22 @@ impl MetadataManager {
         MetadataManager
     }
 
-    pub fn get<T: MetadataTrait>(&mut self, session: &Session, id: SpotifyId)
-          -> MetadataRef<T> {
+    pub fn get<T: MetadataTrait>(&mut self, session: &Session, id: SpotifyId) -> MetadataRef<T> {
 
         let _session = session.clone();
         session.mercury(MercuryRequest {
-            method: MercuryMethod::GET,
-            uri: format!("{}/{}", T::base_url(), id.to_base16()),
-            content_type: None,
-            payload: Vec::new()
-        }).and_then(move |response| {
-            let msg : T::Message = protobuf::parse_from_bytes(
-                response.payload.first().unwrap()).unwrap();
-
-            Ok(T::parse(&msg, &_session))
-        })
+                   method: MercuryMethod::GET,
+                   uri: format!("{}/{}", T::base_url(), id.to_base16()),
+                   content_type: None,
+                   payload: Vec::new(),
+               })
+               .and_then(move |response| {
+                   let msg: T::Message = protobuf::parse_from_bytes(response.payload
+                                                                            .first()
+                                                                            .unwrap())
+                                             .unwrap();
+
+                   Ok(T::parse(&msg, &_session))
+               })
     }
 }
-

+ 31 - 26
src/player.rs

@@ -22,7 +22,7 @@ pub struct PlayerState {
     position_measured_at: i64,
     update_time: i64,
 
-    end_of_track: bool
+    end_of_track: bool,
 }
 
 struct PlayerInternal {
@@ -36,7 +36,7 @@ enum PlayerCommand {
     Play,
     Pause,
     Stop,
-    Seek(u32)
+    Seek(u32),
 }
 
 impl Player {
@@ -49,17 +49,16 @@ impl Player {
             position_measured_at: 0,
             update_time: util::now_ms(),
             end_of_track: false,
-        }), Condvar::new()));
+        }),
+                              Condvar::new()));
 
         let internal = PlayerInternal {
             session: session,
             commands: cmd_rx,
-            state: state.clone()
+            state: state.clone(),
         };
 
-        thread::spawn(move || {
-            internal.run()
-        });
+        thread::spawn(move || internal.run());
 
         Player {
             commands: cmd_tx,
@@ -113,11 +112,17 @@ impl PlayerInternal {
                     let mut track = self.session.metadata::<Track>(track_id).await().unwrap();
 
                     if !track.available {
-                        let alternatives = track.alternatives.iter()
-                            .map(|alt_id| self.session.metadata::<Track>(*alt_id))
-                            .collect::<Vec<TrackRef>>();
-
-                        track = eventual::sequence(alternatives.into_iter()).iter().find(|alt| alt.available).unwrap();
+                        let alternatives = track.alternatives
+                                                .iter()
+                                                .map(|alt_id| {
+                                                    self.session.metadata::<Track>(*alt_id)
+                                                })
+                                                .collect::<Vec<TrackRef>>();
+
+                        track = eventual::sequence(alternatives.into_iter())
+                                    .iter()
+                                    .find(|alt| alt.available)
+                                    .unwrap();
                     }
 
                     let format = match self.session.0.config.bitrate {
@@ -152,11 +157,12 @@ impl PlayerInternal {
                 Some(PlayerCommand::Seek(ms)) => {
                     decoder.as_mut().unwrap().time_seek(ms as f64 / 1000f64).unwrap();
                     self.update(|state| {
-                        state.position_ms = (decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
+                        state.position_ms =
+                            (decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
                         state.position_measured_at = util::now_ms();
                         return true;
                     });
-                },
+                }
                 Some(PlayerCommand::Play) => {
                     self.update(|state| {
                         state.status = PlayStatus::kPlayStatusPlay;
@@ -164,7 +170,7 @@ impl PlayerInternal {
                     });
 
                     stream.start().unwrap();
-                },
+                }
                 Some(PlayerCommand::Pause) => {
                     self.update(|state| {
                         state.status = PlayStatus::kPlayStatusPause;
@@ -173,7 +179,7 @@ impl PlayerInternal {
                     });
 
                     stream.stop().unwrap();
-                },
+                }
                 Some(PlayerCommand::Stop) => {
                     self.update(|state| {
                         if state.status == PlayStatus::kPlayStatusPlay {
@@ -184,7 +190,7 @@ impl PlayerInternal {
 
                     stream.stop().unwrap();
                     decoder = None;
-                },
+                }
                 None => (),
             }
 
@@ -193,11 +199,10 @@ impl PlayerInternal {
                     Some(Ok(packet)) => {
                         match stream.write(&packet.data) {
                             Ok(_) => (),
-                            Err(portaudio::PaError::OutputUnderflowed)
-                                => eprintln!("Underflow"),
-                            Err(e) => panic!("PA Error {}", e)
+                            Err(portaudio::PaError::OutputUnderflowed) => eprintln!("Underflow"),
+                            Err(e) => panic!("PA Error {}", e),
                         };
-                    },
+                    }
                     Some(Err(vorbis::VorbisError::Hole)) => (),
                     Some(Err(e)) => panic!("Vorbis error {:?}", e),
                     None => {
@@ -216,7 +221,8 @@ impl PlayerInternal {
                     let now = util::now_ms();
 
                     if now - state.position_measured_at > 5000 {
-                        state.position_ms = (decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
+                        state.position_ms =
+                            (decoder.as_mut().unwrap().time_tell().unwrap() * 1000f64) as u32;
                         state.position_measured_at = now;
                         return true;
                     } else {
@@ -232,7 +238,8 @@ impl PlayerInternal {
     }
 
     fn update<F>(&self, f: F)
-        where F: FnOnce(&mut MutexGuard<PlayerState>) -> bool {
+        where F: FnOnce(&mut MutexGuard<PlayerState>) -> bool
+    {
         let mut guard = self.state.0.lock().unwrap();
         let update = f(&mut guard);
         if update {
@@ -245,8 +252,7 @@ impl PlayerInternal {
 impl SpircDelegate for Player {
     type State = PlayerState;
 
-    fn load(&self, track: SpotifyId,
-            start_playing: bool, position_ms: u32) {
+    fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32) {
         self.command(PlayerCommand::Load(track, start_playing, position_ms));
     }
 
@@ -308,4 +314,3 @@ impl SpircState for PlayerState {
         return self.end_of_track;
     }
 }
-

+ 14 - 17
src/session.rs

@@ -25,7 +25,7 @@ use util;
 pub enum Bitrate {
     Bitrate96,
     Bitrate160,
-    Bitrate320
+    Bitrate320,
 }
 
 pub struct Config {
@@ -123,12 +123,12 @@ impl Session {
             }
         });
 
-        let init_client_packet =
-            connection.send_packet_prefix(&[0,4], &request.write_to_bytes().unwrap()).unwrap();
-        let init_server_packet =
-            connection.recv_packet().unwrap();
+        let init_client_packet = connection.send_packet_prefix(&[0, 4],
+                                                               &request.write_to_bytes().unwrap())
+                                           .unwrap();
+        let init_server_packet = connection.recv_packet().unwrap();
 
-        let response : protocol::keyexchange::APResponseMessage =
+        let response: protocol::keyexchange::APResponseMessage =
             protobuf::parse_from_bytes(&init_server_packet[4..]).unwrap();
 
         let remote_key = response.get_challenge()
@@ -160,7 +160,7 @@ impl Session {
 
         let packet = protobuf_init!(protocol::keyexchange::ClientResponsePlaintext::new(), {
             login_crypto_response.diffie_hellman => {
-                hmac: challenge 
+                hmac: challenge
             },
             pow_response => {},
             crypto_response => {},
@@ -169,10 +169,9 @@ impl Session {
 
         connection.send_packet(&packet.write_to_bytes().unwrap()).unwrap();
 
-        let cipher_connection = CipherConnection::new(
-            connection.into_stream(),
-            &send_key,
-            &recv_key);
+        let cipher_connection = CipherConnection::new(connection.into_stream(),
+                                                      &send_key,
+                                                      &recv_key);
 
         *self.0.rx_connection.lock().unwrap() = Some(cipher_connection.clone());
         *self.0.tx_connection.lock().unwrap() = Some(cipher_connection);
@@ -184,14 +183,13 @@ impl Session {
         match cmd {
             0x4 => self.send_packet(0x49, &data).unwrap(),
             0x4a => (),
-            0x9  => self.0.stream.lock().unwrap().handle(cmd, data),
+            0x9 => self.0.stream.lock().unwrap().handle(cmd, data),
             0xd | 0xe => self.0.audio_key.lock().unwrap().handle(cmd, data),
             0x1b => {
-                self.0.data.write().unwrap().country =
-                    String::from_utf8(data).unwrap();
-            },
+                self.0.data.write().unwrap().country = String::from_utf8(data).unwrap();
+            }
             0xb2...0xb6 => self.0.mercury.lock().unwrap().handle(cmd, data),
-            _ => ()
+            _ => (),
         }
     }
 
@@ -227,4 +225,3 @@ impl Session {
         self.0.mercury.lock().unwrap().subscribe(self, uri)
     }
 }
-

+ 28 - 19
src/spirc.rs

@@ -34,14 +34,13 @@ pub struct SpircManager<D: SpircDelegate> {
     last_command_msgid: u32,
 
     tracks: Vec<SpotifyId>,
-    index: u32
+    index: u32,
 }
 
 pub trait SpircDelegate {
     type State : SpircState;
 
-    fn load(&self, track: SpotifyId,
-            start_playing: bool, position_ms: u32);
+    fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32);
     fn play(&self);
     fn pause(&self);
     fn seek(&self, position_ms: u32);
@@ -58,9 +57,8 @@ pub trait SpircState {
     fn end_of_track(&self) -> bool;
 }
 
-impl <D: SpircDelegate> SpircManager<D> {
-    pub fn new(session: Session, delegate: D)
-            -> SpircManager<D> {
+impl<D: SpircDelegate> SpircManager<D> {
+    pub fn new(session: Session, delegate: D) -> SpircManager<D> {
 
         let ident = session.0.data.read().unwrap().device_id.clone();
         let name = session.0.config.device_name.clone();
@@ -88,13 +86,19 @@ impl <D: SpircDelegate> SpircManager<D> {
             last_command_msgid: 0,
 
             tracks: Vec::new(),
-            index: 0
+            index: 0,
         }
     }
 
     pub fn run(&mut self) {
         let rx = self.session.mercury_sub(format!("hm://remote/user/{}/",
-                    self.session.0.data.read().unwrap().canonical_username.clone()));
+                                                  self.session
+                                                      .0
+                                                      .data
+                                                      .read()
+                                                      .unwrap()
+                                                      .canonical_username
+                                                      .clone()));
         let updates = self.delegate.updates();
 
         self.notify(true, None);
@@ -149,9 +153,11 @@ impl <D: SpircDelegate> SpircManager<D> {
 
 
                 self.index = frame.get_state().get_playing_track_index();
-                self.tracks = frame.get_state().get_track().iter()
-                    .map(|track| SpotifyId::from_raw(track.get_gid()))
-                    .collect();
+                self.tracks = frame.get_state()
+                                   .get_track()
+                                   .iter()
+                                   .map(|track| SpotifyId::from_raw(track.get_gid()))
+                                   .collect();
 
                 let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
                 let track = self.tracks[self.index as usize];
@@ -173,7 +179,7 @@ impl <D: SpircDelegate> SpircManager<D> {
                     self.delegate.stop();
                 }
             }
-            _ => ()
+            _ => (),
         }
     }
 
@@ -200,13 +206,16 @@ impl <D: SpircDelegate> SpircManager<D> {
             pkt.set_state(self.spirc_state());
         }
 
-        self.session.mercury(MercuryRequest{
-            method: MercuryMethod::SEND,
-            uri: format!("hm://remote/user/{}", 
-                         self.session.0.data.read().unwrap().canonical_username.clone()),
-            content_type: None,
-            payload: vec![ pkt.write_to_bytes().unwrap() ]
-        }).await().unwrap();
+        self.session
+            .mercury(MercuryRequest {
+                method: MercuryMethod::SEND,
+                uri: format!("hm://remote/user/{}",
+                             self.session.0.data.read().unwrap().canonical_username.clone()),
+                content_type: None,
+                payload: vec![pkt.write_to_bytes().unwrap()],
+            })
+            .await()
+            .unwrap();
     }
 
     fn spirc_state(&self) -> protocol::spirc::State {

+ 24 - 18
src/stream.rs

@@ -17,12 +17,12 @@ type ChannelId = u16;
 
 enum ChannelMode {
     Header,
-    Data
+    Data,
 }
 
 struct Channel {
     mode: ChannelMode,
-    callback: mpsc::Sender<StreamEvent>
+    callback: mpsc::Sender<StreamEvent>,
 }
 
 pub struct StreamManager {
@@ -38,16 +38,19 @@ impl StreamManager {
         }
     }
 
-    pub fn request(&mut self, session: &Session,
-                   file: FileId, offset: u32, size: u32)
-        -> mpsc::Receiver<StreamEvent> {
+    pub fn request(&mut self,
+                   session: &Session,
+                   file: FileId,
+                   offset: u32,
+                   size: u32)
+                   -> mpsc::Receiver<StreamEvent> {
 
         let (tx, rx) = mpsc::channel();
 
         let channel_id = self.next_id;
         self.next_id += 1;
 
-        let mut data : Vec<u8> = Vec::new();
+        let mut data: Vec<u8> = Vec::new();
         data.write_u16::<BigEndian>(channel_id).unwrap();
         data.write_u8(0).unwrap();
         data.write_u8(1).unwrap();
@@ -61,10 +64,11 @@ impl StreamManager {
 
         session.send_packet(0x8, &data).unwrap();
 
-        self.channels.insert(channel_id, Channel {
-            mode: ChannelMode::Header,
-            callback: tx
-        });
+        self.channels.insert(channel_id,
+                             Channel {
+                                 mode: ChannelMode::Header,
+                                 callback: tx,
+                             });
 
         rx
     }
@@ -75,12 +79,14 @@ impl PacketHandler for StreamManager {
         let data = ArcVec::new(data);
         let mut packet = Cursor::new(&data as &[u8]);
 
-        let id : ChannelId = packet.read_u16::<BigEndian>().unwrap();
+        let id: ChannelId = packet.read_u16::<BigEndian>().unwrap();
         let mut close = false;
         {
             let channel = match self.channels.get_mut(&id) {
                 Some(ch) => ch,
-                None => { return; }
+                None => {
+                    return;
+                }
             };
 
             match channel.mode {
@@ -105,7 +111,7 @@ impl PacketHandler for StreamManager {
                             packet.seek(SeekFrom::Current(length as i64 - 1)).unwrap();
                         }
                     }
-                    
+
                     if length == 0 {
                         channel.mode = ChannelMode::Data;
                     }
@@ -114,10 +120,11 @@ impl PacketHandler for StreamManager {
                 ChannelMode::Data => {
                     if packet.position() < data.len() as u64 {
                         channel.callback
-                            .send(StreamEvent::Data(data.clone().offset(packet.position() as usize)))
-                            .unwrap_or_else(|_| {
-                                close = true;
-                            });
+                               .send(StreamEvent::Data(data.clone()
+                                                           .offset(packet.position() as usize)))
+                               .unwrap_or_else(|_| {
+                                   close = true;
+                               });
                     } else {
                         close = true;
                     }
@@ -130,4 +137,3 @@ impl PacketHandler for StreamManager {
         }
     }
 }
-

+ 4 - 5
src/util/arcvec.rs

@@ -9,13 +9,13 @@ pub struct ArcVec<T> {
     length: usize,
 }
 
-impl <T> ArcVec<T> {
+impl<T> ArcVec<T> {
     pub fn new(data: Vec<T>) -> ArcVec<T> {
         let length = data.len();
         ArcVec {
             data: Arc::new(data),
             offset: 0,
-            length: length
+            length: length,
         }
     }
 
@@ -40,13 +40,12 @@ impl<T> Deref for ArcVec<T> {
     type Target = [T];
 
     fn deref(&self) -> &[T] {
-        &self.data[self.offset..self.offset+self.length]
+        &self.data[self.offset..self.offset + self.length]
     }
 }
 
-impl<T : fmt::Debug> fmt::Debug for ArcVec<T> {
+impl<T: fmt::Debug> fmt::Debug for ArcVec<T> {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
         self.deref().fmt(formatter)
     }
 }
-

+ 26 - 16
src/util/int128.rs

@@ -4,12 +4,15 @@ use std;
 #[allow(non_camel_case_types)]
 pub struct u128 {
     high: u64,
-    low: u64
+    low: u64,
 }
 
 impl u128 {
     pub fn from_parts(high: u64, low: u64) -> u128 {
-        u128 { high: high, low: low }
+        u128 {
+            high: high,
+            low: low,
+        }
     }
 
     pub fn parts(&self) -> (u64, u64) {
@@ -28,18 +31,26 @@ impl std::ops::Add<u128> for 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 };
+                   if low < self.low {
+            1
+        } else {
+            0
+        };
 
         u128::from_parts(high, low)
     }
 }
 
-impl <'a> std::ops::Add<&'a u128> for u128 {
+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 };
+                   if low < self.low {
+            1
+        } else {
+            0
+        };
 
         u128::from_parts(high, low)
     }
@@ -56,19 +67,21 @@ impl std::ops::Mul<u128> 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 = [std::num::Zero::zero(); 16];
         for i in 0..4 {
             for j in 0..4 {
                 let shift = i + j;
-                let product = top[3-i] * bottom[3-j];
+                let product = top[3 - i] * bottom[3 - j];
                 let (high, low) = match shift {
                     0 => (0, product),
                     1 => (product >> 32, product << 32),
@@ -76,8 +89,7 @@ impl std::ops::Mul<u128> for u128 {
                     3 => (product << 32, 0),
                     _ => {
                         if product != 0 {
-                            panic!("Overflow on mul {:?} {:?} ({} {})",
-                                self, rhs, i, j)
+                            panic!("Overflow on mul {:?} {:?} ({} {})", self, rhs, i, j)
                         } else {
                             (0, 0)
                         }
@@ -90,5 +102,3 @@ impl std::ops::Mul<u128> for u128 {
         rows.iter().sum::<u128>()
     }
 }
-
-

+ 10 - 10
src/util/mod.rs

@@ -1,5 +1,5 @@
 use num::{BigUint, Integer, Zero, One};
-use rand::{Rng,Rand};
+use rand::{Rng, Rand};
 use std::io;
 use std::ops::{Mul, Rem, Shr};
 use std::fs;
@@ -44,7 +44,7 @@ pub fn rand_vec<G: Rng, R: Rand>(rng: &mut G, size: usize) -> Vec<R> {
         vec.push(R::rand(rng));
     }
 
-    return vec
+    return vec;
 }
 
 pub mod version {
@@ -66,10 +66,10 @@ pub trait IgnoreExt {
     fn ignore(self);
 }
 
-impl <T, E> IgnoreExt for Result<T, E> {
+impl<T, E> IgnoreExt for Result<T, E> {
     fn ignore(self) {
         match self {
-            Ok(_)  => (),
+            Ok(_) => (),
             Err(_) => (),
         }
     }
@@ -81,18 +81,19 @@ pub fn now_ms() -> i64 {
 }
 
 pub fn mkdir_existing(path: &Path) -> io::Result<()> {
-    fs::create_dir(path)
-        .or_else(|err| if err.kind() == io::ErrorKind::AlreadyExists {
+    fs::create_dir(path).or_else(|err| {
+        if err.kind() == io::ErrorKind::AlreadyExists {
             Ok(())
         } else {
             Err(err)
-        })
+        }
+    })
 }
 
 pub fn powm(base: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
     let mut base = base.clone();
     let mut exp = exp.clone();
-    let mut result : BigUint = One::one();
+    let mut result: BigUint = One::one();
 
     while !exp.is_zero() {
         if exp.is_odd() {
@@ -117,7 +118,7 @@ impl StrChunksExt for str {
     }
 }
 
-impl <'s> Iterator for StrChunks<'s> {
+impl<'s> Iterator for StrChunks<'s> {
     type Item = &'s str;
     fn next(&mut self) -> Option<&'s str> {
         let &mut StrChunks(data, size) = self;
@@ -130,4 +131,3 @@ impl <'s> Iterator for StrChunks<'s> {
         }
     }
 }
-

+ 10 - 9
src/util/spotify_id.rs

@@ -1,6 +1,6 @@
 use std;
 use util::u128;
-use byteorder::{BigEndian,ByteOrder};
+use byteorder::{BigEndian, ByteOrder};
 use std::ascii::AsciiExt;
 
 #[derive(Debug,Copy,Clone,PartialEq,Eq,Hash)]
@@ -9,7 +9,8 @@ pub struct SpotifyId(u128);
 #[derive(Debug,Copy,Clone,PartialEq,Eq,Hash)]
 pub struct FileId(pub [u8; 20]);
 
-const BASE62_DIGITS: &'static [u8] = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+const BASE62_DIGITS: &'static [u8] =
+    b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
 const BASE16_DIGITS: &'static [u8] = b"0123456789abcdef";
 
 impl SpotifyId {
@@ -17,7 +18,7 @@ impl SpotifyId {
         assert!(id.is_ascii());
         let data = id.as_bytes();
 
-        let mut n : u128 = std::num::Zero::zero();
+        let mut n: u128 = std::num::Zero::zero();
         for c in data {
             let d = BASE16_DIGITS.iter().position(|e| e == c).unwrap() as u8;
             n = n * u128::from(16);
@@ -31,7 +32,7 @@ impl SpotifyId {
         assert!(id.is_ascii());
         let data = id.as_bytes();
 
-        let mut n : u128 = std::num::Zero::zero();
+        let mut n: u128 = std::num::Zero::zero();
         for c in data {
             let d = BASE62_DIGITS.iter().position(|e| e == c).unwrap() as u8;
             n = n * u128::from(62);
@@ -56,10 +57,10 @@ impl SpotifyId {
 
         let mut data = [0u8; 32];
         for i in 0..16 {
-            data[31-i] = BASE16_DIGITS[(low.wrapping_shr(4 * i as u32) & 0xF) as usize];
+            data[31 - i] = BASE16_DIGITS[(low.wrapping_shr(4 * i as u32) & 0xF) as usize];
         }
         for i in 0..16 {
-            data[15-i] = BASE16_DIGITS[(high.wrapping_shr(4 * i as u32) & 0xF) as usize];
+            data[15 - i] = BASE16_DIGITS[(high.wrapping_shr(4 * i as u32) & 0xF) as usize];
         }
 
         std::str::from_utf8(&data).unwrap().to_owned()
@@ -71,7 +72,7 @@ impl SpotifyId {
 
         let mut data = [0u8; 16];
 
-        BigEndian::write_u64(&mut data[0..8],  high);
+        BigEndian::write_u64(&mut data[0..8], high);
         BigEndian::write_u64(&mut data[8..16], low);
 
         data
@@ -80,10 +81,10 @@ impl SpotifyId {
 
 impl FileId {
     pub fn to_base16(&self) -> String {
-        self.0.iter()
+        self.0
+            .iter()
             .map(|b| format!("{:02x}", b))
             .collect::<Vec<String>>()
             .concat()
     }
 }
-

+ 8 - 9
src/util/subfile.rs

@@ -2,39 +2,38 @@ use std::io::{Read, Seek, SeekFrom, Result};
 
 pub struct Subfile<T: Read + Seek> {
     stream: T,
-    offset: u64
+    offset: u64,
 }
 
-impl <T: Read + Seek> Subfile<T> {
+impl<T: Read + Seek> Subfile<T> {
     pub fn new(mut stream: T, offset: u64) -> Subfile<T> {
         stream.seek(SeekFrom::Start(offset)).unwrap();
         Subfile {
             stream: stream,
-            offset: offset
+            offset: offset,
         }
     }
 }
 
-impl <T: Read + Seek> Read for Subfile<T> {
+impl<T: Read + Seek> Read for Subfile<T> {
     fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
         self.stream.read(buf)
     }
 }
 
-impl <T: Read + Seek> Seek for Subfile<T> {
+impl<T: Read + Seek> Seek for Subfile<T> {
     fn seek(&mut self, mut pos: SeekFrom) -> Result<u64> {
         pos = match pos {
             SeekFrom::Start(offset) => SeekFrom::Start(offset + self.offset),
-            x => x
+            x => x,
         };
 
         let newpos = try!(self.stream.seek(pos));
 
         if newpos > self.offset {
-            return Ok(newpos - self.offset)
+            return Ok(newpos - self.offset);
         } else {
-            return Ok(0)
+            return Ok(0);
         }
     }
 }
-

+ 2 - 3
src/util/zerofile.rs

@@ -3,14 +3,14 @@ use std::cmp::{min, max};
 
 pub struct ZeroFile {
     position: u64,
-    size: u64
+    size: u64,
 }
 
 impl ZeroFile {
     pub fn new(size: u64) -> ZeroFile {
         ZeroFile {
             position: 0,
-            size: size
+            size: size,
         }
     }
 }
@@ -41,4 +41,3 @@ impl io::Read for ZeroFile {
         Ok(len)
     }
 }
-

+ 2 - 1
src/zeroconf.rs

@@ -22,7 +22,8 @@ pub mod stub {
                         _: &[&str])
                         -> std::result::Result<DNSService, DNSError> {
             writeln!(&mut std::io::stderr(),
-                     "WARNING: dns-sd is not enabled. Service will probably not be visible").unwrap();
+                     "WARNING: dns-sd is not enabled. Service will probably not be visible")
+                .unwrap();
             Ok(DNSService)
         }
     }