librespot/src/stream.rs

140 lines
4.1 KiB
Rust
Raw Normal View History

2015-06-23 14:38:29 +00:00
use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt};
use std::collections::HashMap;
use std::io::{Cursor, Seek, SeekFrom, Write};
use std::sync::mpsc;
use util::{ArcVec, FileId};
use connection::PacketHandler;
use session::Session;
2015-06-23 14:38:29 +00:00
#[derive(Debug)]
pub enum StreamEvent {
Header(u8, ArcVec<u8>),
Data(ArcVec<u8>),
}
type ChannelId = u16;
enum ChannelMode {
Header,
2016-01-02 15:19:39 +00:00
Data,
2015-06-23 14:38:29 +00:00
}
struct Channel {
mode: ChannelMode,
2016-01-02 15:19:39 +00:00
callback: mpsc::Sender<StreamEvent>,
2015-06-23 14:38:29 +00:00
}
pub struct StreamManager {
next_id: ChannelId,
channels: HashMap<ChannelId, Channel>,
}
impl StreamManager {
pub fn new() -> StreamManager {
StreamManager {
2015-06-23 14:38:29 +00:00
next_id: 0,
channels: HashMap::new(),
}
2015-06-23 14:38:29 +00:00
}
2016-01-02 15:19:39 +00:00
pub fn request(&mut self,
session: &Session,
file: FileId,
offset: u32,
size: u32)
-> mpsc::Receiver<StreamEvent> {
let (tx, rx) = mpsc::channel();
2015-06-23 14:38:29 +00:00
let channel_id = self.next_id;
self.next_id += 1;
2016-01-02 15:19:39 +00:00
let mut data: Vec<u8> = Vec::new();
2015-06-23 14:38:29 +00:00
data.write_u16::<BigEndian>(channel_id).unwrap();
data.write_u8(0).unwrap();
data.write_u8(1).unwrap();
data.write_u16::<BigEndian>(0x0000).unwrap();
data.write_u32::<BigEndian>(0x00000000).unwrap();
data.write_u32::<BigEndian>(0x00009C40).unwrap();
data.write_u32::<BigEndian>(0x00020000).unwrap();
2015-07-07 21:40:31 +00:00
data.write(&file.0).unwrap();
data.write_u32::<BigEndian>(offset).unwrap();
data.write_u32::<BigEndian>(offset + size).unwrap();
2015-06-23 14:38:29 +00:00
session.send_packet(0x8, &data).unwrap();
2015-06-23 14:38:29 +00:00
2016-01-02 15:19:39 +00:00
self.channels.insert(channel_id,
Channel {
mode: ChannelMode::Header,
callback: tx,
});
rx
2015-06-23 14:38:29 +00:00
}
}
2015-06-23 14:38:29 +00:00
impl PacketHandler for StreamManager {
fn handle(&mut self, _cmd: u8, data: Vec<u8>) {
2015-06-23 14:38:29 +00:00
let data = ArcVec::new(data);
let mut packet = Cursor::new(&data as &[u8]);
2016-01-02 15:19:39 +00:00
let id: ChannelId = packet.read_u16::<BigEndian>().unwrap();
2015-06-23 17:34:48 +00:00
let mut close = false;
{
let channel = match self.channels.get_mut(&id) {
Some(ch) => ch,
2016-01-02 15:19:39 +00:00
None => {
return;
}
2015-06-23 17:34:48 +00:00
};
match channel.mode {
ChannelMode::Header => {
let mut length = 0;
2015-07-03 00:23:49 +00:00
while packet.position() < data.len() as u64 && !close {
2015-06-23 17:34:48 +00:00
length = packet.read_u16::<BigEndian>().unwrap();
if length > 0 {
let header_id = packet.read_u8().unwrap();
2015-07-03 00:23:49 +00:00
channel.callback
.send(StreamEvent::Header(
header_id,
data.clone()
.offset(packet.position() as usize)
.limit(length as usize - 1)
))
.unwrap_or_else(|_| {
close = true;
});
2015-06-23 17:34:48 +00:00
packet.seek(SeekFrom::Current(length as i64 - 1)).unwrap();
}
}
2016-01-02 15:19:39 +00:00
2015-06-23 17:34:48 +00:00
if length == 0 {
channel.mode = ChannelMode::Data;
2015-06-23 14:38:29 +00:00
}
}
2015-06-23 17:34:48 +00:00
ChannelMode::Data => {
if packet.position() < data.len() as u64 {
2015-07-03 00:23:49 +00:00
channel.callback
2016-01-02 15:19:39 +00:00
.send(StreamEvent::Data(data.clone()
.offset(packet.position() as usize)))
.unwrap_or_else(|_| {
close = true;
});
2015-06-23 17:34:48 +00:00
} else {
close = true;
}
2015-06-23 14:38:29 +00:00
}
}
}
2015-06-23 17:34:48 +00:00
if close {
self.channels.remove(&id);
}
2015-06-23 14:38:29 +00:00
}
}