mirror of https://github.com/fafhrd91/actix-web
Fix RSV bit to be autobahn compliant
This commit is contained in:
parent
73580fb527
commit
74d4a89ae8
|
@ -101,12 +101,21 @@ impl Decoder for Codec {
|
||||||
|
|
||||||
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||||
match Parser::parse(src, self.server, self.max_size) {
|
match Parser::parse(src, self.server, self.max_size) {
|
||||||
Ok(Some((finished, opcode, payload))) => {
|
Ok(Some((finished, rsv, opcode, payload))) => {
|
||||||
// continuation is not supported
|
// continuation is not supported
|
||||||
if !finished {
|
if !finished {
|
||||||
return Err(ProtocolError::NoContinuation);
|
return Err(ProtocolError::NoContinuation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Since this is the default codec we have no extension
|
||||||
|
// and should fail if rsv is set.
|
||||||
|
// In an async context this will cause a NON-STRICT
|
||||||
|
// autoban complience since we might terminate
|
||||||
|
// before receiving the prior message.
|
||||||
|
if rsv != 0 {
|
||||||
|
return Err(ProtocolError::RSVSet);
|
||||||
|
}
|
||||||
|
|
||||||
match opcode {
|
match opcode {
|
||||||
OpCode::Continue => Err(ProtocolError::NoContinuation),
|
OpCode::Continue => Err(ProtocolError::NoContinuation),
|
||||||
OpCode::Bad => Err(ProtocolError::BadOpCode),
|
OpCode::Bad => Err(ProtocolError::BadOpCode),
|
||||||
|
|
|
@ -17,7 +17,8 @@ impl Parser {
|
||||||
src: &[u8],
|
src: &[u8],
|
||||||
server: bool,
|
server: bool,
|
||||||
max_size: usize,
|
max_size: usize,
|
||||||
) -> Result<Option<(usize, bool, OpCode, usize, Option<u32>)>, ProtocolError> {
|
) -> Result<Option<(usize, bool, u8, OpCode, usize, Option<u32>)>, ProtocolError>
|
||||||
|
{
|
||||||
let chunk_len = src.len();
|
let chunk_len = src.len();
|
||||||
|
|
||||||
let mut idx = 2;
|
let mut idx = 2;
|
||||||
|
@ -28,6 +29,7 @@ impl Parser {
|
||||||
let first = src[0];
|
let first = src[0];
|
||||||
let second = src[1];
|
let second = src[1];
|
||||||
let finished = first & 0x80 != 0;
|
let finished = first & 0x80 != 0;
|
||||||
|
let rsv: u8 = first & 0x70 >> 4;
|
||||||
|
|
||||||
// check masking
|
// check masking
|
||||||
let masked = second & 0x80 != 0;
|
let masked = second & 0x80 != 0;
|
||||||
|
@ -86,7 +88,7 @@ impl Parser {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some((idx, finished, opcode, length, mask)))
|
Ok(Some((idx, finished, rsv, opcode, length, mask)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the input stream into a frame.
|
/// Parse the input stream into a frame.
|
||||||
|
@ -94,9 +96,9 @@ impl Parser {
|
||||||
src: &mut BytesMut,
|
src: &mut BytesMut,
|
||||||
server: bool,
|
server: bool,
|
||||||
max_size: usize,
|
max_size: usize,
|
||||||
) -> Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError> {
|
) -> Result<Option<(bool, u8, OpCode, Option<BytesMut>)>, ProtocolError> {
|
||||||
// try to parse ws frame metadata
|
// try to parse ws frame metadata
|
||||||
let (idx, finished, opcode, length, mask) =
|
let (idx, finished, rsv, opcode, length, mask) =
|
||||||
match Parser::parse_metadata(src, server, max_size)? {
|
match Parser::parse_metadata(src, server, max_size)? {
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
Some(res) => res,
|
Some(res) => res,
|
||||||
|
@ -112,7 +114,7 @@ impl Parser {
|
||||||
|
|
||||||
// no need for body
|
// no need for body
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return Ok(Some((finished, opcode, None)));
|
return Ok(Some((finished, rsv, opcode, None)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut data = src.split_to(length);
|
let mut data = src.split_to(length);
|
||||||
|
@ -124,7 +126,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
OpCode::Close if length > 125 => {
|
OpCode::Close if length > 125 => {
|
||||||
debug!("Received close frame with payload length exceeding 125. Morphing to protocol close frame.");
|
debug!("Received close frame with payload length exceeding 125. Morphing to protocol close frame.");
|
||||||
return Ok(Some((true, OpCode::Close, None)));
|
return Ok(Some((true, rsv, OpCode::Close, None)));
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -134,7 +136,7 @@ impl Parser {
|
||||||
apply_mask(&mut data, mask);
|
apply_mask(&mut data, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some((finished, opcode, Some(data))))
|
Ok(Some((finished, rsv, opcode, Some(data))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the payload of a close frame.
|
/// Parse the payload of a close frame.
|
||||||
|
@ -223,12 +225,13 @@ mod tests {
|
||||||
|
|
||||||
struct F {
|
struct F {
|
||||||
finished: bool,
|
finished: bool,
|
||||||
|
rsv: u8,
|
||||||
opcode: OpCode,
|
opcode: OpCode,
|
||||||
payload: Bytes,
|
payload: Bytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_none(
|
fn is_none(
|
||||||
frm: &Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError>,
|
frm: &Result<Option<(bool, u8, OpCode, Option<BytesMut>)>, ProtocolError>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match *frm {
|
match *frm {
|
||||||
Ok(None) => true,
|
Ok(None) => true,
|
||||||
|
@ -237,11 +240,12 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract(
|
fn extract(
|
||||||
frm: Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError>,
|
frm: Result<Option<(bool, u8, OpCode, Option<BytesMut>)>, ProtocolError>,
|
||||||
) -> F {
|
) -> F {
|
||||||
match frm {
|
match frm {
|
||||||
Ok(Some((finished, opcode, payload))) => F {
|
Ok(Some((finished, rsv, opcode, payload))) => F {
|
||||||
finished,
|
finished,
|
||||||
|
rsv,
|
||||||
opcode,
|
opcode,
|
||||||
payload: payload
|
payload: payload
|
||||||
.map(|b| b.freeze())
|
.map(|b| b.freeze())
|
||||||
|
@ -344,6 +348,20 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_rsv() {
|
||||||
|
let mut buf = BytesMut::from(&[0b0111_0001u8, 0b0000_0001u8][..]);
|
||||||
|
buf.extend(&[1u8]);
|
||||||
|
|
||||||
|
assert!(Parser::parse(&mut buf, true, 1024).is_err());
|
||||||
|
|
||||||
|
let frame = extract(Parser::parse(&mut buf, false, 1024));
|
||||||
|
assert!(!frame.finished);
|
||||||
|
assert_eq!(frame.rsv, 7);
|
||||||
|
assert_eq!(frame.opcode, OpCode::Text);
|
||||||
|
assert_eq!(frame.payload, Bytes::from(vec![1u8]));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ping_frame() {
|
fn test_ping_frame() {
|
||||||
let mut buf = BytesMut::new();
|
let mut buf = BytesMut::new();
|
||||||
|
|
|
@ -50,6 +50,9 @@ pub enum ProtocolError {
|
||||||
/// Bad utf-8 encoding
|
/// Bad utf-8 encoding
|
||||||
#[display(fmt = "Bad utf-8 encoding.")]
|
#[display(fmt = "Bad utf-8 encoding.")]
|
||||||
BadEncoding,
|
BadEncoding,
|
||||||
|
/// Continuation is not supported
|
||||||
|
#[display(fmt = "RSV set without extensions.")]
|
||||||
|
RSVSet,
|
||||||
/// Io error
|
/// Io error
|
||||||
#[display(fmt = "io error: {}", _0)]
|
#[display(fmt = "io error: {}", _0)]
|
||||||
Io(io::Error),
|
Io(io::Error),
|
||||||
|
|
Loading…
Reference in New Issue