1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-25 00:12:59 +01:00
actix-extras/src/ws/codec.rs

149 lines
4.5 KiB
Rust
Raw Normal View History

2018-10-05 21:47:22 +02:00
use bytes::BytesMut;
use tokio_codec::{Decoder, Encoder};
2018-10-10 22:20:00 +02:00
use super::frame::Parser;
2018-10-05 21:47:22 +02:00
use super::proto::{CloseReason, OpCode};
use super::ProtocolError;
use body::Binary;
/// `WebSocket` Message
#[derive(Debug, PartialEq)]
pub enum Message {
/// Text message
Text(String),
/// Binary message
Binary(Binary),
/// Ping message
Ping(String),
/// Pong message
Pong(String),
/// Close message with optional reason
Close(Option<CloseReason>),
}
2018-10-10 22:20:00 +02:00
/// `WebSocket` frame
#[derive(Debug, PartialEq)]
pub enum Frame {
/// Text frame, codec does not verify utf8 encoding
Text(Option<BytesMut>),
/// Binary frame
Binary(Option<BytesMut>),
/// Ping message
Ping(String),
/// Pong message
Pong(String),
/// Close message with optional reason
Close(Option<CloseReason>),
}
2018-10-24 06:44:20 +02:00
#[derive(Debug)]
2018-10-05 21:47:22 +02:00
/// WebSockets protocol codec
pub struct Codec {
max_size: usize,
server: bool,
}
impl Codec {
/// Create new websocket frames decoder
pub fn new() -> Codec {
Codec {
max_size: 65_536,
server: true,
}
}
/// Set max frame size
///
/// By default max size is set to 64kb
pub fn max_size(mut self, size: usize) -> Self {
self.max_size = size;
self
}
/// Set decoder to client mode.
///
/// By default decoder works in server mode.
pub fn client_mode(mut self) -> Self {
self.server = false;
self
}
}
impl Encoder for Codec {
type Item = Message;
type Error = ProtocolError;
fn encode(&mut self, item: Message, dst: &mut BytesMut) -> Result<(), Self::Error> {
match item {
Message::Text(txt) => {
2018-10-10 22:20:00 +02:00
Parser::write_message(dst, txt, OpCode::Text, true, !self.server)
2018-10-05 21:47:22 +02:00
}
Message::Binary(bin) => {
2018-10-10 22:20:00 +02:00
Parser::write_message(dst, bin, OpCode::Binary, true, !self.server)
2018-10-05 21:47:22 +02:00
}
Message::Ping(txt) => {
2018-10-10 22:20:00 +02:00
Parser::write_message(dst, txt, OpCode::Ping, true, !self.server)
2018-10-05 21:47:22 +02:00
}
Message::Pong(txt) => {
2018-10-10 22:20:00 +02:00
Parser::write_message(dst, txt, OpCode::Pong, true, !self.server)
2018-10-05 21:47:22 +02:00
}
2018-10-10 22:20:00 +02:00
Message::Close(reason) => Parser::write_close(dst, reason, !self.server),
2018-10-05 21:47:22 +02:00
}
Ok(())
}
}
impl Decoder for Codec {
2018-10-10 22:20:00 +02:00
type Item = Frame;
2018-10-05 21:47:22 +02:00
type Error = ProtocolError;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
2018-10-10 22:20:00 +02:00
match Parser::parse(src, self.server, self.max_size) {
2018-10-05 21:47:22 +02:00
Ok(Some((finished, opcode, payload))) => {
// continuation is not supported
if !finished {
return Err(ProtocolError::NoContinuation);
}
match opcode {
OpCode::Continue => Err(ProtocolError::NoContinuation),
OpCode::Bad => Err(ProtocolError::BadOpCode),
OpCode::Close => {
2018-10-10 22:20:00 +02:00
if let Some(ref pl) = payload {
let close_reason = Parser::parse_close_payload(pl);
Ok(Some(Frame::Close(close_reason)))
} else {
Ok(Some(Frame::Close(None)))
}
2018-10-05 21:47:22 +02:00
}
2018-10-10 22:20:00 +02:00
OpCode::Ping => {
if let Some(ref pl) = payload {
Ok(Some(Frame::Ping(String::from_utf8_lossy(pl).into())))
} else {
Ok(Some(Frame::Ping(String::new())))
2018-10-05 21:47:22 +02:00
}
}
2018-10-10 22:20:00 +02:00
OpCode::Pong => {
if let Some(ref pl) = payload {
Ok(Some(Frame::Pong(String::from_utf8_lossy(pl).into())))
} else {
Ok(Some(Frame::Pong(String::new())))
}
}
OpCode::Binary => Ok(Some(Frame::Binary(payload))),
OpCode::Text => {
Ok(Some(Frame::Text(payload)))
//let tmp = Vec::from(payload.as_ref());
//match String::from_utf8(tmp) {
// Ok(s) => Ok(Some(Message::Text(s))),
// Err(_) => Err(ProtocolError::BadEncoding),
//}
}
2018-10-05 21:47:22 +02:00
}
}
Ok(None) => Ok(None),
Err(e) => Err(e),
}
}
}