Browse Source

Remove DecodeError, use io::Error instead.

wip
Titouan Rigoudy 7 years ago
parent
commit
766d11d564
7 changed files with 244 additions and 180 deletions
  1. +147
    -112
      src/proto/codec.rs
  2. +1
    -1
      src/proto/mod.rs
  3. +16
    -11
      src/proto/peer/message.rs
  4. +24
    -19
      src/proto/server/request.rs
  5. +41
    -24
      src/proto/server/response.rs
  6. +8
    -9
      src/proto/transport.rs
  7. +7
    -4
      src/proto/user.rs

+ 147
- 112
src/proto/codec.rs View File

@ -8,84 +8,12 @@ use bytes::{Buf, BufMut, BytesMut, LittleEndian};
use encoding::{Encoding, EncoderTrap, DecoderTrap}; use encoding::{Encoding, EncoderTrap, DecoderTrap};
use encoding::all::WINDOWS_1252; use encoding::all::WINDOWS_1252;
// Constants
// ---------
/// Length of an encoded 32-bit integer in bytes. /// Length of an encoded 32-bit integer in bytes.
const U32_BYTE_LEN: usize = 4; const U32_BYTE_LEN: usize = 4;
/*==============*
* DECODE ERROR *
*==============*/
/// An error that arose when decoding a protocol message.
#[derive(Debug)]
pub enum DecodeError {
/// Attempted to decode a boolean, but the value was neither 0 nor 1.
/// The invalid value is enclosed.
InvalidBoolError(u8),
/// Attempted to decode an unsigned 16-bit integer, but the value did not
/// fit in 16 bits. The invalid value is enclosed.
InvalidU16Error(u32),
/// Attempted to decode the enclosed bytes as an Windows 1252 encoded
/// string, but one of the bytes was not a valid character encoding.
InvalidStringError(Vec<u8>),
/// Attempted to decode a user::Status, but the value was not a valid
/// representation of an enum variant. The invalid value is enclosed.
InvalidUserStatusError(u32),
/// Encountered the enclosed I/O error while decoding.
IOError(io::Error),
/// Attempted to decode a message with the enclosed code, unknown to this
/// library.
UnknownCodeError(u32),
}
impl fmt::Display for DecodeError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
DecodeError::InvalidBoolError(n) => write!(fmt, "InvalidBoolError: {}", n),
DecodeError::InvalidU16Error(n) => write!(fmt, "InvalidU16Error: {}", n),
DecodeError::InvalidStringError(ref bytes) => {
write!(fmt, "InvalidStringError: {:?}", bytes)
}
DecodeError::InvalidUserStatusError(n) => write!(fmt, "InvalidUserStatusError: {}", n),
DecodeError::IOError(ref err) => write!(fmt, "IOError: {}", err),
DecodeError::UnknownCodeError(code) => write!(fmt, "UnknownCodeError: {}", code),
}
}
}
impl error::Error for DecodeError {
fn description(&self) -> &str {
match *self {
DecodeError::InvalidBoolError(_) => "InvalidBoolError",
DecodeError::InvalidU16Error(_) => "InvalidU16Error",
DecodeError::InvalidStringError(_) => "InvalidStringError",
DecodeError::InvalidUserStatusError(_) => "InvalidUserStatusError",
DecodeError::IOError(_) => "IOError",
DecodeError::UnknownCodeError(code) => "UnknownCodeError",
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
DecodeError::InvalidBoolError(_) => None,
DecodeError::InvalidU16Error(_) => None,
DecodeError::InvalidStringError(_) => None,
DecodeError::InvalidUserStatusError(_) => None,
DecodeError::IOError(ref err) => Some(err),
DecodeError::UnknownCodeError(_) => None,
}
}
}
impl From<io::Error> for DecodeError {
fn from(err: io::Error) -> Self {
DecodeError::IOError(err)
}
}
fn unexpected_eof_error(value_type: &str) -> DecodeError {
DecodeError::from(io::Error::new(io::ErrorKind::UnexpectedEof, value_type))
}
/*===================================* /*===================================*
* BASIC TYPES ENCODING AND DECODING * * BASIC TYPES ENCODING AND DECODING *
*===================================*/ *===================================*/
@ -108,7 +36,7 @@ fn unexpected_eof_error(value_type: &str) -> DecodeError {
/// Only here to enable `ProtoDecoder::decode_vec`. /// Only here to enable `ProtoDecoder::decode_vec`.
pub trait ProtoDecode: Sized { pub trait ProtoDecode: Sized {
/// Attempts to decode an instance of `Self` using the given decoder. /// Attempts to decode an instance of `Self` using the given decoder.
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError>;
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self>;
} }
/// This trait is implemented by types that can be encoded into messages with /// This trait is implemented by types that can be encoded into messages with
@ -132,59 +60,93 @@ impl<'a> ProtoDecoder<'a> {
ProtoDecoder { inner: inner } ProtoDecoder { inner: inner }
} }
pub fn has_remaining(&self) -> bool {
self.inner.has_remaining()
// Private helper methods
// ----------------------
// Builds an EOF error encountered when reading a value of the given type.
fn unexpected_eof_error(type_name: &str) -> io::Error {
io::Error::new(
io::ErrorKind::UnexpectedEof,
format!("reading {}", type_name),
)
} }
pub fn decode_u32(&mut self) -> Result<u32, DecodeError> {
if self.inner.remaining() < U32_BYTE_LEN {
return Err(unexpected_eof_error("u32"));
// Builds an InvalidData error for the given value of the given type.
fn invalid_data_error<T: fmt::Debug>(type_name: &str, value: T) -> io::Error {
io::Error::new(
io::ErrorKind::InvalidData,
format!("invalid {}: {:?}", type_name, value),
)
}
// Asserts that the underlying buffer contains at least `n` more bytes from
// which to read a value of the given type.
// Returns Ok(()) if there are that many bytes, an error otherwise.
fn expect_remaining(&mut self, type_name: &str, n: usize) -> io::Result<()> {
if self.inner.remaining() < n {
Err(Self::unexpected_eof_error(type_name))
} else {
Ok(())
} }
}
// Decodes a u32 value as the first step in decoding a value of the given type.
fn decode_u32_generic(&mut self, type_name: &str) -> io::Result<u32> {
self.expect_remaining(type_name, U32_BYTE_LEN)?;
Ok(self.inner.get_u32::<LittleEndian>()) Ok(self.inner.get_u32::<LittleEndian>())
} }
pub fn decode_u16(&mut self) -> Result<u16, DecodeError> {
let n = self.decode_u32()?;
// Public methods
// --------------
pub fn has_remaining(&self) -> bool {
self.inner.has_remaining()
}
pub fn decode_u32(&mut self) -> io::Result<u32> {
self.decode_u32_generic("u32")
}
pub fn decode_u16(&mut self) -> io::Result<u16> {
let n = self.decode_u32_generic("u16")?;
if n > u16::MAX as u32 { if n > u16::MAX as u32 {
return Err(DecodeError::InvalidU16Error(n));
return Err(Self::invalid_data_error("u16", n));
} }
Ok(n as u16) Ok(n as u16)
} }
pub fn decode_bool(&mut self) -> Result<bool, DecodeError> {
if self.inner.remaining() < 1 {
return Err(unexpected_eof_error("bool"));
}
pub fn decode_bool(&mut self) -> io::Result<bool> {
self.expect_remaining("bool", 1)?;
match self.inner.get_u8() { match self.inner.get_u8() {
0 => Ok(false), 0 => Ok(false),
1 => Ok(true), 1 => Ok(true),
n => Err(DecodeError::InvalidBoolError(n)),
n => Err(Self::invalid_data_error("bool", n)),
} }
} }
pub fn decode_ipv4_addr(&mut self) -> Result<net::Ipv4Addr, DecodeError> {
let ip = self.decode_u32()?;
pub fn decode_ipv4_addr(&mut self) -> io::Result<net::Ipv4Addr> {
let ip = self.decode_u32_generic("ipv4 address")?;
Ok(net::Ipv4Addr::from(ip)) Ok(net::Ipv4Addr::from(ip))
} }
pub fn decode_string(&mut self) -> Result<String, DecodeError> {
let len = self.decode_u32()? as usize;
if self.inner.remaining() < len {
return Err(unexpected_eof_error("string"));
}
pub fn decode_string(&mut self) -> io::Result<String> {
let len = self.decode_u32_generic("string length")? as usize;
self.expect_remaining("string", len)?;
let result = { let result = {
let bytes = &self.inner.bytes()[..len]; let bytes = &self.inner.bytes()[..len];
WINDOWS_1252.decode(bytes, DecoderTrap::Strict).map_err( WINDOWS_1252.decode(bytes, DecoderTrap::Strict).map_err(
|_| {
DecodeError::InvalidStringError(bytes.to_vec())
|err| {
Self::invalid_data_error("string", (err, bytes))
}, },
) )
}; };
self.inner.advance(len); self.inner.advance(len);
result result
} }
pub fn decode_pair<T, U>(&mut self) -> Result<(T, U), DecodeError>
pub fn decode_pair<T, U>(&mut self) -> io::Result<(T, U)>
where where
T: ProtoDecode, T: ProtoDecode,
U: ProtoDecode, U: ProtoDecode,
@ -194,8 +156,8 @@ impl<'a> ProtoDecoder<'a> {
Ok((first, second)) Ok((first, second))
} }
pub fn decode_vec<T: ProtoDecode>(&mut self) -> Result<Vec<T>, DecodeError> {
let len = self.decode_u32()? as usize;
pub fn decode_vec<T: ProtoDecode>(&mut self) -> io::Result<Vec<T>> {
let len = self.decode_u32_generic("vector length")? as usize;
let mut vec = Vec::with_capacity(len); let mut vec = Vec::with_capacity(len);
for _ in 0..len { for _ in 0..len {
let val = T::decode(self)?; let val = T::decode(self)?;
@ -279,7 +241,7 @@ impl<'a> ProtoEncoder<'a> {
} }
impl ProtoDecode for u32 { impl ProtoDecode for u32 {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
decoder.decode_u32() decoder.decode_u32()
} }
} }
@ -291,7 +253,7 @@ impl ProtoEncode for u32 {
} }
impl ProtoDecode for bool { impl ProtoDecode for bool {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
decoder.decode_bool() decoder.decode_bool()
} }
} }
@ -303,7 +265,7 @@ impl ProtoEncode for bool {
} }
impl ProtoDecode for u16 { impl ProtoDecode for u16 {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
decoder.decode_u16() decoder.decode_u16()
} }
} }
@ -315,7 +277,7 @@ impl ProtoEncode for u16 {
} }
impl ProtoDecode for net::Ipv4Addr { impl ProtoDecode for net::Ipv4Addr {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
decoder.decode_ipv4_addr() decoder.decode_ipv4_addr()
} }
} }
@ -327,7 +289,7 @@ impl ProtoEncode for net::Ipv4Addr {
} }
impl ProtoDecode for String { impl ProtoDecode for String {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
decoder.decode_string() decoder.decode_string()
} }
} }
@ -365,7 +327,7 @@ impl<'a> ProtoEncode for &'a String {
} }
impl<T: ProtoDecode, U: ProtoDecode> ProtoDecode for (T, U) { impl<T: ProtoDecode, U: ProtoDecode> ProtoDecode for (T, U) {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
decoder.decode_pair::<T, U>() decoder.decode_pair::<T, U>()
} }
} }
@ -377,7 +339,7 @@ impl<T: ProtoEncode, U: ProtoEncode> ProtoEncode for (T, U) {
} }
impl<T: ProtoDecode> ProtoDecode for Vec<T> { impl<T: ProtoDecode> ProtoDecode for Vec<T> {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
decoder.decode_vec::<T>() decoder.decode_vec::<T>()
} }
} }
@ -414,6 +376,28 @@ pub mod tests {
assert_eq!(output, input); assert_eq!(output, input);
} }
pub fn expect_io_error<T>(result: io::Result<T>, kind: io::ErrorKind, message: &str)
where
T: fmt::Debug + Send + 'static,
{
match result {
Err(e) => {
assert_eq!(e.kind(), kind);
let ok = match e.get_ref() {
Some(e) => {
assert_eq!(e.description(), message);
true
}
None => false,
};
if !ok {
panic!(e)
}
}
Ok(message) => panic!(message),
}
}
// Helper for succinctness in tests below. // Helper for succinctness in tests below.
fn new_cursor(vec: Vec<u8>) -> io::Cursor<BytesMut> { fn new_cursor(vec: Vec<u8>) -> io::Cursor<BytesMut> {
io::Cursor::new(BytesMut::from(vec)) io::Cursor::new(BytesMut::from(vec))
@ -431,6 +415,36 @@ pub mod tests {
(u32::MAX, [255, 255, 255, 255]), (u32::MAX, [255, 255, 255, 255]),
]; ];
#[test]
fn expect_io_error_success() {
let kind = io::ErrorKind::InvalidInput;
let message = "some message";
let result: io::Result<()> = Err(io::Error::new(kind, message));
expect_io_error(result, kind, message);
}
#[test]
#[should_panic]
fn expect_io_error_not_err() {
expect_io_error(Ok(()), io::ErrorKind::InvalidInput, "some message");
}
#[test]
#[should_panic]
fn expect_io_error_wrong_kind() {
let result: io::Result<()> =
Err(io::Error::new(io::ErrorKind::UnexpectedEof, "some message"));
expect_io_error(result, io::ErrorKind::InvalidInput, "some message");
}
#[test]
#[should_panic]
fn expect_io_error_wrong_message() {
let result: io::Result<()> =
Err(io::Error::new(io::ErrorKind::InvalidInput, "some message"));
expect_io_error(result, io::ErrorKind::InvalidInput, "other message");
}
#[test] #[test]
fn encode_u32() { fn encode_u32() {
for &(val, ref encoded_bytes) in &U32_ENCODINGS { for &(val, ref encoded_bytes) in &U32_ENCODINGS {
@ -460,6 +474,13 @@ pub mod tests {
} }
} }
#[test]
fn decode_u32_unexpected_eof() {
let mut cursor = new_cursor(vec![13]);
let result = ProtoDecoder::new(&mut cursor).decode_u32();
expect_io_error(result, io::ErrorKind::UnexpectedEof, "reading u32");
}
#[test] #[test]
fn encode_bool() { fn encode_bool() {
let mut bytes = BytesMut::from(vec![13]); let mut bytes = BytesMut::from(vec![13]);
@ -485,10 +506,17 @@ pub mod tests {
} }
#[test] #[test]
#[should_panic]
fn decode_bool_invalid() { fn decode_bool_invalid() {
let mut cursor = new_cursor(vec![42]); let mut cursor = new_cursor(vec![42]);
ProtoDecoder::new(&mut cursor).decode_bool().unwrap();
let result = ProtoDecoder::new(&mut cursor).decode_bool();
expect_io_error(result, io::ErrorKind::InvalidData, "invalid bool: 42");
}
#[test]
fn decode_bool_unexpected_eof() {
let mut cursor = new_cursor(vec![]);
let result = ProtoDecoder::new(&mut cursor).decode_bool();
expect_io_error(result, io::ErrorKind::UnexpectedEof, "reading bool");
} }
#[test] #[test]
@ -530,10 +558,17 @@ pub mod tests {
} }
#[test] #[test]
#[should_panic]
fn decode_u16_invalid() { fn decode_u16_invalid() {
let mut cursor = new_cursor(vec![0, 0, 1, 0]); let mut cursor = new_cursor(vec![0, 0, 1, 0]);
ProtoDecoder::new(&mut cursor).decode_u16().unwrap();
let result = ProtoDecoder::new(&mut cursor).decode_u16();
expect_io_error(result, io::ErrorKind::InvalidData, "invalid u16: 65536");
}
#[test]
fn decode_u16_unexpected_eof() {
let mut cursor = new_cursor(vec![]);
let result = ProtoDecoder::new(&mut cursor).decode_u16();
expect_io_error(result, io::ErrorKind::UnexpectedEof, "reading u16");
} }
#[test] #[test]


+ 1
- 1
src/proto/mod.rs View File

@ -8,7 +8,7 @@ mod stream;
mod transport; mod transport;
mod user; mod user;
pub use self::codec::{DecodeError, ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder};
pub use self::codec::{ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder};
pub use self::handler::*; pub use self::handler::*;
pub use self::packet::*; pub use self::packet::*;
pub use self::stream::*; pub use self::stream::*;


+ 16
- 11
src/proto/peer/message.rs View File

@ -1,7 +1,7 @@
use std::io; use std::io;
use proto::{DecodeError, MutPacket, Packet, PacketReadError, ProtoDecode, ProtoDecoder,
ProtoEncode, ProtoEncoder, ReadFromPacket, WriteToPacket};
use proto::{MutPacket, Packet, PacketReadError, ProtoDecode, ProtoDecoder, ProtoEncode,
ProtoEncoder, ReadFromPacket, WriteToPacket};
use proto::peer::constants::*; use proto::peer::constants::*;
/*=========* /*=========*
@ -41,7 +41,7 @@ impl ReadFromPacket for Message {
} }
impl ProtoDecode for Message { impl ProtoDecode for Message {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let code = decoder.decode_u32()?; let code = decoder.decode_u32()?;
let message = match code { let message = match code {
CODE_PIERCE_FIREWALL => { CODE_PIERCE_FIREWALL => {
@ -53,7 +53,10 @@ impl ProtoDecode for Message {
Message::PeerInit(peer_init) Message::PeerInit(peer_init)
} }
_ => { _ => {
return Err(DecodeError::UnknownCodeError(code));
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("unknown peer message code: {}", code),
))
} }
}; };
Ok(message) Ok(message)
@ -135,7 +138,7 @@ impl ProtoEncode for PeerInit {
} }
impl ProtoDecode for PeerInit { impl ProtoDecode for PeerInit {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let user_name = decoder.decode_string()?; let user_name = decoder.decode_string()?;
let connection_type = decoder.decode_string()?; let connection_type = decoder.decode_string()?;
let token = decoder.decode_u32()?; let token = decoder.decode_u32()?;
@ -154,8 +157,8 @@ mod tests {
use bytes::BytesMut; use bytes::BytesMut;
use proto::{DecodeError, ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder};
use proto::codec::tests::roundtrip;
use proto::{ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder};
use proto::codec::tests::{expect_io_error, roundtrip};
use super::*; use super::*;
@ -165,10 +168,12 @@ mod tests {
ProtoEncoder::new(&mut bytes).encode_u32(1337).unwrap(); ProtoEncoder::new(&mut bytes).encode_u32(1337).unwrap();
let mut cursor = io::Cursor::new(bytes); let mut cursor = io::Cursor::new(bytes);
match Message::decode(&mut ProtoDecoder::new(&mut cursor)) {
Err(DecodeError::UnknownCodeError(1337)) => {}
result => panic!(result),
}
let result = Message::decode(&mut ProtoDecoder::new(&mut cursor));
expect_io_error(
result,
io::ErrorKind::InvalidData,
"unknown peer message code: 1337",
);
} }
#[test] #[test]


+ 24
- 19
src/proto/server/request.rs View File

@ -3,7 +3,7 @@ use std::io;
use crypto::md5::Md5; use crypto::md5::Md5;
use crypto::digest::Digest; use crypto::digest::Digest;
use proto::{DecodeError, ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder};
use proto::{ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder};
use proto::packet::{MutPacket, WriteToPacket}; use proto::packet::{MutPacket, WriteToPacket};
use proto::server::constants::*; use proto::server::constants::*;
@ -149,7 +149,7 @@ impl ProtoEncode for ServerRequest {
} }
impl ProtoDecode for ServerRequest { impl ProtoDecode for ServerRequest {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let code = decoder.decode_u32()?; let code = decoder.decode_u32()?;
let request = match code { let request = match code {
CODE_CANNOT_CONNECT => { CODE_CANNOT_CONNECT => {
@ -194,7 +194,10 @@ impl ProtoDecode for ServerRequest {
ServerRequest::UserStatusRequest(request) ServerRequest::UserStatusRequest(request)
} }
_ => { _ => {
return Err(DecodeError::UnknownCodeError(code));
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("unknown server request code: {}", code),
))
} }
}; };
Ok(request) Ok(request)
@ -227,7 +230,7 @@ impl ProtoEncode for CannotConnectRequest {
} }
impl ProtoDecode for CannotConnectRequest { impl ProtoDecode for CannotConnectRequest {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let token = decoder.decode_u32()?; let token = decoder.decode_u32()?;
let user_name = decoder.decode_string()?; let user_name = decoder.decode_string()?;
Ok(Self { token, user_name }) Ok(Self { token, user_name })
@ -263,7 +266,7 @@ impl ProtoEncode for ConnectToPeerRequest {
} }
impl ProtoDecode for ConnectToPeerRequest { impl ProtoDecode for ConnectToPeerRequest {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let token = decoder.decode_u32()?; let token = decoder.decode_u32()?;
let user_name = decoder.decode_string()?; let user_name = decoder.decode_string()?;
let connection_type = decoder.decode_string()?; let connection_type = decoder.decode_string()?;
@ -301,7 +304,7 @@ impl ProtoEncode for FileSearchRequest {
} }
impl ProtoDecode for FileSearchRequest { impl ProtoDecode for FileSearchRequest {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let ticket = decoder.decode_u32()?; let ticket = decoder.decode_u32()?;
let query = decoder.decode_string()?; let query = decoder.decode_string()?;
Ok(Self { ticket, query }) Ok(Self { ticket, query })
@ -373,7 +376,7 @@ impl ProtoEncode for LoginRequest {
} }
impl ProtoDecode for LoginRequest { impl ProtoDecode for LoginRequest {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let username = decoder.decode_string()?; let username = decoder.decode_string()?;
let password = decoder.decode_string()?; let password = decoder.decode_string()?;
let major = decoder.decode_u32()?; let major = decoder.decode_u32()?;
@ -412,7 +415,7 @@ impl ProtoEncode for PeerAddressRequest {
} }
impl ProtoDecode for PeerAddressRequest { impl ProtoDecode for PeerAddressRequest {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let username = decoder.decode_string()?; let username = decoder.decode_string()?;
Ok(Self { username: username }) Ok(Self { username: username })
} }
@ -441,7 +444,7 @@ impl ProtoEncode for RoomJoinRequest {
} }
impl ProtoDecode for RoomJoinRequest { impl ProtoDecode for RoomJoinRequest {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let room_name = decoder.decode_string()?; let room_name = decoder.decode_string()?;
Ok(Self { room_name: room_name }) Ok(Self { room_name: room_name })
} }
@ -470,7 +473,7 @@ impl ProtoEncode for RoomLeaveRequest {
} }
impl ProtoDecode for RoomLeaveRequest { impl ProtoDecode for RoomLeaveRequest {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let room_name = decoder.decode_string()?; let room_name = decoder.decode_string()?;
Ok(Self { room_name: room_name }) Ok(Self { room_name: room_name })
} }
@ -502,7 +505,7 @@ impl ProtoEncode for RoomMessageRequest {
} }
impl ProtoDecode for RoomMessageRequest { impl ProtoDecode for RoomMessageRequest {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let room_name = decoder.decode_string()?; let room_name = decoder.decode_string()?;
let message = decoder.decode_string()?; let message = decoder.decode_string()?;
Ok(Self { room_name, message }) Ok(Self { room_name, message })
@ -532,7 +535,7 @@ impl ProtoEncode for SetListenPortRequest {
} }
impl ProtoDecode for SetListenPortRequest { impl ProtoDecode for SetListenPortRequest {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let port = decoder.decode_u16()?; let port = decoder.decode_u16()?;
Ok(Self { port: port }) Ok(Self { port: port })
} }
@ -561,7 +564,7 @@ impl ProtoEncode for UserStatusRequest {
} }
impl ProtoDecode for UserStatusRequest { impl ProtoDecode for UserStatusRequest {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let user_name = decoder.decode_string()?; let user_name = decoder.decode_string()?;
Ok(Self { user_name: user_name }) Ok(Self { user_name: user_name })
} }
@ -578,8 +581,8 @@ mod tests {
use bytes::BytesMut; use bytes::BytesMut;
use proto::{DecodeError, ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder};
use proto::codec::tests::roundtrip;
use proto::{ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder};
use proto::codec::tests::{expect_io_error, roundtrip};
use super::*; use super::*;
@ -589,10 +592,12 @@ mod tests {
ProtoEncoder::new(&mut bytes).encode_u32(1337).unwrap(); ProtoEncoder::new(&mut bytes).encode_u32(1337).unwrap();
let mut cursor = io::Cursor::new(bytes); let mut cursor = io::Cursor::new(bytes);
match ServerRequest::decode(&mut ProtoDecoder::new(&mut cursor)) {
Err(DecodeError::UnknownCodeError(1337)) => {}
result => panic!(result),
}
let result = ServerRequest::decode(&mut ProtoDecoder::new(&mut cursor));
expect_io_error(
result,
io::ErrorKind::InvalidData,
"unknown server request code: 1337",
);
} }
#[test] #[test]


+ 41
- 24
src/proto/server/response.rs View File

@ -2,7 +2,7 @@ use std::io;
use std::net; use std::net;
use proto::server::constants::*; use proto::server::constants::*;
use proto::{DecodeError, ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder, User, UserStatus};
use proto::{ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder, User, UserStatus};
use proto::packet::{Packet, PacketReadError, ReadFromPacket}; use proto::packet::{Packet, PacketReadError, ReadFromPacket};
/*=================* /*=================*
@ -178,7 +178,7 @@ impl ProtoEncode for ServerResponse {
} }
impl ProtoDecode for ServerResponse { impl ProtoDecode for ServerResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let code = decoder.decode_u32()?; let code = decoder.decode_u32()?;
let response = match code { let response = match code {
CODE_CONNECT_TO_PEER => { CODE_CONNECT_TO_PEER => {
@ -250,7 +250,10 @@ impl ProtoDecode for ServerResponse {
ServerResponse::WishlistIntervalResponse(response) ServerResponse::WishlistIntervalResponse(response)
} }
_ => { _ => {
return Err(DecodeError::UnknownCodeError(code));
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("unknown server response code: {}", code),
));
} }
}; };
Ok(response) Ok(response)
@ -303,7 +306,7 @@ impl ProtoEncode for ConnectToPeerResponse {
} }
impl ProtoDecode for ConnectToPeerResponse { impl ProtoDecode for ConnectToPeerResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let user_name = decoder.decode_string()?; let user_name = decoder.decode_string()?;
let connection_type = decoder.decode_string()?; let connection_type = decoder.decode_string()?;
let ip = decoder.decode_ipv4_addr()?; let ip = decoder.decode_ipv4_addr()?;
@ -356,7 +359,7 @@ impl ProtoEncode for FileSearchResponse {
} }
impl ProtoDecode for FileSearchResponse { impl ProtoDecode for FileSearchResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let user_name = decoder.decode_string()?; let user_name = decoder.decode_string()?;
let ticket = decoder.decode_u32()?; let ticket = decoder.decode_u32()?;
let query = decoder.decode_string()?; let query = decoder.decode_string()?;
@ -430,7 +433,7 @@ impl ProtoEncode for LoginResponse {
} }
impl ProtoDecode for LoginResponse { impl ProtoDecode for LoginResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let ok = decoder.decode_bool()?; let ok = decoder.decode_bool()?;
if !ok { if !ok {
let reason = decoder.decode_string()?; let reason = decoder.decode_string()?;
@ -476,7 +479,7 @@ impl ProtoEncode for ParentMinSpeedResponse {
} }
impl ProtoDecode for ParentMinSpeedResponse { impl ProtoDecode for ParentMinSpeedResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let value = decoder.decode_u32()?; let value = decoder.decode_u32()?;
Ok(Self { value }) Ok(Self { value })
} }
@ -505,7 +508,7 @@ impl ProtoEncode for ParentSpeedRatioResponse {
} }
impl ProtoDecode for ParentSpeedRatioResponse { impl ProtoDecode for ParentSpeedRatioResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let value = decoder.decode_u32()?; let value = decoder.decode_u32()?;
Ok(Self { value }) Ok(Self { value })
} }
@ -541,7 +544,7 @@ impl ProtoEncode for PeerAddressResponse {
} }
impl ProtoDecode for PeerAddressResponse { impl ProtoDecode for PeerAddressResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let username = decoder.decode_string()?; let username = decoder.decode_string()?;
let ip = decoder.decode_ipv4_addr()?; let ip = decoder.decode_ipv4_addr()?;
let port = decoder.decode_u16()?; let port = decoder.decode_u16()?;
@ -572,7 +575,7 @@ impl ProtoEncode for PrivilegedUsersResponse {
} }
impl ProtoDecode for PrivilegedUsersResponse { impl ProtoDecode for PrivilegedUsersResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let users = decoder.decode_vec::<String>()?; let users = decoder.decode_vec::<String>()?;
Ok(Self { users }) Ok(Self { users })
} }
@ -738,7 +741,7 @@ impl ProtoEncode for UserInfo {
} }
impl ProtoDecode for UserInfo { impl ProtoDecode for UserInfo {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let average_speed = decoder.decode_u32()?; let average_speed = decoder.decode_u32()?;
let num_downloads = decoder.decode_u32()?; let num_downloads = decoder.decode_u32()?;
let unknown = decoder.decode_u32()?; let unknown = decoder.decode_u32()?;
@ -814,7 +817,7 @@ fn build_users(
} }
impl ProtoDecode for RoomJoinResponse { impl ProtoDecode for RoomJoinResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let room_name = decoder.decode_string()?; let room_name = decoder.decode_string()?;
let user_names = decoder.decode_vec::<String>()?; let user_names = decoder.decode_vec::<String>()?;
let user_statuses = decoder.decode_vec::<UserStatus>()?; let user_statuses = decoder.decode_vec::<UserStatus>()?;
@ -868,7 +871,7 @@ impl ProtoEncode for RoomLeaveResponse {
} }
impl ProtoDecode for RoomLeaveResponse { impl ProtoDecode for RoomLeaveResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let room_name = decoder.decode_string()?; let room_name = decoder.decode_string()?;
Ok(Self { room_name }) Ok(Self { room_name })
} }
@ -958,7 +961,7 @@ impl RoomListResponse {
rooms rooms
} }
fn decode_rooms(decoder: &mut ProtoDecoder) -> Result<Vec<(String, u32)>, DecodeError> {
fn decode_rooms(decoder: &mut ProtoDecoder) -> io::Result<Vec<(String, u32)>> {
let room_names = decoder.decode_vec::<String>()?; let room_names = decoder.decode_vec::<String>()?;
let user_counts = decoder.decode_vec::<u32>()?; let user_counts = decoder.decode_vec::<u32>()?;
Ok(Self::build_rooms(room_names, user_counts)) Ok(Self::build_rooms(room_names, user_counts))
@ -988,7 +991,7 @@ impl ProtoEncode for RoomListResponse {
} }
impl ProtoDecode for RoomListResponse { impl ProtoDecode for RoomListResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let rooms = Self::decode_rooms(decoder)?; let rooms = Self::decode_rooms(decoder)?;
let owned_private_rooms = Self::decode_rooms(decoder)?; let owned_private_rooms = Self::decode_rooms(decoder)?;
let other_private_rooms = Self::decode_rooms(decoder)?; let other_private_rooms = Self::decode_rooms(decoder)?;
@ -1035,7 +1038,7 @@ impl ProtoEncode for RoomMessageResponse {
} }
impl ProtoDecode for RoomMessageResponse { impl ProtoDecode for RoomMessageResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let room_name = decoder.decode_string()?; let room_name = decoder.decode_string()?;
let user_name = decoder.decode_string()?; let user_name = decoder.decode_string()?;
let message = decoder.decode_string()?; let message = decoder.decode_string()?;
@ -1081,7 +1084,7 @@ impl ProtoEncode for RoomTickersResponse {
} }
impl ProtoDecode for RoomTickersResponse { impl ProtoDecode for RoomTickersResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let room_name = decoder.decode_string()?; let room_name = decoder.decode_string()?;
let tickers = decoder.decode_vec::<(String, String)>()?; let tickers = decoder.decode_vec::<(String, String)>()?;
Ok(Self { room_name, tickers }) Ok(Self { room_name, tickers })
@ -1143,7 +1146,7 @@ impl ProtoEncode for RoomUserJoinedResponse {
} }
impl ProtoDecode for RoomUserJoinedResponse { impl ProtoDecode for RoomUserJoinedResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let room_name = decoder.decode_string()?; let room_name = decoder.decode_string()?;
let user_name = decoder.decode_string()?; let user_name = decoder.decode_string()?;
let status = UserStatus::decode(decoder)?; let status = UserStatus::decode(decoder)?;
@ -1186,7 +1189,7 @@ impl ProtoEncode for RoomUserLeftResponse {
} }
impl ProtoDecode for RoomUserLeftResponse { impl ProtoDecode for RoomUserLeftResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let room_name = decoder.decode_string()?; let room_name = decoder.decode_string()?;
let user_name = decoder.decode_string()?; let user_name = decoder.decode_string()?;
Ok(Self { Ok(Self {
@ -1237,7 +1240,7 @@ impl ProtoEncode for UserInfoResponse {
} }
impl ProtoDecode for UserInfoResponse { impl ProtoDecode for UserInfoResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let user_name = decoder.decode_string()?; let user_name = decoder.decode_string()?;
let average_speed = decoder.decode_u32()?; let average_speed = decoder.decode_u32()?;
let num_downloads = decoder.decode_u32()?; let num_downloads = decoder.decode_u32()?;
@ -1286,7 +1289,7 @@ impl ProtoEncode for UserStatusResponse {
} }
impl ProtoDecode for UserStatusResponse { impl ProtoDecode for UserStatusResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let user_name = decoder.decode_string()?; let user_name = decoder.decode_string()?;
let status = UserStatus::decode(decoder)?; let status = UserStatus::decode(decoder)?;
let is_privileged = decoder.decode_bool()?; let is_privileged = decoder.decode_bool()?;
@ -1321,7 +1324,7 @@ impl ProtoEncode for WishlistIntervalResponse {
} }
impl ProtoDecode for WishlistIntervalResponse { impl ProtoDecode for WishlistIntervalResponse {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let seconds = decoder.decode_u32()?; let seconds = decoder.decode_u32()?;
Ok(Self { seconds }) Ok(Self { seconds })
} }
@ -1338,11 +1341,25 @@ mod tests {
use bytes::BytesMut; use bytes::BytesMut;
use proto::{DecodeError, ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder};
use proto::codec::tests::roundtrip;
use proto::{ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder};
use proto::codec::tests::{expect_io_error, roundtrip};
use super::*; use super::*;
#[test]
fn invalid_code() {
let mut bytes = BytesMut::new();
ProtoEncoder::new(&mut bytes).encode_u32(1337).unwrap();
let mut cursor = io::Cursor::new(bytes);
let result = ServerResponse::decode(&mut ProtoDecoder::new(&mut cursor));
expect_io_error(
result,
io::ErrorKind::InvalidData,
"unknown server response code: 1337",
);
}
#[test] #[test]
fn roundtrip_connect_to_peer() { fn roundtrip_connect_to_peer() {
roundtrip(ServerResponse::ConnectToPeerResponse( roundtrip(ServerResponse::ConnectToPeerResponse(


+ 8
- 9
src/proto/transport.rs View File

@ -6,8 +6,7 @@ use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::length_delimited; use tokio_io::codec::length_delimited;
use proto::peer; use proto::peer;
use proto::{DecodeError, ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder, ServerResponse,
ServerRequest};
use proto::{ProtoDecode, ProtoDecoder, ProtoEncode, ProtoEncoder, ServerResponse, ServerRequest};
/* ------- * /* ------- *
* Helpers * * Helpers *
@ -20,7 +19,7 @@ fn new_framed<T: AsyncRead + AsyncWrite>(io: T) -> length_delimited::Framed<T, B
.new_framed(io) .new_framed(io)
} }
fn decode_server_response(bytes: &mut BytesMut) -> Result<ServerResponse, DecodeError> {
fn decode_server_response(bytes: &mut BytesMut) -> io::Result<ServerResponse> {
unimplemented!(); unimplemented!();
} }
@ -28,7 +27,7 @@ fn encode_server_request(request: &ServerRequest) -> Result<BytesMut, io::Error>
unimplemented!(); unimplemented!();
} }
fn decode_peer_message(bytes: BytesMut) -> Result<peer::Message, DecodeError> {
fn decode_peer_message(bytes: BytesMut) -> io::Result<peer::Message> {
let mut cursor = io::Cursor::new(bytes); let mut cursor = io::Cursor::new(bytes);
let message = peer::Message::decode(&mut ProtoDecoder::new(&mut cursor))?; let message = peer::Message::decode(&mut ProtoDecoder::new(&mut cursor))?;
if cursor.has_remaining() { if cursor.has_remaining() {
@ -56,14 +55,14 @@ pub struct ServerTransport<T> {
} }
impl<T: AsyncRead + AsyncWrite> ServerTransport<T> { impl<T: AsyncRead + AsyncWrite> ServerTransport<T> {
fn new(io: T) -> ServerTransport<T> {
pub fn new(io: T) -> ServerTransport<T> {
ServerTransport { framed: new_framed(io) } ServerTransport { framed: new_framed(io) }
} }
} }
impl<T: AsyncRead> Stream for ServerTransport<T> { impl<T: AsyncRead> Stream for ServerTransport<T> {
type Item = ServerResponse; type Item = ServerResponse;
type Error = DecodeError;
type Error = io::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
match self.framed.poll() { match self.framed.poll() {
@ -73,7 +72,7 @@ impl<T: AsyncRead> Stream for ServerTransport<T> {
} }
Ok(Async::Ready(None)) => Ok(Async::Ready(None)), Ok(Async::Ready(None)) => Ok(Async::Ready(None)),
Ok(Async::NotReady) => Ok(Async::NotReady), Ok(Async::NotReady) => Ok(Async::NotReady),
Err(err) => Err(DecodeError::from(err)),
Err(err) => Err(err),
} }
} }
} }
@ -112,7 +111,7 @@ impl<T: AsyncRead + AsyncWrite> PeerTransport<T> {
impl<T: AsyncRead> Stream for PeerTransport<T> { impl<T: AsyncRead> Stream for PeerTransport<T> {
type Item = peer::Message; type Item = peer::Message;
type Error = DecodeError;
type Error = io::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
match self.framed.poll() { match self.framed.poll() {
@ -122,7 +121,7 @@ impl<T: AsyncRead> Stream for PeerTransport<T> {
} }
Ok(Async::Ready(None)) => Ok(Async::Ready(None)), Ok(Async::Ready(None)) => Ok(Async::Ready(None)),
Ok(Async::NotReady) => Ok(Async::NotReady), Ok(Async::NotReady) => Ok(Async::NotReady),
Err(err) => Err(DecodeError::from(err)),
Err(err) => Err(err),
} }
} }
} }


+ 7
- 4
src/proto/user.rs View File

@ -1,7 +1,7 @@
use std::io; use std::io;
use proto::{DecodeError, MutPacket, Packet, PacketReadError, ProtoDecode, ProtoDecoder,
ProtoEncode, ProtoEncoder, ReadFromPacket, WriteToPacket};
use proto::{MutPacket, Packet, PacketReadError, ProtoDecode, ProtoDecoder, ProtoEncode,
ProtoEncoder, ReadFromPacket, WriteToPacket};
const STATUS_OFFLINE: u32 = 1; const STATUS_OFFLINE: u32 = 1;
const STATUS_AWAY: u32 = 2; const STATUS_AWAY: u32 = 2;
@ -54,13 +54,16 @@ impl ProtoEncode for UserStatus {
} }
impl ProtoDecode for UserStatus { impl ProtoDecode for UserStatus {
fn decode(decoder: &mut ProtoDecoder) -> Result<Self, DecodeError> {
fn decode(decoder: &mut ProtoDecoder) -> io::Result<Self> {
let value = decoder.decode_u32()?; let value = decoder.decode_u32()?;
match value { match value {
STATUS_OFFLINE => Ok(UserStatus::Offline), STATUS_OFFLINE => Ok(UserStatus::Offline),
STATUS_AWAY => Ok(UserStatus::Away), STATUS_AWAY => Ok(UserStatus::Away),
STATUS_ONLINE => Ok(UserStatus::Online), STATUS_ONLINE => Ok(UserStatus::Online),
_ => Err(DecodeError::InvalidUserStatusError(value)),
_ => Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("invalid user status: {}", value),
)),
} }
} }
} }


Loading…
Cancel
Save