2018-06-23 06:29:23 +02:00
|
|
|
use byteorder::{ByteOrder, LittleEndian, NetworkEndian};
|
2018-11-18 22:48:42 +01:00
|
|
|
use bytes::{BufMut, Bytes, BytesMut};
|
2018-12-06 23:32:52 +01:00
|
|
|
use log::debug;
|
2018-02-10 05:43:14 +01:00
|
|
|
use rand;
|
2017-10-08 06:48:00 +02:00
|
|
|
|
2018-12-06 23:32:52 +01:00
|
|
|
use crate::ws::mask::apply_mask;
|
|
|
|
use crate::ws::proto::{CloseCode, CloseReason, OpCode};
|
|
|
|
use crate::ws::ProtocolError;
|
2017-10-08 06:48:00 +02:00
|
|
|
|
|
|
|
/// A struct representing a `WebSocket` frame.
|
2018-01-10 19:12:34 +01:00
|
|
|
#[derive(Debug)]
|
2018-10-10 22:20:00 +02:00
|
|
|
pub struct Parser;
|
2017-10-08 06:48:00 +02:00
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
impl Parser {
|
2018-10-05 21:47:22 +02:00
|
|
|
fn parse_metadata(
|
2018-10-30 00:39:46 +01:00
|
|
|
src: &[u8],
|
|
|
|
server: bool,
|
|
|
|
max_size: usize,
|
2018-10-05 21:47:22 +02:00
|
|
|
) -> Result<Option<(usize, bool, OpCode, usize, Option<u32>)>, ProtocolError> {
|
|
|
|
let chunk_len = src.len();
|
2018-03-09 05:39:05 +01:00
|
|
|
|
|
|
|
let mut idx = 2;
|
|
|
|
if chunk_len < 2 {
|
2018-10-05 21:47:22 +02:00
|
|
|
return Ok(None);
|
2018-03-09 05:39:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-05 21:47:22 +02:00
|
|
|
let first = src[0];
|
|
|
|
let second = src[1];
|
2018-03-09 05:39:05 +01:00
|
|
|
let finished = first & 0x80 != 0;
|
|
|
|
|
|
|
|
// check masking
|
|
|
|
let masked = second & 0x80 != 0;
|
|
|
|
if !masked && server {
|
2018-04-14 01:02:01 +02:00
|
|
|
return Err(ProtocolError::UnmaskedFrame);
|
2018-03-09 05:39:05 +01:00
|
|
|
} else if masked && !server {
|
2018-04-14 01:02:01 +02:00
|
|
|
return Err(ProtocolError::MaskedFrame);
|
2018-03-09 05:39:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Op code
|
|
|
|
let opcode = OpCode::from(first & 0x0F);
|
|
|
|
|
|
|
|
if let OpCode::Bad = opcode {
|
2018-04-14 01:02:01 +02:00
|
|
|
return Err(ProtocolError::InvalidOpcode(first & 0x0F));
|
2018-03-09 05:39:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
let len = second & 0x7F;
|
|
|
|
let length = if len == 126 {
|
|
|
|
if chunk_len < 4 {
|
2018-10-05 21:47:22 +02:00
|
|
|
return Ok(None);
|
2018-03-09 05:39:05 +01:00
|
|
|
}
|
2018-10-05 21:47:22 +02:00
|
|
|
let len = NetworkEndian::read_uint(&src[idx..], 2) as usize;
|
2018-03-09 05:39:05 +01:00
|
|
|
idx += 2;
|
|
|
|
len
|
|
|
|
} else if len == 127 {
|
|
|
|
if chunk_len < 10 {
|
2018-10-05 21:47:22 +02:00
|
|
|
return Ok(None);
|
2018-03-09 05:39:05 +01:00
|
|
|
}
|
2018-10-05 21:47:22 +02:00
|
|
|
let len = NetworkEndian::read_uint(&src[idx..], 8);
|
2018-07-06 03:46:47 +02:00
|
|
|
if len > max_size as u64 {
|
|
|
|
return Err(ProtocolError::Overflow);
|
|
|
|
}
|
2018-03-09 05:39:05 +01:00
|
|
|
idx += 8;
|
2018-07-06 03:46:47 +02:00
|
|
|
len as usize
|
2018-03-09 05:39:05 +01:00
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
// check for max allowed size
|
|
|
|
if length > max_size {
|
2018-04-14 01:02:01 +02:00
|
|
|
return Err(ProtocolError::Overflow);
|
2018-03-09 05:39:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
let mask = if server {
|
|
|
|
if chunk_len < idx + 4 {
|
2018-10-05 21:47:22 +02:00
|
|
|
return Ok(None);
|
2018-03-09 05:39:05 +01:00
|
|
|
}
|
|
|
|
|
2018-10-05 21:47:22 +02:00
|
|
|
let mask: &[u8] = &src[idx..idx + 4];
|
2018-06-23 06:29:23 +02:00
|
|
|
let mask_u32 = LittleEndian::read_u32(mask);
|
2018-03-09 05:39:05 +01:00
|
|
|
idx += 4;
|
|
|
|
Some(mask_u32)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2018-10-05 21:47:22 +02:00
|
|
|
Ok(Some((idx, finished, opcode, length, mask)))
|
2018-03-09 05:39:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse the input stream into a frame.
|
2018-10-05 21:47:22 +02:00
|
|
|
pub fn parse(
|
2018-10-30 00:39:46 +01:00
|
|
|
src: &mut BytesMut,
|
|
|
|
server: bool,
|
|
|
|
max_size: usize,
|
2018-10-10 22:20:00 +02:00
|
|
|
) -> Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError> {
|
2018-10-05 21:47:22 +02:00
|
|
|
// try to parse ws frame metadata
|
|
|
|
let (idx, finished, opcode, length, mask) =
|
2018-10-10 22:20:00 +02:00
|
|
|
match Parser::parse_metadata(src, server, max_size)? {
|
2018-10-05 21:47:22 +02:00
|
|
|
None => return Ok(None),
|
|
|
|
Some(res) => res,
|
|
|
|
};
|
2018-03-09 05:39:05 +01:00
|
|
|
|
2018-10-05 21:47:22 +02:00
|
|
|
// not enough data
|
|
|
|
if src.len() < idx + length {
|
|
|
|
return Ok(None);
|
2018-03-09 02:19:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// remove prefix
|
2018-10-05 21:47:22 +02:00
|
|
|
src.split_to(idx);
|
2018-02-10 02:20:28 +01:00
|
|
|
|
2018-03-09 22:03:15 +01:00
|
|
|
// no need for body
|
2018-03-09 03:19:46 +01:00
|
|
|
if length == 0 {
|
2018-10-10 22:20:00 +02:00
|
|
|
return Ok(Some((finished, opcode, None)));
|
2018-03-09 03:19:46 +01:00
|
|
|
}
|
|
|
|
|
2018-10-05 21:47:22 +02:00
|
|
|
let mut data = src.split_to(length);
|
2018-02-10 02:20:28 +01:00
|
|
|
|
|
|
|
// control frames must have length <= 125
|
|
|
|
match opcode {
|
|
|
|
OpCode::Ping | OpCode::Pong if length > 125 => {
|
2018-03-02 20:29:55 +01:00
|
|
|
return Err(ProtocolError::InvalidLength(length))
|
2017-10-08 06:48:00 +02:00
|
|
|
}
|
2018-02-10 02:20:28 +01:00
|
|
|
OpCode::Close if length > 125 => {
|
|
|
|
debug!("Received close frame with payload length exceeding 125. Morphing to protocol close frame.");
|
2018-10-10 22:20:00 +02:00
|
|
|
return Ok(Some((true, OpCode::Close, None)));
|
2017-10-08 06:48:00 +02:00
|
|
|
}
|
2018-04-14 01:02:01 +02:00
|
|
|
_ => (),
|
2018-02-10 02:20:28 +01:00
|
|
|
}
|
2017-10-08 06:48:00 +02:00
|
|
|
|
2018-02-10 02:20:28 +01:00
|
|
|
// unmask
|
2018-10-05 21:47:22 +02:00
|
|
|
if let Some(mask) = mask {
|
|
|
|
apply_mask(&mut data, mask);
|
|
|
|
}
|
2017-10-08 06:48:00 +02:00
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
Ok(Some((finished, opcode, Some(data))))
|
2017-10-08 06:48:00 +02:00
|
|
|
}
|
|
|
|
|
2018-04-21 22:50:27 +02:00
|
|
|
/// Parse the payload of a close frame.
|
2018-10-10 22:20:00 +02:00
|
|
|
pub fn parse_close_payload(payload: &[u8]) -> Option<CloseReason> {
|
2018-04-21 22:50:27 +02:00
|
|
|
if payload.len() >= 2 {
|
2018-10-10 22:20:00 +02:00
|
|
|
let raw_code = NetworkEndian::read_u16(payload);
|
2018-04-21 22:50:27 +02:00
|
|
|
let code = CloseCode::from(raw_code);
|
|
|
|
let description = if payload.len() > 2 {
|
2018-10-10 22:20:00 +02:00
|
|
|
Some(String::from_utf8_lossy(&payload[2..]).into())
|
2018-04-21 22:50:27 +02:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2018-05-17 21:20:20 +02:00
|
|
|
Some(CloseReason { code, description })
|
2018-04-21 22:50:27 +02:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-10 05:43:14 +01:00
|
|
|
/// Generate binary representation
|
2018-11-18 22:48:42 +01:00
|
|
|
pub fn write_message<B: Into<Bytes>>(
|
2018-10-30 00:39:46 +01:00
|
|
|
dst: &mut BytesMut,
|
|
|
|
pl: B,
|
|
|
|
op: OpCode,
|
|
|
|
fin: bool,
|
|
|
|
mask: bool,
|
2018-10-05 21:47:22 +02:00
|
|
|
) {
|
|
|
|
let payload = pl.into();
|
|
|
|
let one: u8 = if fin {
|
|
|
|
0x80 | Into::<u8>::into(op)
|
2018-02-10 05:43:14 +01:00
|
|
|
} else {
|
2018-10-05 21:47:22 +02:00
|
|
|
op.into()
|
2018-02-10 09:05:20 +01:00
|
|
|
};
|
|
|
|
let payload_len = payload.len();
|
2018-10-05 21:47:22 +02:00
|
|
|
let (two, p_len) = if mask {
|
2018-02-10 09:05:20 +01:00
|
|
|
(0x80, payload_len + 4)
|
|
|
|
} else {
|
|
|
|
(0, payload_len)
|
2018-02-10 05:43:14 +01:00
|
|
|
};
|
2017-10-08 06:48:00 +02:00
|
|
|
|
2018-10-05 21:47:22 +02:00
|
|
|
if payload_len < 126 {
|
|
|
|
dst.put_slice(&[one, two | payload_len as u8]);
|
2018-02-10 05:43:14 +01:00
|
|
|
} else if payload_len <= 65_535 {
|
2018-10-05 21:47:22 +02:00
|
|
|
dst.reserve(p_len + 4);
|
|
|
|
dst.put_slice(&[one, two | 126]);
|
|
|
|
dst.put_u16_be(payload_len as u16);
|
2017-10-08 06:48:00 +02:00
|
|
|
} else {
|
2018-10-05 21:47:22 +02:00
|
|
|
dst.reserve(p_len + 10);
|
|
|
|
dst.put_slice(&[one, two | 127]);
|
|
|
|
dst.put_u64_be(payload_len as u64);
|
2018-02-10 05:43:14 +01:00
|
|
|
};
|
2017-10-08 06:48:00 +02:00
|
|
|
|
2018-10-05 21:47:22 +02:00
|
|
|
if mask {
|
2018-03-09 05:39:05 +01:00
|
|
|
let mask = rand::random::<u32>();
|
2018-10-05 21:47:22 +02:00
|
|
|
dst.put_u32_le(mask);
|
|
|
|
dst.extend_from_slice(payload.as_ref());
|
|
|
|
let pos = dst.len() - payload_len;
|
|
|
|
apply_mask(&mut dst[pos..], mask);
|
2018-01-10 19:12:34 +01:00
|
|
|
} else {
|
2018-10-05 21:47:22 +02:00
|
|
|
dst.put_slice(payload.as_ref());
|
2017-10-08 06:48:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-05 21:47:22 +02:00
|
|
|
/// Create a new Close control frame.
|
|
|
|
#[inline]
|
|
|
|
pub fn write_close(dst: &mut BytesMut, reason: Option<CloseReason>, mask: bool) {
|
|
|
|
let payload = match reason {
|
|
|
|
None => Vec::new(),
|
|
|
|
Some(reason) => {
|
|
|
|
let mut code_bytes = [0; 2];
|
|
|
|
NetworkEndian::write_u16(&mut code_bytes, reason.code.into());
|
|
|
|
|
|
|
|
let mut payload = Vec::from(&code_bytes[..]);
|
|
|
|
if let Some(description) = reason.description {
|
|
|
|
payload.extend(description.as_bytes());
|
|
|
|
}
|
|
|
|
payload
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
Parser::write_message(dst, payload, OpCode::Close, true, mask)
|
2017-10-08 06:48:00 +02:00
|
|
|
}
|
|
|
|
}
|
2017-10-23 22:31:22 +02:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2018-10-10 22:20:00 +02:00
|
|
|
use bytes::Bytes;
|
2018-02-26 22:58:23 +01:00
|
|
|
|
2018-10-05 21:47:22 +02:00
|
|
|
struct F {
|
|
|
|
finished: bool,
|
|
|
|
opcode: OpCode,
|
2018-10-10 22:20:00 +02:00
|
|
|
payload: Bytes,
|
2018-10-05 21:47:22 +02:00
|
|
|
}
|
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
fn is_none(
|
|
|
|
frm: &Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError>,
|
|
|
|
) -> bool {
|
2018-04-05 05:24:09 +02:00
|
|
|
match *frm {
|
2018-10-05 21:47:22 +02:00
|
|
|
Ok(None) => true,
|
2018-02-26 22:58:23 +01:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2018-04-14 01:02:01 +02:00
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
fn extract(
|
|
|
|
frm: Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError>,
|
|
|
|
) -> F {
|
2018-02-26 22:58:23 +01:00
|
|
|
match frm {
|
2018-10-05 21:47:22 +02:00
|
|
|
Ok(Some((finished, opcode, payload))) => F {
|
|
|
|
finished,
|
|
|
|
opcode,
|
2018-10-10 22:20:00 +02:00
|
|
|
payload: payload
|
|
|
|
.map(|b| b.freeze())
|
|
|
|
.unwrap_or_else(|| Bytes::from("")),
|
2018-10-05 21:47:22 +02:00
|
|
|
},
|
2018-03-30 00:55:27 +02:00
|
|
|
_ => unreachable!("error"),
|
2018-02-26 22:58:23 +01:00
|
|
|
}
|
|
|
|
}
|
2017-10-23 22:31:22 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_parse() {
|
2018-10-05 21:47:22 +02:00
|
|
|
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b0000_0001u8][..]);
|
2018-10-10 22:20:00 +02:00
|
|
|
assert!(is_none(&Parser::parse(&mut buf, false, 1024)));
|
2018-02-26 22:58:23 +01:00
|
|
|
|
2018-04-05 05:24:09 +02:00
|
|
|
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b0000_0001u8][..]);
|
2017-10-23 22:31:22 +02:00
|
|
|
buf.extend(b"1");
|
2018-02-26 22:58:23 +01:00
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
let frame = extract(Parser::parse(&mut buf, false, 1024));
|
2017-10-23 22:31:22 +02:00
|
|
|
assert!(!frame.finished);
|
|
|
|
assert_eq!(frame.opcode, OpCode::Text);
|
2018-01-10 19:12:34 +01:00
|
|
|
assert_eq!(frame.payload.as_ref(), &b"1"[..]);
|
2017-10-23 22:31:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_parse_length0() {
|
2018-10-05 21:47:22 +02:00
|
|
|
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b0000_0000u8][..]);
|
2018-10-10 22:20:00 +02:00
|
|
|
let frame = extract(Parser::parse(&mut buf, false, 1024));
|
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() {
|
2018-10-05 21:47:22 +02:00
|
|
|
let mut buf = BytesMut::from(&[0b0000_0001u8, 126u8][..]);
|
2018-10-10 22:20:00 +02:00
|
|
|
assert!(is_none(&Parser::parse(&mut buf, false, 1024)));
|
2018-02-26 22:58:23 +01:00
|
|
|
|
2018-04-05 05:24:09 +02:00
|
|
|
let mut buf = BytesMut::from(&[0b0000_0001u8, 126u8][..]);
|
2017-10-23 22:31:22 +02:00
|
|
|
buf.extend(&[0u8, 4u8][..]);
|
|
|
|
buf.extend(b"1234");
|
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
let frame = extract(Parser::parse(&mut buf, false, 1024));
|
2017-10-23 22:31:22 +02:00
|
|
|
assert!(!frame.finished);
|
|
|
|
assert_eq!(frame.opcode, OpCode::Text);
|
2018-01-10 19:12:34 +01:00
|
|
|
assert_eq!(frame.payload.as_ref(), &b"1234"[..]);
|
2017-10-23 22:31:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_parse_length4() {
|
2018-10-05 21:47:22 +02:00
|
|
|
let mut buf = BytesMut::from(&[0b0000_0001u8, 127u8][..]);
|
2018-10-10 22:20:00 +02:00
|
|
|
assert!(is_none(&Parser::parse(&mut buf, false, 1024)));
|
2018-02-26 22:58:23 +01:00
|
|
|
|
2018-04-05 05:24:09 +02:00
|
|
|
let mut buf = BytesMut::from(&[0b0000_0001u8, 127u8][..]);
|
2017-10-23 22:31:22 +02:00
|
|
|
buf.extend(&[0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8][..]);
|
|
|
|
buf.extend(b"1234");
|
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
let frame = extract(Parser::parse(&mut buf, false, 1024));
|
2017-10-23 22:31:22 +02:00
|
|
|
assert!(!frame.finished);
|
|
|
|
assert_eq!(frame.opcode, OpCode::Text);
|
2018-01-10 19:12:34 +01:00
|
|
|
assert_eq!(frame.payload.as_ref(), &b"1234"[..]);
|
2017-10-23 22:31:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_parse_frame_mask() {
|
2018-04-05 05:24:09 +02:00
|
|
|
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b1000_0001u8][..]);
|
2017-10-23 22:31:22 +02:00
|
|
|
buf.extend(b"0001");
|
|
|
|
buf.extend(b"1");
|
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
assert!(Parser::parse(&mut buf, false, 1024).is_err());
|
2018-02-10 05:43:14 +01:00
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
let frame = extract(Parser::parse(&mut buf, true, 1024));
|
2018-02-10 05:43:14 +01:00
|
|
|
assert!(!frame.finished);
|
|
|
|
assert_eq!(frame.opcode, OpCode::Text);
|
2018-10-10 22:20:00 +02:00
|
|
|
assert_eq!(frame.payload, Bytes::from(vec![1u8]));
|
2018-02-10 05:43:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_parse_frame_no_mask() {
|
2018-04-05 05:24:09 +02:00
|
|
|
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b0000_0001u8][..]);
|
2018-02-10 05:43:14 +01:00
|
|
|
buf.extend(&[1u8]);
|
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
assert!(Parser::parse(&mut buf, true, 1024).is_err());
|
2018-02-10 05:43:14 +01:00
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
let frame = extract(Parser::parse(&mut buf, false, 1024));
|
2017-10-23 22:31:22 +02:00
|
|
|
assert!(!frame.finished);
|
|
|
|
assert_eq!(frame.opcode, OpCode::Text);
|
2018-10-10 22:20:00 +02:00
|
|
|
assert_eq!(frame.payload, Bytes::from(vec![1u8]));
|
2017-10-23 22:31:22 +02:00
|
|
|
}
|
|
|
|
|
2018-02-27 19:09:24 +01:00
|
|
|
#[test]
|
|
|
|
fn test_parse_frame_max_size() {
|
2018-04-05 05:24:09 +02:00
|
|
|
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b0000_0010u8][..]);
|
2018-02-27 19:09:24 +01:00
|
|
|
buf.extend(&[1u8, 1u8]);
|
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
assert!(Parser::parse(&mut buf, true, 1).is_err());
|
2018-02-27 19:09:24 +01:00
|
|
|
|
2018-10-10 22:20:00 +02:00
|
|
|
if let Err(ProtocolError::Overflow) = Parser::parse(&mut buf, false, 0) {
|
2018-02-27 19:09:24 +01:00
|
|
|
} else {
|
2018-03-30 00:55:27 +02:00
|
|
|
unreachable!("error");
|
2018-02-27 19:09:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-23 22:31:22 +02:00
|
|
|
#[test]
|
|
|
|
fn test_ping_frame() {
|
2018-10-05 21:47:22 +02:00
|
|
|
let mut buf = BytesMut::new();
|
2018-10-10 22:20:00 +02:00
|
|
|
Parser::write_message(&mut buf, Vec::from("data"), OpCode::Ping, true, false);
|
2017-10-23 22:31:22 +02:00
|
|
|
|
|
|
|
let mut v = vec![137u8, 4u8];
|
|
|
|
v.extend(b"data");
|
2018-10-05 21:47:22 +02:00
|
|
|
assert_eq!(&buf[..], &v[..]);
|
2017-10-23 22:31:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_pong_frame() {
|
2018-10-05 21:47:22 +02:00
|
|
|
let mut buf = BytesMut::new();
|
2018-10-10 22:20:00 +02:00
|
|
|
Parser::write_message(&mut buf, Vec::from("data"), OpCode::Pong, true, false);
|
2017-10-23 22:31:22 +02:00
|
|
|
|
|
|
|
let mut v = vec![138u8, 4u8];
|
|
|
|
v.extend(b"data");
|
2018-10-05 21:47:22 +02:00
|
|
|
assert_eq!(&buf[..], &v[..]);
|
2017-10-23 22:31:22 +02:00
|
|
|
}
|
|
|
|
|
2018-04-22 17:43:47 +02:00
|
|
|
#[test]
|
|
|
|
fn test_close_frame() {
|
2018-10-05 21:47:22 +02:00
|
|
|
let mut buf = BytesMut::new();
|
2018-04-22 17:43:47 +02:00
|
|
|
let reason = (CloseCode::Normal, "data");
|
2018-10-10 22:20:00 +02:00
|
|
|
Parser::write_close(&mut buf, Some(reason.into()), false);
|
2018-04-22 17:43:47 +02:00
|
|
|
|
|
|
|
let mut v = vec![136u8, 6u8, 3u8, 232u8];
|
|
|
|
v.extend(b"data");
|
2018-10-05 21:47:22 +02:00
|
|
|
assert_eq!(&buf[..], &v[..]);
|
2018-04-22 17:43:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_empty_close_frame() {
|
2018-10-05 21:47:22 +02:00
|
|
|
let mut buf = BytesMut::new();
|
2018-10-10 22:20:00 +02:00
|
|
|
Parser::write_close(&mut buf, None, false);
|
2018-10-05 21:47:22 +02:00
|
|
|
assert_eq!(&buf[..], &vec![0x88, 0x00][..]);
|
2018-04-22 17:43:47 +02:00
|
|
|
}
|
2017-10-23 22:31:22 +02:00
|
|
|
}
|