1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! Defines error types and levels of punishment to use upon
//! encountering.

use rlp::DecoderError;
use network::NetworkError;

use std::fmt;

/// Levels of punishment.
///
/// Currently just encompasses two different kinds of disconnect and
/// no punishment, but this is where reputation systems might come into play.
// In ascending order
#[derive(Debug, PartialEq, Eq)]
pub enum Punishment {
	/// Perform no punishment.
	None,
	/// Disconnect the peer, but don't prevent them from reconnecting.
	Disconnect,
	/// Disconnect the peer and prevent them from reconnecting.
	Disable,
}

/// Kinds of errors which can be encountered in the course of LES.
#[derive(Debug)]
pub enum Error {
	/// An RLP decoding error.
	Rlp(DecoderError),
	/// A network error.
	Network(NetworkError),
	/// Out of buffer.
	BufferEmpty,
	/// Unrecognized packet code.
	UnrecognizedPacket(u8),
	/// Unexpected handshake.
	UnexpectedHandshake,
	/// Peer on wrong network (wrong NetworkId or genesis hash)
	WrongNetwork,
	/// Unknown peer.
	UnknownPeer,
	/// Unsolicited response.
	UnsolicitedResponse,
	/// Not a server.
	NotServer,
	/// Unsupported protocol version.
	UnsupportedProtocolVersion(u8),
	/// Bad protocol version.
	BadProtocolVersion,
	/// Peer is overburdened.
	Overburdened,
}

impl Error {
	/// What level of punishment does this error warrant?
	pub fn punishment(&self) -> Punishment {
		match *self {
			Error::Rlp(_) => Punishment::Disable,
			Error::Network(_) => Punishment::None,
			Error::BufferEmpty => Punishment::Disable,
			Error::UnrecognizedPacket(_) => Punishment::Disconnect,
			Error::UnexpectedHandshake => Punishment::Disconnect,
			Error::WrongNetwork => Punishment::Disable,
			Error::UnknownPeer => Punishment::Disconnect,
			Error::UnsolicitedResponse => Punishment::Disable,
			Error::NotServer => Punishment::Disable,
			Error::UnsupportedProtocolVersion(_) => Punishment::Disable,
			Error::BadProtocolVersion => Punishment::Disable,
			Error::Overburdened => Punishment::None,
		}
	}
}

impl From<DecoderError> for Error {
	fn from(err: DecoderError) -> Self {
		Error::Rlp(err)
	}
}

impl From<NetworkError> for Error {
	fn from(err: NetworkError) -> Self {
		Error::Network(err)
	}
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			Error::Rlp(ref err) => err.fmt(f),
			Error::Network(ref err) => err.fmt(f),
			Error::BufferEmpty => write!(f, "Out of buffer"),
			Error::UnrecognizedPacket(code) => write!(f, "Unrecognized packet: 0x{:x}", code),
			Error::UnexpectedHandshake => write!(f, "Unexpected handshake"),
			Error::WrongNetwork => write!(f, "Wrong network"),
			Error::UnknownPeer => write!(f, "Unknown peer"),
			Error::UnsolicitedResponse => write!(f, "Peer provided unsolicited data"),
			Error::NotServer => write!(f, "Peer not a server."),
			Error::UnsupportedProtocolVersion(pv) => write!(f, "Unsupported protocol version: {}", pv),
			Error::BadProtocolVersion => write!(f, "Bad protocol version in handshake"),
			Error::Overburdened => write!(f, "Peer overburdened"),
		}
	}
}