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

This commit is contained in:
Paul Lietar 2015-12-29 23:12:02 +01:00
parent 8c2aa28d43
commit 654a403459
3 changed files with 32 additions and 16 deletions

View file

@ -9,13 +9,16 @@ use session::Session;
use connection::PacketHandler;
pub type AudioKey = [u8; 16];
#[derive(Debug,Hash,PartialEq,Eq,Copy,Clone)]
pub struct AudioKeyError;
#[derive(Debug,Hash,PartialEq,Eq,Clone)]
struct AudioKeyId(SpotifyId, FileId);
enum AudioKeyStatus {
Loading(Vec<eventual::Complete<AudioKey, ()>>),
Loaded(AudioKey)
Loading(Vec<eventual::Complete<AudioKey, AudioKeyError>>),
Loaded(AudioKey),
Failed(AudioKeyError)
}
pub struct AudioKeyManager {
@ -34,12 +37,15 @@ impl AudioKeyManager {
}
pub fn request(&mut self, session: &Session, track: SpotifyId, file: FileId)
-> eventual::Future<AudioKey, ()> {
-> 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.clone())
eventual::Future::of(key)
}
AudioKeyStatus::Loading(ref mut req) => {
let (tx, rx) = eventual::Future::pair();
@ -69,19 +75,29 @@ impl AudioKeyManager {
impl PacketHandler for AudioKeyManager {
fn handle(&mut self, cmd: u8, data: Vec<u8>) {
assert_eq!(cmd, 0xd);
let mut data = Cursor::new(data);
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) }) {
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);
}
}
}
}

View file

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

View file

@ -14,7 +14,7 @@ use util::{SpotifyId, FileId, mkdir_existing};
use mercury::{MercuryManager, MercuryRequest, MercuryResponse};
use metadata::{MetadataManager, MetadataRef, MetadataTrait};
use stream::{StreamManager, StreamEvent};
use audio_key::{AudioKeyManager, AudioKey};
use audio_key::{AudioKeyManager, AudioKey, AudioKeyError};
use audio_file::{AudioFileManager, AudioFile};
use connection::PacketHandler;
@ -189,7 +189,7 @@ impl Session {
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)
}