Fix RSV bit to be autobahn compliant

This commit is contained in:
Heinz Gies 2019-09-10 13:15:42 +02:00 committed by Heinz N. Gies
parent 73580fb527
commit 74d4a89ae8
3 changed files with 41 additions and 11 deletions

View File

@ -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),

View File

@ -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();

View File

@ -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),