diff --git a/src/codec.rs b/src/codec.rs new file mode 100644 index 000000000..339543a41 --- /dev/null +++ b/src/codec.rs @@ -0,0 +1,182 @@ +use bytes::{BigEndian, BufMut, BytesMut}; + +use proto::{Header, LongType, Packet, ShortType}; + +use std::io; + +use tokio_io::codec::{Decoder, Encoder}; + +pub struct QuicCodec {} + +impl Decoder for QuicCodec { + type Item = Packet; + type Error = io::Error; + fn decode(&mut self, buf: &mut BytesMut) -> Result, io::Error> { + let first = buf[0]; + let (header, number, offset) = if first & 128 == 128 { + + let h = Header::Long { + ptype: LongType::from_byte(first ^ 128), + conn_id: bytes_to_u64(&buf[1..9]), + version: bytes_to_u32(&buf[9..13]), + }; + let number = bytes_to_u32(&buf[13..17]); + (h, number, 17) + + } else { + + let ptype = ShortType::from_byte(first & 7); + let conn_id = if first & 0x40 == 0x40 { + Some(bytes_to_u64(&buf[1..9])) + } else { + None + }; + let h = Header::Short { + ptype, + conn_id, + key_phase: first & 0x20 == 0x20, + }; + + let offset = if conn_id.is_some() { 9 } else { 1 }; + let size = match h { + Header::Short { ref ptype, .. } => ptype.buf_len(), + _ => panic!("must be a short header"), + }; + let number = if size == 1 { + buf[offset] as u32 + } else if size == 2 { + (buf[offset] as u32) << 8 | (buf[offset + 1] as u32) + } else { + bytes_to_u32(&buf[offset..offset + 4]) + }; + (h, number, offset + size) + + }; + Ok(Some(Packet { + header, + number, + payload: Vec::new(), + })) + } +} + +impl Encoder for QuicCodec { + type Item = Packet; + type Error = io::Error; + fn encode(&mut self, msg: Self::Item, dst: &mut BytesMut) -> Result<(), io::Error> { + let required = msg.buf_len(); + let cur_size = dst.remaining_mut(); + if cur_size < required { + dst.reserve(required - cur_size); + } + Ok(()) + } +} + +pub struct VarLen { + val: u64, +} + +impl VarLen { + pub fn new(val: u64) -> VarLen { + VarLen { val } + } +} + +impl BufLen for VarLen { + fn buf_len(&self) -> usize { + match self.val { + v if v <= 63 => 1, + v if v <= 16_383 => 2, + v if v <= 1_073_741_823 => 4, + v if v <= 4_611_686_018_427_387_903 => 8, + v => panic!("too large for variable-length encoding: {}", v), + } + } +} + +impl Codec for VarLen { + fn encode(&self, buf: &mut T) { + match self.buf_len() { + 1 => buf.put_u8(self.val as u8), + 2 => buf.put_u16::(self.val as u16 | 16384), + 4 => buf.put_u32::(self.val as u32 | 2_147_483_648), + 8 => buf.put_u64::(self.val | 13_835_058_055_282_163_712), + _ => panic!("impossible variable-length encoding"), + } + } +} + +fn bytes_to_u64(bytes: &[u8]) -> u64 { + debug_assert_eq!(bytes.len(), 8); + ((bytes[0] as u64) << 56 | + (bytes[1] as u64) << 48 | + (bytes[2] as u64) << 40 | + (bytes[3] as u64) << 32 | + (bytes[4] as u64) << 24 | + (bytes[5] as u64) << 16 | + (bytes[6] as u64) << 8 | + (bytes[7] as u64)) +} + +fn bytes_to_u32(bytes: &[u8]) -> u32 { + debug_assert_eq!(bytes.len(), 4); + ((bytes[0] as u32) << 24 | + (bytes[1] as u32) << 16 | + (bytes[2] as u32) << 8 | + (bytes[3] as u32)) +} + +pub trait BufLen { + fn buf_len(&self) -> usize; +} + +impl BufLen for Option where T: BufLen { + fn buf_len(&self) -> usize { + match *self { + Some(ref v) => v.buf_len(), + None => 0, + } + } +} + +pub trait Codec { + fn encode(&self, buf: &mut T); +} + +#[cfg(test)] +mod tests { + use super::{Codec, VarLen}; + #[test] + fn test_var_len_encoding_8() { + let num = 151_288_809_941_952_652; + let bytes = b"\xc2\x19\x7c\x5e\xff\x14\xe8\x8c"; + let mut buf = Vec::new(); + VarLen::new(num).encode(&mut buf); + assert_eq!(bytes[..], *buf); + } + #[test] + fn test_var_len_encoding_4() { + let num = 494_878_333; + let bytes = b"\x9d\x7f\x3e\x7d"; + let mut buf = Vec::new(); + VarLen::new(num).encode(&mut buf); + assert_eq!(bytes[..], *buf); + } + #[test] + fn test_var_len_encoding_2() { + let num = 15_293; + let bytes = b"\x7b\xbd"; + let mut buf = Vec::new(); + VarLen::new(num).encode(&mut buf); + assert_eq!(bytes[..], *buf); + } + #[test] + fn test_var_len_encoding_1_short() { + let num = 37; + let bytes = b"\x25"; + let mut buf = Vec::new(); + VarLen::new(num).encode(&mut buf); + assert_eq!(bytes[..], *buf); + } +} diff --git a/src/frame.rs b/src/frame.rs index 8b660e829..774da39e8 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -1,6 +1,6 @@ use bytes::BufMut; -use proto::{BufLen, Codec, VarLen}; +use codec::{BufLen, Codec, VarLen}; pub enum Frame { Padding(PaddingFrame), diff --git a/src/lib.rs b/src/lib.rs index f47d039b2..1058ff15b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,13 +11,15 @@ use futures::Future; use rand::{Rng, thread_rng}; +use self::codec::{BufLen, Codec}; use self::frame::{Frame, PaddingFrame, StreamFrame}; -use self::proto::{BufLen, Codec, DRAFT_10, Header, LongType, Packet}; +use self::proto::{DRAFT_10, Header, LongType, Packet}; use std::net::{SocketAddr, ToSocketAddrs}; use tokio::net::UdpSocket; +mod codec; mod frame; mod proto; mod tls; diff --git a/src/proto.rs b/src/proto.rs index 129ffc85a..fdb32ebd8 100644 --- a/src/proto.rs +++ b/src/proto.rs @@ -1,78 +1,8 @@ -use bytes::{BigEndian, BufMut, BytesMut}; +use bytes::{BigEndian, BufMut}; +use codec::{BufLen, Codec, VarLen}; use frame::Frame; -use std::io; - -use tokio_io::codec::{Decoder, Encoder}; - -pub struct QuicCodec {} - -impl Decoder for QuicCodec { - type Item = Packet; - type Error = io::Error; - fn decode(&mut self, buf: &mut BytesMut) -> Result, io::Error> { - let first = buf[0]; - let (header, number, offset) = if first & 128 == 128 { - - let h = Header::Long { - ptype: LongType::from_byte(first ^ 128), - conn_id: bytes_to_u64(&buf[1..9]), - version: bytes_to_u32(&buf[9..13]), - }; - let number = bytes_to_u32(&buf[13..17]); - (h, number, 17) - - } else { - - let ptype = ShortType::from_byte(first & 7); - let conn_id = if first & 0x40 == 0x40 { - Some(bytes_to_u64(&buf[1..9])) - } else { - None - }; - let h = Header::Short { - ptype, - conn_id, - key_phase: first & 0x20 == 0x20, - }; - - let offset = if conn_id.is_some() { 9 } else { 1 }; - let size = match h { - Header::Short { ref ptype, .. } => ptype.buf_len(), - _ => panic!("must be a short header"), - }; - let number = if size == 1 { - buf[offset] as u32 - } else if size == 2 { - (buf[offset] as u32) << 8 | (buf[offset + 1] as u32) - } else { - bytes_to_u32(&buf[offset..offset + 4]) - }; - (h, number, offset + size) - - }; - Ok(Some(Packet { - header, - number, - payload: Vec::new(), - })) - } -} - -impl Encoder for QuicCodec { - type Item = Packet; - type Error = io::Error; - fn encode(&mut self, msg: Self::Item, dst: &mut BytesMut) -> Result<(), io::Error> { - let required = msg.buf_len(); - let cur_size = dst.remaining_mut(); - if cur_size < required { - dst.reserve(required - cur_size); - } - Ok(()) - } -} - pub struct Packet { pub header: Header, pub number: u32, @@ -166,7 +96,7 @@ pub enum LongType { impl Copy for LongType {} impl LongType { - fn to_byte(&self) -> u8 { + pub fn to_byte(&self) -> u8 { use self::LongType::*; match *self { Initial => 0x7f, @@ -175,7 +105,7 @@ impl LongType { Protected => 0x7c, } } - fn from_byte(v: u8) -> Self { + pub fn from_byte(v: u8) -> Self { use self::LongType::*; match v { 0x7f => Initial, @@ -208,7 +138,7 @@ impl BufLen for ShortType { } impl ShortType { - fn to_byte(&self) -> u8 { + pub fn to_byte(&self) -> u8 { use self::ShortType::*; match *self { One => 1, @@ -216,7 +146,7 @@ impl ShortType { Four => 4, } } - fn from_byte(v: u8) -> Self { + pub fn from_byte(v: u8) -> Self { use self::ShortType::*; match v { 0 => One, @@ -227,112 +157,4 @@ impl ShortType { } } -pub struct VarLen { - val: u64, -} - -impl VarLen { - pub fn new(val: u64) -> VarLen { - VarLen { val } - } -} - -impl BufLen for VarLen { - fn buf_len(&self) -> usize { - match self.val { - v if v <= 63 => 1, - v if v <= 16_383 => 2, - v if v <= 1_073_741_823 => 4, - v if v <= 4_611_686_018_427_387_903 => 8, - v => panic!("too large for variable-length encoding: {}", v), - } - } -} - -impl Codec for VarLen { - fn encode(&self, buf: &mut T) { - match self.buf_len() { - 1 => buf.put_u8(self.val as u8), - 2 => buf.put_u16::(self.val as u16 | 16384), - 4 => buf.put_u32::(self.val as u32 | 2_147_483_648), - 8 => buf.put_u64::(self.val | 13_835_058_055_282_163_712), - _ => panic!("impossible variable-length encoding"), - } - } -} - -fn bytes_to_u64(bytes: &[u8]) -> u64 { - debug_assert_eq!(bytes.len(), 8); - ((bytes[0] as u64) << 56 | - (bytes[1] as u64) << 48 | - (bytes[2] as u64) << 40 | - (bytes[3] as u64) << 32 | - (bytes[4] as u64) << 24 | - (bytes[5] as u64) << 16 | - (bytes[6] as u64) << 8 | - (bytes[7] as u64)) -} - -fn bytes_to_u32(bytes: &[u8]) -> u32 { - debug_assert_eq!(bytes.len(), 4); - ((bytes[0] as u32) << 24 | - (bytes[1] as u32) << 16 | - (bytes[2] as u32) << 8 | - (bytes[3] as u32)) -} - -pub trait BufLen { - fn buf_len(&self) -> usize; -} - -impl BufLen for Option where T: BufLen { - fn buf_len(&self) -> usize { - match *self { - Some(ref v) => v.buf_len(), - None => 0, - } - } -} - -pub trait Codec { - fn encode(&self, buf: &mut T); -} - pub const DRAFT_10: u32 = 0xff00000a; - -#[cfg(test)] -mod tests { - use super::{Codec, VarLen}; - #[test] - fn test_var_len_encoding_8() { - let num = 151_288_809_941_952_652; - let bytes = b"\xc2\x19\x7c\x5e\xff\x14\xe8\x8c"; - let mut buf = Vec::new(); - VarLen::new(num).encode(&mut buf); - assert_eq!(bytes[..], *buf); - } - #[test] - fn test_var_len_encoding_4() { - let num = 494_878_333; - let bytes = b"\x9d\x7f\x3e\x7d"; - let mut buf = Vec::new(); - VarLen::new(num).encode(&mut buf); - assert_eq!(bytes[..], *buf); - } - #[test] - fn test_var_len_encoding_2() { - let num = 15_293; - let bytes = b"\x7b\xbd"; - let mut buf = Vec::new(); - VarLen::new(num).encode(&mut buf); - assert_eq!(bytes[..], *buf); - } - #[test] - fn test_var_len_encoding_1_short() { - let num = 37; - let bytes = b"\x25"; - let mut buf = Vec::new(); - VarLen::new(num).encode(&mut buf); - assert_eq!(bytes[..], *buf); - } -}