2019-01-07 11:33:07 +01:00
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
2016-02-05 13:40:41 +01:00
2019-01-07 11:33:07 +01:00
// Parity Ethereum is free software: you can redistribute it and/or modify
2016-02-05 13:40:41 +01:00
// 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.
2019-01-07 11:33:07 +01:00
// Parity Ethereum is distributed in the hope that it will be useful,
2016-02-05 13:40:41 +01:00
// 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
2019-01-07 11:33:07 +01:00
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
2016-02-05 13:40:41 +01:00
2019-06-17 08:44:59 +02:00
use std ::{ error , io , net , fmt } ;
2018-06-01 13:37:43 +02:00
use libc ::{ ENFILE , EMFILE } ;
2016-01-15 16:36:08 +01:00
use io ::IoError ;
2017-11-13 14:37:08 +01:00
use { rlp , ethkey , crypto , snappy } ;
2016-01-15 16:36:08 +01:00
2016-02-17 14:07:26 +01:00
#[ derive(Debug, Copy, Clone, PartialEq, Eq) ]
2016-01-15 16:36:08 +01:00
pub enum DisconnectReason
{
DisconnectRequested ,
2016-02-17 14:07:26 +01:00
TCPError ,
BadProtocol ,
2016-01-15 16:36:08 +01:00
UselessPeer ,
2016-02-17 14:07:26 +01:00
TooManyPeers ,
DuplicatePeer ,
IncompatibleProtocol ,
NullIdentity ,
ClientQuit ,
UnexpectedIdentity ,
LocalIdentity ,
2016-02-02 20:58:12 +01:00
PingTimeout ,
2016-02-17 14:07:26 +01:00
Unknown ,
}
impl DisconnectReason {
pub fn from_u8 ( n : u8 ) -> DisconnectReason {
match n {
0 = > DisconnectReason ::DisconnectRequested ,
1 = > DisconnectReason ::TCPError ,
2 = > DisconnectReason ::BadProtocol ,
3 = > DisconnectReason ::UselessPeer ,
4 = > DisconnectReason ::TooManyPeers ,
5 = > DisconnectReason ::DuplicatePeer ,
6 = > DisconnectReason ::IncompatibleProtocol ,
7 = > DisconnectReason ::NullIdentity ,
8 = > DisconnectReason ::ClientQuit ,
9 = > DisconnectReason ::UnexpectedIdentity ,
10 = > DisconnectReason ::LocalIdentity ,
11 = > DisconnectReason ::PingTimeout ,
_ = > DisconnectReason ::Unknown ,
}
}
2016-01-15 16:36:08 +01:00
}
2016-05-21 00:12:51 +02:00
impl fmt ::Display for DisconnectReason {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
use self ::DisconnectReason ::* ;
let msg = match * self {
DisconnectRequested = > " disconnect requested " ,
TCPError = > " TCP error " ,
BadProtocol = > " bad protocol " ,
UselessPeer = > " useless peer " ,
TooManyPeers = > " too many peers " ,
DuplicatePeer = > " duplicate peer " ,
IncompatibleProtocol = > " incompatible protocol " ,
NullIdentity = > " null identity " ,
ClientQuit = > " client quit " ,
UnexpectedIdentity = > " unexpected identity " ,
LocalIdentity = > " local identity " ,
PingTimeout = > " ping timeout " ,
Unknown = > " unknown " ,
} ;
f . write_str ( msg )
}
}
2019-06-17 08:44:59 +02:00
/// Queue error
#[ derive(Debug, derive_more::Display) ]
pub enum Error {
/// Socket IO error.
SocketIo ( IoError ) ,
/// Decompression error.
Decompression ( snappy ::InvalidInput ) ,
/// Rlp decoder error.
Rlp ( rlp ::DecoderError ) ,
/// Error concerning the network address parsing subsystem.
#[ display(fmt = " Failed to parse network address " ) ]
AddressParse ,
/// Error concerning the network address resolution subsystem.
#[ display(fmt = " Failed to resolve network address {} " , _0) ]
AddressResolve ( AddressResolveError ) ,
/// Authentication failure
#[ display(fmt = " Authentication failure " ) ]
Auth ,
/// Unrecognised protocol
#[ display(fmt = " Bad protocol " ) ]
BadProtocol ,
/// Expired message
#[ display(fmt = " Expired message " ) ]
Expired ,
/// Peer not found
#[ display(fmt = " Peer not found " ) ]
PeerNotFound ,
/// Peer is disconnected
#[ display(fmt = " Peer disconnected: {} " , _0) ]
Disconnect ( DisconnectReason ) ,
/// Invalid node id
#[ display(fmt = " Invalid node id " ) ]
InvalidNodeId ,
/// Packet size is over the protocol limit
#[ display(fmt = " Packet is too large " ) ]
OversizedPacket ,
/// Reached system resource limits for this process
#[ display(fmt = " Too many open files in this process. Check your resource limits and restart parity " ) ]
ProcessTooManyFiles ,
/// Reached system wide resource limits
#[ display(fmt = " Too many open files on system. Consider closing some processes/release some file handlers or increas the system-wide resource limits and restart parity. " ) ]
SystemTooManyFiles ,
/// An unknown IO error occurred.
#[ display(fmt = " Unexpected IO error: {} " , _0) ]
Io ( io ::Error ) ,
}
2016-01-15 16:36:08 +01:00
2019-06-17 08:44:59 +02:00
/// Wraps io::Error for Display impl
#[ derive(Debug) ]
pub struct AddressResolveError ( Option < io ::Error > ) ;
2016-08-05 10:32:04 +02:00
2019-06-17 08:44:59 +02:00
impl fmt ::Display for AddressResolveError {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> Result < ( ) , fmt ::Error > {
write! ( f , " {} " , self . 0. as_ref ( ) . map_or ( " " . to_string ( ) , | e | e . to_string ( ) ) )
}
}
2016-01-15 16:36:08 +01:00
2019-06-17 08:44:59 +02:00
impl From < Option < io ::Error > > for AddressResolveError {
fn from ( err : Option < io ::Error > ) -> Self {
AddressResolveError ( err )
}
}
2017-11-13 14:37:08 +01:00
2019-06-17 08:44:59 +02:00
impl error ::Error for Error {
2019-08-27 17:29:33 +02:00
fn source ( & self ) -> Option < & ( dyn error ::Error + 'static ) > {
2019-06-17 08:44:59 +02:00
match self {
Error ::Decompression ( e ) = > Some ( e ) ,
Error ::Rlp ( e ) = > Some ( e ) ,
_ = > None ,
2017-11-13 14:37:08 +01:00
}
2019-06-17 08:44:59 +02:00
}
}
2018-06-01 13:37:43 +02:00
2019-06-17 08:44:59 +02:00
impl From < IoError > for Error {
fn from ( err : IoError ) -> Self {
Error ::SocketIo ( err )
}
}
2018-06-01 13:37:43 +02:00
2019-06-17 08:44:59 +02:00
impl From < snappy ::InvalidInput > for Error {
fn from ( err : snappy ::InvalidInput ) -> Self {
Error ::Decompression ( err )
}
}
2018-06-01 13:37:43 +02:00
2019-06-17 08:44:59 +02:00
impl From < rlp ::DecoderError > for Error {
fn from ( err : rlp ::DecoderError ) -> Self {
Error ::Rlp ( err )
2018-06-01 13:37:43 +02:00
}
}
impl From < io ::Error > for Error {
fn from ( err : io ::Error ) -> Self {
match err . raw_os_error ( ) {
2019-06-17 08:44:59 +02:00
Some ( ENFILE ) = > Error ::ProcessTooManyFiles ,
Some ( EMFILE ) = > Error ::SystemTooManyFiles ,
_ = > Error ::Io ( err )
2018-06-01 13:37:43 +02:00
}
2016-08-24 18:35:21 +02:00
}
}
2017-11-13 14:37:08 +01:00
impl From < ethkey ::Error > for Error {
fn from ( _err : ethkey ::Error ) -> Self {
2019-06-17 08:44:59 +02:00
Error ::Auth
2017-10-19 14:41:11 +02:00
}
}
2018-05-05 11:02:33 +02:00
impl From < ethkey ::crypto ::Error > for Error {
fn from ( _err : ethkey ::crypto ::Error ) -> Self {
2019-06-17 08:44:59 +02:00
Error ::Auth
2018-05-05 11:02:33 +02:00
}
}
impl From < crypto ::error ::SymmError > for Error {
fn from ( _err : crypto ::error ::SymmError ) -> Self {
2019-06-17 08:44:59 +02:00
Error ::Auth
2016-08-05 10:32:04 +02:00
}
}
2018-05-09 15:58:02 +02:00
impl From < net ::AddrParseError > for Error {
2019-06-17 08:44:59 +02:00
fn from ( _err : net ::AddrParseError ) -> Self { Error ::AddressParse }
2018-05-09 15:58:02 +02:00
}
2016-02-17 14:07:26 +01:00
#[ test ]
fn test_errors ( ) {
assert_eq! ( DisconnectReason ::ClientQuit , DisconnectReason ::from_u8 ( 8 ) ) ;
let mut r = DisconnectReason ::DisconnectRequested ;
for i in 0 .. 20 {
r = DisconnectReason ::from_u8 ( i ) ;
}
assert_eq! ( DisconnectReason ::Unknown , r ) ;
2019-06-17 08:44:59 +02:00
match < Error as From < rlp ::DecoderError > > ::from ( rlp ::DecoderError ::RlpIsTooBig ) {
Error ::Rlp ( _ ) = > { } ,
2018-05-05 11:02:33 +02:00
_ = > panic! ( " Unexpected error " ) ,
2016-02-17 14:07:26 +01:00
}
2019-06-17 08:44:59 +02:00
match < Error as From < ethkey ::crypto ::Error > > ::from ( ethkey ::crypto ::Error ::InvalidMessage ) {
Error ::Auth = > { } ,
2018-05-05 11:02:33 +02:00
_ = > panic! ( " Unexpected error " ) ,
2016-02-17 14:07:26 +01:00
}
}
2018-06-01 13:37:43 +02:00
#[ test ]
fn test_io_errors ( ) {
use libc ::{ EMFILE , ENFILE } ;
assert_matches! (
< Error as From < io ::Error > > ::from (
io ::Error ::from_raw_os_error ( ENFILE )
2019-06-17 08:44:59 +02:00
) ,
Error ::ProcessTooManyFiles ) ;
2018-06-01 13:37:43 +02:00
assert_matches! (
< Error as From < io ::Error > > ::from (
io ::Error ::from_raw_os_error ( EMFILE )
2019-06-17 08:44:59 +02:00
) ,
Error ::SystemTooManyFiles ) ;
2018-06-01 13:37:43 +02:00
assert_matches! (
< Error as From < io ::Error > > ::from (
io ::Error ::from_raw_os_error ( 0 )
2019-06-17 08:44:59 +02:00
) ,
Error ::Io ( _ ) ) ;
2018-06-01 13:37:43 +02:00
}