use std::mem;
use http::StreamId;
#[macro_escape]
macro_rules! unpack_octets_4 {
($buf:ident, $offset:expr, $tip:ty) => (
(($buf[$offset + 0] as $tip) << 24) |
(($buf[$offset + 1] as $tip) << 16) |
(($buf[$offset + 2] as $tip) << 8) |
(($buf[$offset + 3] as $tip) << 0)
);
}
pub mod data;
pub mod headers;
pub mod settings;
pub use self::data::{DataFlag, DataFrame};
pub use self::headers::{HeadersFlag, HeadersFrame};
pub use self::settings::{SettingsFlag, SettingsFrame, HttpSetting};
pub type FrameHeaderBuffer = [u8; 9];
pub type FrameHeader = (u32, u8, u8, u32);
pub fn unpack_header(header: &FrameHeaderBuffer) -> FrameHeader {
let length: u32 =
((header[0] as u32) << 16) |
((header[1] as u32) << 8) |
((header[2] as u32) << 0);
let frame_type = header[3];
let flags = header[4];
let stream_id: u32 = unpack_octets_4!(header, 5, u32);
(length, frame_type, flags, stream_id)
}
pub fn pack_header(header: &FrameHeader) -> FrameHeaderBuffer {
let &(length, frame_type, flags, stream_id) = header;
[
(((length >> 16) & 0x000000FF) as u8),
(((length >> 8) & 0x000000FF) as u8),
(((length >> 0) & 0x000000FF) as u8),
frame_type,
flags,
(((stream_id >> 24) & 0x000000FF) as u8),
(((stream_id >> 16) & 0x000000FF) as u8),
(((stream_id >> 8) & 0x000000FF) as u8),
(((stream_id >> 0) & 0x000000FF) as u8),
]
}
fn parse_padded_payload<'a>(payload: &'a [u8]) -> Option<(&'a [u8], u8)> {
if payload.len() == 0 {
return None;
}
let pad_len = payload[0] as usize;
if pad_len >= payload.len() {
return None;
}
Some((&payload[1..payload.len() - pad_len], pad_len as u8))
}
pub trait Flag {
fn bitmask(&self) -> u8;
}
pub trait Frame: Sized {
type FlagType: Flag;
fn from_raw(raw_frame: RawFrame) -> Option<Self>;
fn is_set(&self, flag: Self::FlagType) -> bool;
fn get_stream_id(&self) -> StreamId;
fn get_header(&self) -> FrameHeader;
fn set_flag(&mut self, flag: Self::FlagType);
fn serialize(&self) -> Vec<u8>;
}
#[derive(PartialEq)]
#[derive(Debug)]
#[derive(Clone)]
pub struct RawFrame {
raw_content: Vec<u8>,
}
impl RawFrame {
pub fn new(header: FrameHeader) -> RawFrame {
RawFrame::with_payload(header, Vec::new())
}
pub fn with_payload(header: FrameHeader, payload: Vec<u8>) -> RawFrame {
let mut raw = Vec::new();
raw.extend(pack_header(&header).into_iter().map(|x| *x));
raw.extend(payload);
RawFrame {
raw_content: raw,
}
}
pub fn from_buf(buf: &[u8]) -> Option<RawFrame> {
if buf.len() < 9 {
return None;
}
let header = unpack_header(unsafe {
assert!(buf.len() >= 9);
mem::transmute(buf.as_ptr())
});
let payload_len = header.0 as usize;
if buf[9..].len() != payload_len {
return None;
}
Some(RawFrame {
raw_content: buf.to_vec(),
})
}
pub fn serialize(&self) -> Vec<u8> {
self.raw_content.clone()
}
pub fn header(&self) -> FrameHeader {
unpack_header(unsafe {
assert!(self.raw_content.len() >= 9);
mem::transmute(self.raw_content.as_ptr())
})
}
pub fn payload(&self) -> &[u8] {
&self.raw_content[9..]
}
}
impl Into<Vec<u8>> for RawFrame {
fn into(self) -> Vec<u8> { self.raw_content }
}
impl From<Vec<u8>> for RawFrame {
fn from(raw: Vec<u8>) -> RawFrame { RawFrame { raw_content: raw } }
}
#[cfg(test)]
mod tests {
use super::{
unpack_header,
pack_header,
RawFrame,
FrameHeader,
Frame,
};
#[test]
fn test_unpack_header() {
{
let header = [0; 9];
assert_eq!((0, 0, 0, 0), unpack_header(&header));
}
{
let header = [0, 0, 1, 2, 3, 0, 0, 0, 4];
assert_eq!((1, 2, 3, 4), unpack_header(&header));
}
{
let header = [0, 0, 1, 200, 100, 0, 0, 0, 4];
assert_eq!((1, 200, 100, 4), unpack_header(&header));
}
{
let header = [0, 0, 1, 0, 0, 0, 0, 0, 0];
assert_eq!((1, 0, 0, 0), unpack_header(&header));
}
{
let header = [0, 1, 0, 0, 0, 0, 0, 0, 0];
assert_eq!((256, 0, 0, 0), unpack_header(&header));
}
{
let header = [1, 0, 0, 0, 0, 0, 0, 0, 0];
assert_eq!((256 * 256, 0, 0, 0), unpack_header(&header));
}
{
let header = [0, 0, 0, 0, 0, 0, 0, 0, 1];
assert_eq!((0, 0, 0, 1), unpack_header(&header));
}
{
let header = [0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 1];
assert_eq!(((1 << 24) - 1, 0, 0, 1), unpack_header(&header));
}
{
let header = [0xFF, 0xFF, 0xFF, 0, 0, 1, 1, 1, 1];
assert_eq!(
((1 << 24) - 1, 0, 0, 1 + (1 << 8) + (1 << 16) + (1 << 24)),
unpack_header(&header));
}
}
#[test]
fn test_pack_header() {
{
let header = [0; 9];
assert_eq!(pack_header(&(0, 0, 0, 0)), header);
}
{
let header = [0, 0, 1, 2, 3, 0, 0, 0, 4];
assert_eq!(pack_header(&(1, 2, 3, 4)), header);
}
{
let header = [0, 0, 1, 200, 100, 0, 0, 0, 4];
assert_eq!(pack_header(&(1, 200, 100, 4)), header);
}
{
let header = [0, 0, 1, 0, 0, 0, 0, 0, 0];
assert_eq!(pack_header(&(1, 0, 0, 0)), header);
}
{
let header = [0, 1, 0, 0, 0, 0, 0, 0, 0];
assert_eq!(pack_header(&(256, 0, 0, 0)), header);
}
{
let header = [1, 0, 0, 0, 0, 0, 0, 0, 0];
assert_eq!(pack_header(&(256 * 256, 0, 0, 0)), header);
}
{
let header = [0, 0, 0, 0, 0, 0, 0, 0, 1];
assert_eq!(pack_header(&(0, 0, 0, 1)), header);
}
{
let header = [0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 1];
assert_eq!(pack_header(&((1 << 24) - 1, 0, 0, 1)), header);
}
{
let header = [0xFF, 0xFF, 0xFF, 0, 0, 1, 1, 1, 1];
let header_components = (
(1 << 24) - 1, 0, 0, 1 + (1 << 8) + (1 << 16) + (1 << 24)
);
assert_eq!(pack_header(&header_components), header);
}
}
pub fn build_test_frame<F: Frame>(header: &FrameHeader, payload: &[u8]) -> F {
let raw = RawFrame::with_payload(header.clone(), payload.to_vec());
Frame::from_raw(raw).unwrap()
}
pub fn build_padded_frame_payload(data: &[u8], pad_len: u8) -> Vec<u8> {
let sz = 1 + data.len() + pad_len as usize;
let mut payload: Vec<u8> = Vec::with_capacity(sz);
payload.push(pad_len);
payload.extend(data.to_vec().into_iter());
for _ in 0..pad_len { payload.push(0); }
payload
}
#[test]
fn test_raw_frame_with_payload() {
{
let data = b"123";
let header = (data.len() as u32, 0x1, 0, 1);
let raw = RawFrame::with_payload(header, data.to_vec());
assert_eq!(raw.header(), header);
assert_eq!(raw.payload(), data)
}
{
let data = b"123456";
let header = (3, 0x1, 0, 1);
let raw = RawFrame::with_payload(header, data.to_vec());
assert_eq!(raw.header(), header);
assert_eq!(raw.payload(), data)
}
{
let data = b"123";
let header = (6, 0x1, 0, 1);
let raw = RawFrame::with_payload(header, data.to_vec());
assert_eq!(raw.header(), header);
assert_eq!(raw.payload(), data)
}
}
#[test]
fn test_raw_frame_from_buffer() {
{
let data = b"123";
let header = (data.len() as u32, 0x1, 0, 1);
let buf = {
let mut buf = Vec::new();
buf.extend(pack_header(&header).to_vec().into_iter());
buf.extend(data.to_vec().into_iter());
buf
};
let raw = RawFrame::from_buf(&buf).unwrap();
assert_eq!(raw.header(), header);
assert_eq!(raw.payload(), data)
}
{
let data = b"123";
let header = (data.len() as u32, 0x1, 0, 1);
let buf = {
let mut buf = Vec::new();
buf.extend(pack_header(&header).to_vec().into_iter());
buf.extend(data.to_vec().into_iter());
buf.extend(vec![1, 2, 3, 4, 5].into_iter());
buf
};
assert!(RawFrame::from_buf(&buf).is_none());
}
{
let data = b"123";
let header = (data.len() as u32, 0x1, 0, 1);
let buf = {
let mut buf = Vec::new();
buf.extend(pack_header(&header).to_vec().into_iter());
buf.extend(data[..2].to_vec().into_iter());
buf
};
assert!(RawFrame::from_buf(&buf).is_none());
}
{
let header = (0, 0x1, 0, 1);
let buf = {
let mut buf = Vec::new();
buf.extend(pack_header(&header)[..5].to_vec().into_iter());
buf
};
assert!(RawFrame::from_buf(&buf).is_none());
}
{
assert!(RawFrame::from_buf(&[]).is_none());
}
}
#[test]
fn test_raw_frame_from_vec_buffer_unchecked() {
{
let data = b"123";
let header = (data.len() as u32, 0x1, 0, 1);
let buf = {
let mut buf = Vec::new();
buf.extend(pack_header(&header).to_vec().into_iter());
buf.extend(data.to_vec().into_iter());
buf
};
let buf_clone = buf.clone();
let raw = RawFrame::from(buf);
assert_eq!(raw.header(), header);
assert_eq!(raw.payload(), data);
assert_eq!(raw.serialize(), buf_clone);
}
{
let data = b"123";
let header = (data.len() as u32, 0x1, 0, 1);
let buf = {
let mut buf = Vec::new();
buf.extend(pack_header(&header).to_vec().into_iter());
buf.extend(data.to_vec().into_iter());
buf.extend(b"12345".to_vec().into_iter());
buf
};
let buf_clone = buf.clone();
let raw = RawFrame::from(buf);
assert_eq!(raw.header(), header);
assert_eq!(raw.payload(), b"12312345");
assert_eq!(raw.serialize(), buf_clone);
}
{
let data = b"123";
let header = (data.len() as u32, 0x1, 0, 1);
let buf = {
let mut buf = Vec::new();
buf.extend(pack_header(&header).to_vec().into_iter());
buf.extend(data[..2].to_vec().into_iter());
buf
};
let buf_clone = buf.clone();
let raw = RawFrame::from(buf);
assert_eq!(raw.header(), header);
assert_eq!(raw.payload(), b"12");
assert_eq!(raw.serialize(), buf_clone);
}
{
let header = (0, 0x1, 0, 1);
let buf = {
let mut buf = Vec::new();
buf.extend(pack_header(&header)[..5].to_vec().into_iter());
buf
};
let buf_clone = buf.clone();
let raw = RawFrame::from(buf);
assert_eq!(raw.serialize(), buf_clone);
}
{
assert_eq!(RawFrame::from(vec![]).serialize(), &[]);
}
}
#[test]
fn test_raw_frame_serialize() {
let data = b"123";
let header = (data.len() as u32, 0x1, 0, 1);
let buf = {
let mut buf = Vec::new();
buf.extend(pack_header(&header).to_vec().into_iter());
buf.extend(data.to_vec().into_iter());
buf
};
let raw = RawFrame::from_buf(&buf).unwrap();
assert_eq!(raw.serialize(), buf);
}
#[test]
fn test_raw_frame_into_vec() {
let data = b"123";
let header = (data.len() as u32, 0x1, 0, 1);
let buf = {
let mut buf = Vec::new();
buf.extend(pack_header(&header).to_vec().into_iter());
buf.extend(data.to_vec().into_iter());
buf
};
let raw = RawFrame::from_buf(&buf).unwrap();
let serialized = raw.serialize();
let vec: Vec<_> = raw.into();
assert_eq!(vec, buf);
assert_eq!(vec, serialized);
}
}