Pārlūkot izejas kodu

Improve handling of missing audio keys by failing the future rather than crashing.

Paul Lietar 9 gadi atpakaļ
vecāks
revīzija
654a403459
3 mainītis faili ar 32 papildinājumiem un 16 dzēšanām
  1. 28 12
      src/audio_key.rs
  2. 2 2
      src/metadata.rs
  3. 2 2
      src/session.rs

+ 28 - 12
src/audio_key.rs

@@ -9,13 +9,16 @@ use session::Session;
 use connection::PacketHandler;
 use connection::PacketHandler;
 
 
 pub type AudioKey = [u8; 16];
 pub type AudioKey = [u8; 16];
+#[derive(Debug,Hash,PartialEq,Eq,Copy,Clone)]
+pub struct AudioKeyError;
 
 
 #[derive(Debug,Hash,PartialEq,Eq,Clone)]
 #[derive(Debug,Hash,PartialEq,Eq,Clone)]
 struct AudioKeyId(SpotifyId, FileId);
 struct AudioKeyId(SpotifyId, FileId);
 
 
 enum AudioKeyStatus {
 enum AudioKeyStatus {
-    Loading(Vec<eventual::Complete<AudioKey, ()>>),
-    Loaded(AudioKey)
+    Loading(Vec<eventual::Complete<AudioKey, AudioKeyError>>),
+    Loaded(AudioKey),
+    Failed(AudioKeyError)
 }
 }
 
 
 pub struct AudioKeyManager {
 pub struct AudioKeyManager {
@@ -34,12 +37,15 @@ impl AudioKeyManager {
     }
     }
 
 
     pub fn request(&mut self, session: &Session, track: SpotifyId, file: FileId)
     pub fn request(&mut self, session: &Session, track: SpotifyId, file: FileId)
-        -> eventual::Future<AudioKey, ()> {
+        -> eventual::Future<AudioKey, AudioKeyError> {
 
 
         let id = AudioKeyId(track, file);
         let id = AudioKeyId(track, file);
         self.cache.get_mut(&id).map(|status| match *status {
         self.cache.get_mut(&id).map(|status| match *status {
+            AudioKeyStatus::Failed(error) => {
+                eventual::Future::error(error)
+            }
             AudioKeyStatus::Loaded(key) => {
             AudioKeyStatus::Loaded(key) => {
-                eventual::Future::of(key.clone())
+                eventual::Future::of(key)
             }
             }
             AudioKeyStatus::Loading(ref mut req) => {
             AudioKeyStatus::Loading(ref mut req) => {
                 let (tx, rx) = eventual::Future::pair();
                 let (tx, rx) = eventual::Future::pair();
@@ -69,19 +75,29 @@ impl AudioKeyManager {
 
 
 impl PacketHandler for AudioKeyManager {
 impl PacketHandler for AudioKeyManager {
     fn handle(&mut self, cmd: u8, data: Vec<u8>) {
     fn handle(&mut self, cmd: u8, data: Vec<u8>) {
-        assert_eq!(cmd, 0xd);
-
         let mut data = Cursor::new(data);
         let mut data = Cursor::new(data);
         let seq = data.read_u32::<BigEndian>().unwrap();
         let seq = data.read_u32::<BigEndian>().unwrap();
-        let mut key = [0u8; 16];
-        data.read_exact(&mut key).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) }) {
-            let status = mem::replace(status, AudioKeyStatus::Loaded(key));
+            if cmd == 0xd {
+                let mut key = [0u8; 16];
+                data.read_exact(&mut key).unwrap();
 
 
-            if let AudioKeyStatus::Loading(cbs) = status {
-                for cb in cbs {
-                    cb.complete(key);
+                let status = mem::replace(status, AudioKeyStatus::Loaded(key));
+
+                if let AudioKeyStatus::Loading(cbs) = status {
+                    for cb in cbs {
+                        cb.complete(key);
+                    }
+                }
+            } else if cmd == 0xe {
+                let error = AudioKeyError;
+                let status = mem::replace(status, AudioKeyStatus::Failed(error));
+
+                if let AudioKeyStatus::Loading(cbs) = status {
+                    for cb in cbs {
+                        cb.fail(error);
+                    }
                 }
                 }
             }
             }
         }
         }

+ 2 - 2
src/metadata.rs

@@ -92,7 +92,7 @@ impl MetadataTrait for Album {
         "hm://metadata/3/album"
         "hm://metadata/3/album"
     }
     }
 
 
-    fn parse(msg: &Self::Message, session: &Session) -> Self {
+    fn parse(msg: &Self::Message, _: &Session) -> Self {
         Album {
         Album {
             id: SpotifyId::from_raw(msg.get_gid()),
             id: SpotifyId::from_raw(msg.get_gid()),
             name: msg.get_name().to_owned(),
             name: msg.get_name().to_owned(),
@@ -118,7 +118,7 @@ impl MetadataTrait for Artist {
         "hm://metadata/3/artist"
         "hm://metadata/3/artist"
     }
     }
 
 
-    fn parse(msg: &Self::Message, session: &Session) -> Self {
+    fn parse(msg: &Self::Message, _: &Session) -> Self {
         Artist {
         Artist {
             id: SpotifyId::from_raw(msg.get_gid()),
             id: SpotifyId::from_raw(msg.get_gid()),
             name: msg.get_name().to_owned(),
             name: msg.get_name().to_owned(),

+ 2 - 2
src/session.rs

@@ -14,7 +14,7 @@ use util::{SpotifyId, FileId, mkdir_existing};
 use mercury::{MercuryManager, MercuryRequest, MercuryResponse};
 use mercury::{MercuryManager, MercuryRequest, MercuryResponse};
 use metadata::{MetadataManager, MetadataRef, MetadataTrait};
 use metadata::{MetadataManager, MetadataRef, MetadataTrait};
 use stream::{StreamManager, StreamEvent};
 use stream::{StreamManager, StreamEvent};
-use audio_key::{AudioKeyManager, AudioKey};
+use audio_key::{AudioKeyManager, AudioKey, AudioKeyError};
 use audio_file::{AudioFileManager, AudioFile};
 use audio_file::{AudioFileManager, AudioFile};
 use connection::PacketHandler;
 use connection::PacketHandler;
 
 
@@ -189,7 +189,7 @@ impl Session {
         self.0.tx_connection.lock().unwrap().send_packet(cmd, data)
         self.0.tx_connection.lock().unwrap().send_packet(cmd, data)
     }
     }
 
 
-    pub fn audio_key(&self, track: SpotifyId, file: FileId) -> Future<AudioKey, ()> {
+    pub fn audio_key(&self, track: SpotifyId, file: FileId) -> Future<AudioKey, AudioKeyError> {
         self.0.audio_key.lock().unwrap().request(self, track, file)
         self.0.audio_key.lock().unwrap().request(self, track, file)
     }
     }