feat: WIP on frame continuation

This commit is contained in:
Maciej Hirsz 2019-11-05 21:14:00 +01:00
parent b5b91fce05
commit 3cc8490c82
2 changed files with 31 additions and 17 deletions

View File

@ -37,11 +37,12 @@ pub enum Frame {
Close(Option<CloseReason>), Close(Option<CloseReason>),
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Clone)]
/// WebSockets protocol codec /// WebSockets protocol codec
pub struct Codec { pub struct Codec {
max_size: usize, max_size: usize,
server: bool, server: bool,
collector: Option<BytesMut>,
} }
impl Codec { impl Codec {
@ -50,6 +51,7 @@ impl Codec {
Codec { Codec {
max_size: 65_536, max_size: 65_536,
server: true, server: true,
collector: None,
} }
} }
@ -102,16 +104,22 @@ 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, opcode, payload))) => {
// continuation is not supported
if !finished {
error!("No continuation 1");
return Err(ProtocolError::NoContinuation);
}
match opcode { match opcode {
OpCode::Continue => { OpCode::Continue => {
error!("No continuation 2"); match self.collector {
Err(ProtocolError::NoContinuation) Some(ref mut prev) => {
if let Some(ref payload) = payload {
prev.extend_from_slice(payload);
}
}
None => self.collector = payload,
}
if finished {
Ok(Some(Frame::Binary(self.collector.take())))
} else {
Ok(None)
}
} }
OpCode::Bad => { OpCode::Bad => {
error!("Bad opcode"); error!("Bad opcode");
@ -140,9 +148,21 @@ impl Decoder for Codec {
Ok(Some(Frame::Pong(String::new()))) Ok(Some(Frame::Pong(String::new())))
} }
} }
OpCode::Binary => Ok(Some(Frame::Binary(payload))), OpCode::Binary => {
if finished {
Ok(Some(Frame::Binary(payload)))
} else {
self.collector = payload;
Ok(None)
}
}
OpCode::Text => { OpCode::Text => {
Ok(Some(Frame::Text(payload))) if finished {
Ok(Some(Frame::Text(payload)))
} else {
self.collector = payload;
Ok(None)
}
//let tmp = Vec::from(payload.as_ref()); //let tmp = Vec::from(payload.as_ref());
//match String::from_utf8(tmp) { //match String::from_utf8(tmp) {
// Ok(s) => Ok(Some(Message::Text(s))), // Ok(s) => Ok(Some(Message::Text(s))),

View File

@ -32,10 +32,8 @@ impl Parser {
// check masking // check masking
let masked = second & 0x80 != 0; let masked = second & 0x80 != 0;
if !masked && server { if !masked && server {
error!("Protocol unmasked frame");
return Err(ProtocolError::UnmaskedFrame); return Err(ProtocolError::UnmaskedFrame);
} else if masked && !server { } else if masked && !server {
error!("Protocol masked frame");
return Err(ProtocolError::MaskedFrame); return Err(ProtocolError::MaskedFrame);
} }
@ -43,7 +41,6 @@ impl Parser {
let opcode = OpCode::from(first & 0x0F); let opcode = OpCode::from(first & 0x0F);
if let OpCode::Bad = opcode { if let OpCode::Bad = opcode {
error!("Protocol invalid opcode");
return Err(ProtocolError::InvalidOpcode(first & 0x0F)); return Err(ProtocolError::InvalidOpcode(first & 0x0F));
} }
@ -63,7 +60,6 @@ impl Parser {
} }
let len = u64::from_be_bytes(TryFrom::try_from(&src[idx..idx + 8]).unwrap()); let len = u64::from_be_bytes(TryFrom::try_from(&src[idx..idx + 8]).unwrap());
if len > max_size as u64 { if len > max_size as u64 {
error!("Protocol overflow 1");
return Err(ProtocolError::Overflow); return Err(ProtocolError::Overflow);
} }
idx += 8; idx += 8;
@ -74,7 +70,6 @@ impl Parser {
// check for max allowed size // check for max allowed size
if length > max_size { if length > max_size {
error!("Protocol overflow 2");
return Err(ProtocolError::Overflow); return Err(ProtocolError::Overflow);
} }
@ -125,7 +120,6 @@ impl Parser {
// control frames must have length <= 125 // control frames must have length <= 125
match opcode { match opcode {
OpCode::Ping | OpCode::Pong if length > 125 => { OpCode::Ping | OpCode::Pong if length > 125 => {
error!("Protocol invalid length");
return Err(ProtocolError::InvalidLength(length)); return Err(ProtocolError::InvalidLength(length));
} }
OpCode::Close if length > 125 => { OpCode::Close if length > 125 => {