1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-05-20 01:08:10 +00:00
actix-web/actix-http/src/ws/frame.rs

406 lines
12 KiB
Rust
Raw Normal View History

use std::cmp::min;
2019-08-06 16:32:22 +00:00
2019-12-19 03:56:14 +00:00
use bytes::{Buf, BufMut, BytesMut};
2022-03-10 03:12:29 +00:00
use tracing::debug;
2017-10-08 04:48:00 +00:00
2022-01-31 21:22:23 +00:00
use super::{
mask::apply_mask,
proto::{CloseCode, CloseReason, OpCode},
ProtocolError,
};
2017-10-08 04:48:00 +00:00
2021-02-12 00:27:20 +00:00
/// A struct representing a WebSocket frame.
#[derive(Debug)]
2018-10-10 20:20:00 +00:00
pub struct Parser;
2017-10-08 04:48:00 +00:00
2018-10-10 20:20:00 +00:00
impl Parser {
2018-10-05 19:47:22 +00:00
fn parse_metadata(
2018-10-29 23:39:46 +00:00
src: &[u8],
server: bool,
2021-12-08 06:01:11 +00:00
) -> Result<Option<(usize, bool, OpCode, usize, Option<[u8; 4]>)>, ProtocolError> {
2018-10-05 19:47:22 +00:00
let chunk_len = src.len();
2018-03-09 04:39:05 +00:00
let mut idx = 2;
if chunk_len < 2 {
2018-10-05 19:47:22 +00:00
return Ok(None);
2018-03-09 04:39:05 +00:00
}
2018-10-05 19:47:22 +00:00
let first = src[0];
let second = src[1];
2018-03-09 04:39:05 +00:00
let finished = first & 0x80 != 0;
// check masking
let masked = second & 0x80 != 0;
if !masked && server {
2018-04-13 23:02:01 +00:00
return Err(ProtocolError::UnmaskedFrame);
2018-03-09 04:39:05 +00:00
} else if masked && !server {
2018-04-13 23:02:01 +00:00
return Err(ProtocolError::MaskedFrame);
2018-03-09 04:39:05 +00:00
}
// Op code
let opcode = OpCode::from(first & 0x0F);
if let OpCode::Bad = opcode {
2018-04-13 23:02:01 +00:00
return Err(ProtocolError::InvalidOpcode(first & 0x0F));
2018-03-09 04:39:05 +00:00
}
let len = second & 0x7F;
let length = if len == 126 {
if chunk_len < 4 {
2018-10-05 19:47:22 +00:00
return Ok(None);
2018-03-09 04:39:05 +00:00
}
2019-08-06 16:32:22 +00:00
let len = usize::from(u16::from_be_bytes(
TryFrom::try_from(&src[idx..idx + 2]).unwrap(),
));
2018-03-09 04:39:05 +00:00
idx += 2;
len
} else if len == 127 {
if chunk_len < 10 {
2018-10-05 19:47:22 +00:00
return Ok(None);
2018-03-09 04:39:05 +00:00
}
2019-08-06 16:32:22 +00:00
let len = u64::from_be_bytes(TryFrom::try_from(&src[idx..idx + 8]).unwrap());
2018-03-09 04:39:05 +00:00
idx += 8;
2018-07-06 01:46:47 +00:00
len as usize
2018-03-09 04:39:05 +00:00
} else {
len as usize
};
let mask = if server {
if chunk_len < idx + 4 {
2018-10-05 19:47:22 +00:00
return Ok(None);
2018-03-09 04:39:05 +00:00
}
2021-02-10 23:11:12 +00:00
let mask = TryFrom::try_from(&src[idx..idx + 4]).unwrap();
2018-03-09 04:39:05 +00:00
idx += 4;
2021-02-10 23:11:12 +00:00
2019-08-06 16:32:22 +00:00
Some(mask)
2018-03-09 04:39:05 +00:00
} else {
None
};
2018-10-05 19:47:22 +00:00
Ok(Some((idx, finished, opcode, length, mask)))
2018-03-09 04:39:05 +00:00
}
/// Parse the input stream into a frame.
2018-10-05 19:47:22 +00:00
pub fn parse(
2018-10-29 23:39:46 +00:00
src: &mut BytesMut,
server: bool,
max_size: usize,
2018-10-10 20:20:00 +00:00
) -> Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError> {
2018-10-05 19:47:22 +00:00
// try to parse ws frame metadata
let (idx, finished, opcode, length, mask) = match Parser::parse_metadata(src, server)? {
None => return Ok(None),
Some(res) => res,
};
2018-03-09 04:39:05 +00:00
2018-10-05 19:47:22 +00:00
// not enough data
if src.len() < idx + length {
let min_length = min(length, max_size);
if src.capacity() < idx + min_length {
src.reserve(idx + min_length - src.capacity());
}
2018-10-05 19:47:22 +00:00
return Ok(None);
2018-03-09 01:19:50 +00:00
}
// remove prefix
2019-12-19 03:56:14 +00:00
src.advance(idx);
// check for max allowed size
if length > max_size {
// drop the payload
src.advance(length);
return Err(ProtocolError::Overflow);
}
2018-03-09 21:03:15 +00:00
// no need for body
2018-03-09 02:19:46 +00:00
if length == 0 {
2018-10-10 20:20:00 +00:00
return Ok(Some((finished, opcode, None)));
2018-03-09 02:19:46 +00:00
}
2018-10-05 19:47:22 +00:00
let mut data = src.split_to(length);
// control frames must have length <= 125
match opcode {
OpCode::Ping | OpCode::Pong if length > 125 => {
2019-02-02 04:18:44 +00:00
return Err(ProtocolError::InvalidLength(length));
2017-10-08 04:48:00 +00:00
}
OpCode::Close if length > 125 => {
debug!("Received close frame with payload length exceeding 125. Morphing to protocol close frame.");
2018-10-10 20:20:00 +00:00
return Ok(Some((true, OpCode::Close, None)));
2017-10-08 04:48:00 +00:00
}
2021-01-04 01:01:35 +00:00
_ => {}
}
2017-10-08 04:48:00 +00:00
// unmask
2018-10-05 19:47:22 +00:00
if let Some(mask) = mask {
apply_mask(&mut data, mask);
}
2017-10-08 04:48:00 +00:00
2018-10-10 20:20:00 +00:00
Ok(Some((finished, opcode, Some(data))))
2017-10-08 04:48:00 +00:00
}
/// Parse the payload of a close frame.
2018-10-10 20:20:00 +00:00
pub fn parse_close_payload(payload: &[u8]) -> Option<CloseReason> {
if payload.len() >= 2 {
2019-08-06 16:32:22 +00:00
let raw_code = u16::from_be_bytes(TryFrom::try_from(&payload[..2]).unwrap());
let code = CloseCode::from(raw_code);
let description = if payload.len() > 2 {
2018-10-10 20:20:00 +00:00
Some(String::from_utf8_lossy(&payload[2..]).into())
} else {
None
};
2018-05-17 19:20:20 +00:00
Some(CloseReason { code, description })
} else {
None
}
}
2018-02-10 04:43:14 +00:00
/// Generate binary representation
pub fn write_message<B: AsRef<[u8]>>(
2018-10-29 23:39:46 +00:00
dst: &mut BytesMut,
pl: B,
op: OpCode,
fin: bool,
mask: bool,
2018-10-05 19:47:22 +00:00
) {
let payload = pl.as_ref();
2018-10-05 19:47:22 +00:00
let one: u8 = if fin {
0x80 | Into::<u8>::into(op)
2018-02-10 04:43:14 +00:00
} else {
2018-10-05 19:47:22 +00:00
op.into()
2018-02-10 08:05:20 +00:00
};
let payload_len = payload.len();
2018-10-05 19:47:22 +00:00
let (two, p_len) = if mask {
2018-02-10 08:05:20 +00:00
(0x80, payload_len + 4)
} else {
(0, payload_len)
2018-02-10 04:43:14 +00:00
};
2017-10-08 04:48:00 +00:00
2018-10-05 19:47:22 +00:00
if payload_len < 126 {
2019-04-01 00:05:02 +00:00
dst.reserve(p_len + 2 + if mask { 4 } else { 0 });
2018-10-05 19:47:22 +00:00
dst.put_slice(&[one, two | payload_len as u8]);
2018-02-10 04:43:14 +00:00
} else if payload_len <= 65_535 {
2019-04-01 00:05:02 +00:00
dst.reserve(p_len + 4 + if mask { 4 } else { 0 });
2018-10-05 19:47:22 +00:00
dst.put_slice(&[one, two | 126]);
2019-12-05 17:35:43 +00:00
dst.put_u16(payload_len as u16);
2017-10-08 04:48:00 +00:00
} else {
2019-04-01 00:05:02 +00:00
dst.reserve(p_len + 10 + if mask { 4 } else { 0 });
2018-10-05 19:47:22 +00:00
dst.put_slice(&[one, two | 127]);
2019-12-05 17:35:43 +00:00
dst.put_u64(payload_len as u64);
2018-02-10 04:43:14 +00:00
};
2017-10-08 04:48:00 +00:00
2018-10-05 19:47:22 +00:00
if mask {
2021-02-10 23:11:12 +00:00
let mask = rand::random::<[u8; 4]>();
dst.put_slice(mask.as_ref());
2019-04-01 00:05:02 +00:00
dst.put_slice(payload.as_ref());
2018-10-05 19:47:22 +00:00
let pos = dst.len() - payload_len;
apply_mask(&mut dst[pos..], mask);
} else {
2018-10-05 19:47:22 +00:00
dst.put_slice(payload.as_ref());
2017-10-08 04:48:00 +00:00
}
}
2018-10-05 19:47:22 +00: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) => {
2019-08-06 16:32:22 +00:00
let mut payload = Into::<u16>::into(reason.code).to_be_bytes().to_vec();
2018-10-05 19:47:22 +00:00
if let Some(description) = reason.description {
payload.extend(description.as_bytes());
}
payload
}
};
2018-10-10 20:20:00 +00:00
Parser::write_message(dst, payload, OpCode::Close, true, mask)
2017-10-08 04:48:00 +00:00
}
}
2017-10-23 20:31:22 +00:00
#[cfg(test)]
mod tests {
2018-10-10 20:20:00 +00:00
use bytes::Bytes;
2018-02-26 21:58:23 +00:00
2023-07-17 01:38:12 +00:00
use super::*;
2018-10-05 19:47:22 +00:00
struct F {
finished: bool,
opcode: OpCode,
2018-10-10 20:20:00 +00:00
payload: Bytes,
2018-10-05 19:47:22 +00:00
}
2021-12-08 06:01:11 +00:00
fn is_none(frm: &Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError>) -> bool {
2020-07-21 07:40:30 +00:00
matches!(*frm, Ok(None))
2018-02-26 21:58:23 +00:00
}
2018-04-13 23:02:01 +00:00
2021-12-08 06:01:11 +00:00
fn extract(frm: Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError>) -> F {
2018-02-26 21:58:23 +00:00
match frm {
2018-10-05 19:47:22 +00:00
Ok(Some((finished, opcode, payload))) => F {
finished,
opcode,
2018-10-10 20:20:00 +00:00
payload: payload
.map(|b| b.freeze())
.unwrap_or_else(|| Bytes::from("")),
2018-10-05 19:47:22 +00:00
},
2018-03-29 22:55:27 +00:00
_ => unreachable!("error"),
2018-02-26 21:58:23 +00:00
}
}
2017-10-23 20:31:22 +00:00
#[test]
fn test_parse() {
2018-10-05 19:47:22 +00:00
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b0000_0001u8][..]);
2018-10-10 20:20:00 +00:00
assert!(is_none(&Parser::parse(&mut buf, false, 1024)));
2018-02-26 21:58:23 +00:00
2018-04-05 03:24:09 +00:00
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b0000_0001u8][..]);
2017-10-23 20:31:22 +00:00
buf.extend(b"1");
2018-02-26 21:58:23 +00:00
2018-10-10 20:20:00 +00:00
let frame = extract(Parser::parse(&mut buf, false, 1024));
2017-10-23 20:31:22 +00:00
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
assert_eq!(frame.payload.as_ref(), &b"1"[..]);
2017-10-23 20:31:22 +00:00
}
#[test]
fn test_parse_length0() {
2018-10-05 19:47:22 +00:00
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b0000_0000u8][..]);
2018-10-10 20:20:00 +00:00
let frame = extract(Parser::parse(&mut buf, false, 1024));
2017-10-23 20:31:22 +00:00
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
assert!(frame.payload.is_empty());
}
#[test]
fn test_parse_length2() {
2018-10-05 19:47:22 +00:00
let mut buf = BytesMut::from(&[0b0000_0001u8, 126u8][..]);
2018-10-10 20:20:00 +00:00
assert!(is_none(&Parser::parse(&mut buf, false, 1024)));
2018-02-26 21:58:23 +00:00
2018-04-05 03:24:09 +00:00
let mut buf = BytesMut::from(&[0b0000_0001u8, 126u8][..]);
2017-10-23 20:31:22 +00:00
buf.extend(&[0u8, 4u8][..]);
buf.extend(b"1234");
2018-10-10 20:20:00 +00:00
let frame = extract(Parser::parse(&mut buf, false, 1024));
2017-10-23 20:31:22 +00:00
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
assert_eq!(frame.payload.as_ref(), &b"1234"[..]);
2017-10-23 20:31:22 +00:00
}
#[test]
fn test_parse_length4() {
2018-10-05 19:47:22 +00:00
let mut buf = BytesMut::from(&[0b0000_0001u8, 127u8][..]);
2018-10-10 20:20:00 +00:00
assert!(is_none(&Parser::parse(&mut buf, false, 1024)));
2018-02-26 21:58:23 +00:00
2018-04-05 03:24:09 +00:00
let mut buf = BytesMut::from(&[0b0000_0001u8, 127u8][..]);
2017-10-23 20:31:22 +00:00
buf.extend(&[0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8][..]);
buf.extend(b"1234");
2018-10-10 20:20:00 +00:00
let frame = extract(Parser::parse(&mut buf, false, 1024));
2017-10-23 20:31:22 +00:00
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
assert_eq!(frame.payload.as_ref(), &b"1234"[..]);
2017-10-23 20:31:22 +00:00
}
#[test]
fn test_parse_frame_mask() {
2018-04-05 03:24:09 +00:00
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b1000_0001u8][..]);
2017-10-23 20:31:22 +00:00
buf.extend(b"0001");
buf.extend(b"1");
2018-10-10 20:20:00 +00:00
assert!(Parser::parse(&mut buf, false, 1024).is_err());
2018-02-10 04:43:14 +00:00
2018-10-10 20:20:00 +00:00
let frame = extract(Parser::parse(&mut buf, true, 1024));
2018-02-10 04:43:14 +00:00
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
2018-10-10 20:20:00 +00:00
assert_eq!(frame.payload, Bytes::from(vec![1u8]));
2018-02-10 04:43:14 +00:00
}
#[test]
fn test_parse_frame_no_mask() {
2018-04-05 03:24:09 +00:00
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b0000_0001u8][..]);
2022-09-25 19:54:17 +00:00
buf.extend([1u8]);
2018-02-10 04:43:14 +00:00
2018-10-10 20:20:00 +00:00
assert!(Parser::parse(&mut buf, true, 1024).is_err());
2018-02-10 04:43:14 +00:00
2018-10-10 20:20:00 +00:00
let frame = extract(Parser::parse(&mut buf, false, 1024));
2017-10-23 20:31:22 +00:00
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Text);
2018-10-10 20:20:00 +00:00
assert_eq!(frame.payload, Bytes::from(vec![1u8]));
2017-10-23 20:31:22 +00:00
}
2018-02-27 18:09:24 +00:00
#[test]
fn test_parse_frame_max_size() {
2018-04-05 03:24:09 +00:00
let mut buf = BytesMut::from(&[0b0000_0001u8, 0b0000_0010u8][..]);
2022-09-25 19:54:17 +00:00
buf.extend([1u8, 1u8]);
2018-02-27 18:09:24 +00:00
2018-10-10 20:20:00 +00:00
assert!(Parser::parse(&mut buf, true, 1).is_err());
2018-02-27 18:09:24 +00:00
2018-10-10 20:20:00 +00:00
if let Err(ProtocolError::Overflow) = Parser::parse(&mut buf, false, 0) {
2018-02-27 18:09:24 +00:00
} else {
2018-03-29 22:55:27 +00:00
unreachable!("error");
2018-02-27 18:09:24 +00:00
}
}
#[test]
fn test_parse_frame_max_size_recoverability() {
let mut buf = BytesMut::new();
// The first text frame with length == 2, payload doesn't matter.
2022-09-25 19:54:17 +00:00
buf.extend([0b0000_0001u8, 0b0000_0010u8, 0b0000_0000u8, 0b0000_0000u8]);
// Next binary frame with length == 2 and payload == `[0x1111_1111u8, 0x1111_1111u8]`.
2022-09-25 19:54:17 +00:00
buf.extend([0b0000_0010u8, 0b0000_0010u8, 0b1111_1111u8, 0b1111_1111u8]);
assert_eq!(buf.len(), 8);
assert!(matches!(
Parser::parse(&mut buf, false, 1),
Err(ProtocolError::Overflow)
));
assert_eq!(buf.len(), 4);
let frame = extract(Parser::parse(&mut buf, false, 2));
assert!(!frame.finished);
assert_eq!(frame.opcode, OpCode::Binary);
assert_eq!(
frame.payload,
Bytes::from(vec![0b1111_1111u8, 0b1111_1111u8])
);
assert_eq!(buf.len(), 0);
}
2017-10-23 20:31:22 +00:00
#[test]
fn test_ping_frame() {
2018-10-05 19:47:22 +00:00
let mut buf = BytesMut::new();
2018-10-10 20:20:00 +00:00
Parser::write_message(&mut buf, Vec::from("data"), OpCode::Ping, true, false);
2017-10-23 20:31:22 +00:00
let mut v = vec![137u8, 4u8];
v.extend(b"data");
2018-10-05 19:47:22 +00:00
assert_eq!(&buf[..], &v[..]);
2017-10-23 20:31:22 +00:00
}
#[test]
fn test_pong_frame() {
2018-10-05 19:47:22 +00:00
let mut buf = BytesMut::new();
2018-10-10 20:20:00 +00:00
Parser::write_message(&mut buf, Vec::from("data"), OpCode::Pong, true, false);
2017-10-23 20:31:22 +00:00
let mut v = vec![138u8, 4u8];
v.extend(b"data");
2018-10-05 19:47:22 +00:00
assert_eq!(&buf[..], &v[..]);
2017-10-23 20:31:22 +00:00
}
2018-04-22 15:43:47 +00:00
#[test]
fn test_close_frame() {
2018-10-05 19:47:22 +00:00
let mut buf = BytesMut::new();
2018-04-22 15:43:47 +00:00
let reason = (CloseCode::Normal, "data");
2018-10-10 20:20:00 +00:00
Parser::write_close(&mut buf, Some(reason.into()), false);
2018-04-22 15:43:47 +00:00
let mut v = vec![136u8, 6u8, 3u8, 232u8];
v.extend(b"data");
2018-10-05 19:47:22 +00:00
assert_eq!(&buf[..], &v[..]);
2018-04-22 15:43:47 +00:00
}
#[test]
fn test_empty_close_frame() {
2018-10-05 19:47:22 +00:00
let mut buf = BytesMut::new();
2018-10-10 20:20:00 +00:00
Parser::write_close(&mut buf, None, false);
2018-10-05 19:47:22 +00:00
assert_eq!(&buf[..], &vec![0x88, 0x00][..]);
2018-04-22 15:43:47 +00:00
}
2017-10-23 20:31:22 +00:00
}