1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-25 00:12:59 +01:00
actix-extras/src/ws/frame.rs

423 lines
12 KiB
Rust
Raw Normal View History

2017-10-09 02:47:41 +02:00
use std::{fmt, mem};
2018-02-10 05:43:14 +01:00
use std::io::{Error, ErrorKind};
2017-10-08 06:48:00 +02:00
use std::iter::FromIterator;
2018-02-10 05:43:14 +01:00
use bytes::{BytesMut, BufMut};
use byteorder::{ByteOrder, BigEndian, NetworkEndian};
use rand;
2017-10-08 06:48:00 +02:00
use body::Binary;
2018-01-10 20:13:29 +01:00
use ws::proto::{OpCode, CloseCode};
use ws::mask::apply_mask;
2017-10-08 06:48:00 +02:00
2018-02-10 05:43:14 +01:00
#[derive(Debug, PartialEq)]
pub(crate) enum FrameData {
Complete(Binary),
Split(Binary, Binary),
}
const MAX_LEN: usize = 122;
2017-10-08 06:48:00 +02:00
/// A struct representing a `WebSocket` frame.
#[derive(Debug)]
2017-10-08 07:41:02 +02:00
pub(crate) struct Frame {
2017-10-08 06:48:00 +02:00
finished: bool,
rsv1: bool,
rsv2: bool,
rsv3: bool,
opcode: OpCode,
payload: Binary,
2017-10-08 06:48:00 +02:00
}
impl Frame {
2018-01-15 22:47:25 +01:00
/// Destruct frame
pub fn unpack(self) -> (bool, OpCode, Binary) {
2017-10-08 06:48:00 +02:00
(self.finished, self.opcode, self.payload)
}
/// Create a new data frame.
#[inline]
pub fn message<B: Into<Binary>>(data: B, code: OpCode, finished: bool) -> Frame {
2017-10-08 06:48:00 +02:00
Frame {
finished: finished,
opcode: code,
payload: data.into(),
2017-10-08 06:48:00 +02:00
.. Frame::default()
}
}
/// Create a new Close control frame.
#[inline]
pub fn close(code: CloseCode, reason: &str) -> Frame {
let raw: [u8; 2] = unsafe {
let u: u16 = code.into();
2017-10-09 02:47:41 +02:00
mem::transmute(u.to_be())
2017-10-08 06:48:00 +02:00
};
let payload = if let CloseCode::Empty = code {
Vec::new()
} else {
Vec::from_iter(
raw[..].iter()
.chain(reason.as_bytes().iter())
.cloned())
};
Frame {
payload: payload.into(),
2017-10-08 06:48:00 +02:00
.. Frame::default()
}
}
/// Parse the input stream into a frame.
2018-02-10 05:43:14 +01:00
pub fn parse(buf: &mut BytesMut, server: bool) -> Result<Option<Frame>, Error> {
2017-10-08 06:48:00 +02:00
let mut idx = 2;
let mut size = buf.len();
2017-10-08 06:48:00 +02:00
if size < 2 {
return Ok(None)
}
size -= 2;
let first = buf[0];
let second = buf[1];
let finished = first & 0x80 != 0;
2018-02-10 05:43:14 +01:00
// check masking
let masked = second & 0x80 != 0;
if !masked && server {
return Err(Error::new(
ErrorKind::Other, "Received an unmasked frame from client"))
} else if masked && !server {
return Err(Error::new(
ErrorKind::Other, "Received a masked frame from server"))
}
let rsv1 = first & 0x40 != 0;
let rsv2 = first & 0x20 != 0;
let rsv3 = first & 0x10 != 0;
let opcode = OpCode::from(first & 0x0F);
let len = second & 0x7F;
let length = if len == 126 {
2017-10-08 06:48:00 +02:00
if size < 2 {
return Ok(None)
}
2018-02-10 05:43:14 +01:00
let len = NetworkEndian::read_uint(&buf[idx..], 2) as usize;
2017-10-08 06:48:00 +02:00
size -= 2;
idx += 2;
len
} else if len == 127 {
if size < 8 {
return Ok(None)
2017-10-08 06:48:00 +02:00
}
2018-02-10 05:43:14 +01:00
let len = NetworkEndian::read_uint(&buf[idx..], 8) as usize;
size -= 8;
idx += 8;
len
} else {
2018-02-10 05:43:14 +01:00
len as usize
};
2017-10-08 06:48:00 +02:00
2018-02-10 05:43:14 +01:00
let mask = if server {
if size < 4 {
2017-10-08 06:48:00 +02:00
return Ok(None)
} else {
2018-02-10 05:43:14 +01:00
let mut mask_bytes = [0u8; 4];
size -= 4;
mask_bytes.copy_from_slice(&buf[idx..idx+4]);
idx += 4;
Some(mask_bytes)
2017-10-08 06:48:00 +02:00
}
} else {
None
};
2017-10-08 06:48:00 +02:00
if size < length {
return Ok(None)
}
// get body
buf.split_to(idx);
let mut data = if length > 0 {
buf.split_to(length)
} else {
BytesMut::new()
};
// Disallow bad opcode
if let OpCode::Bad = opcode {
return Err(
Error::new(
ErrorKind::Other,
format!("Encountered invalid opcode: {}", first & 0x0F)))
}
2017-10-08 06:48:00 +02:00
// control frames must have length <= 125
match opcode {
OpCode::Ping | OpCode::Pong if length > 125 => {
2017-10-08 06:48:00 +02:00
return Err(
Error::new(
ErrorKind::Other,
format!("Rejected WebSocket handshake.Received control frame with length: {}.", length)))
2017-10-08 06:48:00 +02:00
}
OpCode::Close if length > 125 => {
debug!("Received close frame with payload length exceeding 125. Morphing to protocol close frame.");
return Ok(Some(Frame::close(CloseCode::Protocol, "Received close frame with payload length exceeding 125.")))
2017-10-08 06:48:00 +02:00
}
_ => ()
}
2017-10-08 06:48:00 +02:00
// unmask
if let Some(ref mask) = mask {
apply_mask(&mut data, mask);
}
2017-10-08 06:48:00 +02:00
Ok(Some(Frame {
finished: finished,
rsv1: rsv1,
rsv2: rsv2,
rsv3: rsv3,
opcode: opcode,
payload: data.into(),
}))
2017-10-08 06:48:00 +02:00
}
2018-02-10 05:43:14 +01:00
/// Generate binary representation
pub fn generate(self, genmask: bool) -> FrameData {
2017-10-08 06:48:00 +02:00
let mut one = 0u8;
let code: u8 = self.opcode.into();
2017-10-09 02:47:41 +02:00
if self.finished {
2017-10-08 06:48:00 +02:00
one |= 0x80;
}
2017-10-09 02:47:41 +02:00
if self.rsv1 {
2017-10-08 06:48:00 +02:00
one |= 0x40;
}
2017-10-09 02:47:41 +02:00
if self.rsv2 {
2017-10-08 06:48:00 +02:00
one |= 0x20;
}
2017-10-09 02:47:41 +02:00
if self.rsv3 {
2017-10-08 06:48:00 +02:00
one |= 0x10;
}
one |= code;
2018-02-10 05:43:14 +01:00
let (two, mask_size) = if genmask {
(0x80, 4)
} else {
(0, 0)
};
2017-10-08 06:48:00 +02:00
2018-02-10 05:43:14 +01:00
let payload_len = self.payload.len();
let mut buf = if payload_len < MAX_LEN {
if genmask {
let len = payload_len + 6;
let mask: [u8; 4] = rand::random();
let mut buf = BytesMut::with_capacity(len);
{
let buf_mut = unsafe{buf.bytes_mut()};
buf_mut[0] = one;
buf_mut[1] = two | payload_len as u8;
buf_mut[2..6].copy_from_slice(&mask);
buf_mut[6..payload_len+6].copy_from_slice(self.payload.as_ref());
apply_mask(&mut buf_mut[6..], &mask);
}
unsafe{buf.advance_mut(len)};
return FrameData::Complete(buf.into())
} else {
let len = payload_len + 2;
let mut buf = BytesMut::with_capacity(len);
{
let buf_mut = unsafe{buf.bytes_mut()};
buf_mut[0] = one;
buf_mut[1] = two | payload_len as u8;
buf_mut[2..payload_len+2].copy_from_slice(self.payload.as_ref());
}
unsafe{buf.advance_mut(len)};
return FrameData::Complete(buf.into())
}
} else if payload_len < 126 {
let mut buf = BytesMut::with_capacity(mask_size + 2);
{
let buf_mut = unsafe{buf.bytes_mut()};
buf_mut[0] = one;
buf_mut[1] = two | payload_len as u8;
}
unsafe{buf.advance_mut(2)};
buf
} else if payload_len <= 65_535 {
let mut buf = BytesMut::with_capacity(mask_size + 4);
{
let buf_mut = unsafe{buf.bytes_mut()};
buf_mut[0] = one;
buf_mut[1] = two | 126;
BigEndian::write_u16(&mut buf_mut[2..4], payload_len as u16);
}
unsafe{buf.advance_mut(4)};
buf
2017-10-08 06:48:00 +02:00
} else {
2018-02-10 05:43:14 +01:00
let mut buf = BytesMut::with_capacity(mask_size + 10);
{
let buf_mut = unsafe{buf.bytes_mut()};
buf_mut[0] = one;
buf_mut[1] = two | 127;
BigEndian::write_u64(&mut buf_mut[2..10], payload_len as u64);
}
unsafe{buf.advance_mut(10)};
buf
};
2017-10-08 06:48:00 +02:00
2018-02-10 05:43:14 +01:00
if genmask {
let mut payload = Vec::from(self.payload.as_ref());
2018-02-10 05:43:14 +01:00
let mask: [u8; 4] = rand::random();
apply_mask(&mut payload, &mask);
2018-02-10 05:43:14 +01:00
buf.extend_from_slice(&mask);
FrameData::Split(buf.into(), payload.into())
} else {
2018-02-10 05:43:14 +01:00
FrameData::Split(buf.into(), self.payload)
2017-10-08 06:48:00 +02:00
}
}
}
impl Default for Frame {
fn default() -> Frame {
Frame {
finished: true,
rsv1: false,
rsv2: false,
rsv3: false,
opcode: OpCode::Close,
payload: Binary::from(&b""[..]),
2017-10-08 06:48:00 +02:00
}
}
}
impl fmt::Display for Frame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"
<FRAME>
final: {}
reserved: {} {} {}
opcode: {}
payload length: {}
payload: 0x{}
</FRAME>",
self.finished,
self.rsv1,
self.rsv2,
self.rsv3,
self.opcode,
self.payload.len(),
self.payload.as_ref().iter().map(
|byte| format!("{:x}", byte)).collect::<String>())
2017-10-08 06:48:00 +02:00
}
}
2017-10-23 22:31:22 +02:00
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse() {
let mut buf = BytesMut::from(&[0b00000001u8, 0b00000001u8][..]);
2018-02-10 05:43:14 +01:00
assert!(Frame::parse(&mut buf, false).unwrap().is_none());
2017-10-23 22:31:22 +02:00
buf.extend(b"1");
2018-02-10 05:43:14 +01:00
let frame = Frame::parse(&mut buf, false).unwrap().unwrap();
2017-10-23 23:08:11 +02:00
println!("FRAME: {}", frame);
2017-10-23 22:31:22 +02:00
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
assert_eq!(frame.payload.as_ref(), &b"1"[..]);
2017-10-23 22:31:22 +02:00
}
#[test]
fn test_parse_length0() {
let mut buf = BytesMut::from(&[0b00000001u8, 0b00000000u8][..]);
2018-02-10 05:43:14 +01:00
let frame = Frame::parse(&mut buf, false).unwrap().unwrap();
2017-10-23 22:31:22 +02:00
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
assert!(frame.payload.is_empty());
}
#[test]
fn test_parse_length2() {
let mut buf = BytesMut::from(&[0b00000001u8, 126u8][..]);
2018-02-10 05:43:14 +01:00
assert!(Frame::parse(&mut buf, false).unwrap().is_none());
2017-10-23 22:31:22 +02:00
buf.extend(&[0u8, 4u8][..]);
buf.extend(b"1234");
2018-02-10 05:43:14 +01:00
let frame = Frame::parse(&mut buf, false).unwrap().unwrap();
2017-10-23 22:31:22 +02:00
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
assert_eq!(frame.payload.as_ref(), &b"1234"[..]);
2017-10-23 22:31:22 +02:00
}
#[test]
fn test_parse_length4() {
let mut buf = BytesMut::from(&[0b00000001u8, 127u8][..]);
2018-02-10 05:43:14 +01:00
assert!(Frame::parse(&mut buf, false).unwrap().is_none());
2017-10-23 22:31:22 +02:00
buf.extend(&[0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8][..]);
buf.extend(b"1234");
2018-02-10 05:43:14 +01:00
let frame = Frame::parse(&mut buf, false).unwrap().unwrap();
2017-10-23 22:31:22 +02:00
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
assert_eq!(frame.payload.as_ref(), &b"1234"[..]);
2017-10-23 22:31:22 +02:00
}
#[test]
fn test_parse_frame_mask() {
let mut buf = BytesMut::from(&[0b00000001u8, 0b10000001u8][..]);
buf.extend(b"0001");
buf.extend(b"1");
2018-02-10 05:43:14 +01:00
assert!(Frame::parse(&mut buf, false).is_err());
let frame = Frame::parse(&mut buf, true).unwrap().unwrap();
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
assert_eq!(frame.payload, vec![1u8].into());
}
#[test]
fn test_parse_frame_no_mask() {
let mut buf = BytesMut::from(&[0b00000001u8, 0b00000001u8][..]);
buf.extend(&[1u8]);
assert!(Frame::parse(&mut buf, true).is_err());
let frame = Frame::parse(&mut buf, false).unwrap().unwrap();
2017-10-23 22:31:22 +02:00
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
assert_eq!(frame.payload, vec![1u8].into());
2017-10-23 22:31:22 +02:00
}
#[test]
fn test_ping_frame() {
2018-02-10 05:43:14 +01:00
let frame = Frame::message(Vec::from("data"), OpCode::Ping, true);
let res = frame.generate(false);
2017-10-23 22:31:22 +02:00
let mut v = vec![137u8, 4u8];
v.extend(b"data");
2018-02-10 05:43:14 +01:00
assert_eq!(res, FrameData::Complete(v.into()));
2017-10-23 22:31:22 +02:00
}
#[test]
fn test_pong_frame() {
2018-02-10 05:43:14 +01:00
let frame = Frame::message(Vec::from("data"), OpCode::Pong, true);
let res = frame.generate(false);
2017-10-23 22:31:22 +02:00
let mut v = vec![138u8, 4u8];
v.extend(b"data");
2018-02-10 05:43:14 +01:00
assert_eq!(res, FrameData::Complete(v.into()));
2017-10-23 22:31:22 +02:00
}
#[test]
fn test_close_frame() {
2018-02-10 05:43:14 +01:00
let frame = Frame::close(CloseCode::Normal, "data");
let res = frame.generate(false);
2017-10-23 22:31:22 +02:00
let mut v = vec![136u8, 6u8, 3u8, 232u8];
v.extend(b"data");
2018-02-10 05:43:14 +01:00
assert_eq!(res, FrameData::Complete(v.into()));
2017-10-23 22:31:22 +02:00
}
}