use std::fmt; use std::io; use bytes::{Buf, BytesMut}; use tokio_io::codec::length_delimited; use tokio_io::{AsyncRead, AsyncWrite}; use proto::peer; use proto::{Decode, ProtoEncode, ProtoEncoder, ServerRequest, ServerResponse}; fn decode_frame<'a, T>(frame_type: &str, bytes: &'a mut BytesMut) -> io::Result where T: fmt::Debug, io::Cursor<&'a mut BytesMut>: Decode, { let mut cursor = io::Cursor::new(bytes); let frame = cursor.decode()?; if cursor.has_remaining() { warn!( "Received {} with trailing bytes. Frame:\n{:?}Bytes:{:?}", frame_type, frame, cursor.bytes() ); } Ok(frame) } fn encode_frame(frame: &T) -> io::Result { let mut bytes = BytesMut::new(); frame.encode(&mut ProtoEncoder::new(&mut bytes))?; Ok(bytes) } /// Wraps a raw byte async I/O object, providing it with the ability to read and /// write entire frames at once. /// The returned stream and sink of frames is intended to be combined (using /// `Stream::and_then` and `Sink::with`) with the following decoding and /// encoding functions to create a stream/sink of decoded messages. pub fn new_framed(io: T) -> length_delimited::Framed { length_delimited::Builder::new() .length_field_length(4) .little_endian() .new_framed(io) } /// Decodes a server response from the given byte buffer, which should contain /// exactly the bytes encoding the returned response. /// Intended to be used on the result of `new_framed` using `Stream::and_then`. pub fn decode_server_response(bytes: &mut BytesMut) -> io::Result { decode_frame("server response", bytes) } /// Encodes the given server response into a byte buffer, then returns it. /// Intended to be used on a sink of BytesMut objects, using `Sink::with`. pub fn encode_server_response(response: &ServerResponse) -> io::Result { encode_frame(response) } /// Decodes a server request from the given byte buffer, which should contain /// exactly the bytes encoding the returned response. /// Intended to be used on the result of `new_framed` using `Stream::and_then`. pub fn decode_server_request(bytes: &mut BytesMut) -> io::Result { decode_frame("server request", bytes) } /// Encodes the given server request into a byte buffer, then returns it. /// Intended to be used on a sink of BytesMut objects, using `Sink::with`. pub fn encode_server_request(request: &ServerRequest) -> io::Result { encode_frame(request) } /// Decodes a peer message from the given byte buffer, which should contain /// exactly the bytes encoding the returned response. /// Intended to be used on the result of `new_framed` using `Stream::and_then`. pub fn decode_peer_message(bytes: &mut BytesMut) -> io::Result { decode_frame("peer message", bytes) } /// Encodes the given peer message into a byte buffer, then returns it. /// Intended to be used on a sink of BytesMut objects, using `Sink::with`. pub fn encode_peer_message(message: &peer::Message) -> io::Result { encode_frame(message) }