mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
chore(net): move reth_eth_wire::DisconnectReason to reth-eth-wire-types (#10006)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
@ -41,6 +41,7 @@ arbitrary = { workspace = true, features = ["derive"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
reth-primitives = { workspace = true, features = ["arbitrary"] }
|
||||
reth-eth-wire-types = { workspace = true, features = ["arbitrary"] }
|
||||
reth-tracing.workspace = true
|
||||
|
||||
test-fuzz.workspace = true
|
||||
|
||||
@ -1,142 +1,13 @@
|
||||
//! Disconnect
|
||||
|
||||
use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header};
|
||||
use futures::{Sink, SinkExt};
|
||||
use reth_codecs::derive_arbitrary;
|
||||
use reth_ecies::stream::ECIESStream;
|
||||
use reth_primitives::bytes::{Buf, BufMut};
|
||||
use std::future::Future;
|
||||
use thiserror::Error;
|
||||
|
||||
use futures::{Sink, SinkExt};
|
||||
use reth_ecies::stream::ECIESStream;
|
||||
use reth_eth_wire_types::DisconnectReason;
|
||||
use tokio::io::AsyncWrite;
|
||||
use tokio_util::codec::{Encoder, Framed};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// RLPx disconnect reason.
|
||||
#[derive_arbitrary(rlp)]
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, derive_more::Display)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum DisconnectReason {
|
||||
/// Disconnect requested by the local node or remote peer.
|
||||
#[default]
|
||||
#[display(fmt = "disconnect requested")]
|
||||
DisconnectRequested = 0x00,
|
||||
/// TCP related error
|
||||
#[display(fmt = "TCP sub-system error")]
|
||||
TcpSubsystemError = 0x01,
|
||||
/// Breach of protocol at the transport or p2p level
|
||||
#[display(fmt = "breach of protocol, e.g. a malformed message, bad RLP, etc.")]
|
||||
ProtocolBreach = 0x02,
|
||||
/// Node has no matching protocols.
|
||||
#[display(fmt = "useless peer")]
|
||||
UselessPeer = 0x03,
|
||||
/// Either the remote or local node has too many peers.
|
||||
#[display(fmt = "too many peers")]
|
||||
TooManyPeers = 0x04,
|
||||
/// Already connected to the peer.
|
||||
#[display(fmt = "already connected")]
|
||||
AlreadyConnected = 0x05,
|
||||
/// `p2p` protocol version is incompatible
|
||||
#[display(fmt = "incompatible P2P protocol version")]
|
||||
IncompatibleP2PProtocolVersion = 0x06,
|
||||
/// Received a null node identity.
|
||||
#[display(fmt = "null node identity received - this is automatically invalid")]
|
||||
NullNodeIdentity = 0x07,
|
||||
/// Reason when the client is shutting down.
|
||||
#[display(fmt = "client quitting")]
|
||||
ClientQuitting = 0x08,
|
||||
/// When the received handshake's identify is different from what is expected.
|
||||
#[display(fmt = "unexpected identity in handshake")]
|
||||
UnexpectedHandshakeIdentity = 0x09,
|
||||
/// The node is connected to itself
|
||||
#[display(fmt = "identity is the same as this node (i.e. connected to itself)")]
|
||||
ConnectedToSelf = 0x0a,
|
||||
/// Peer or local node did not respond to a ping in time.
|
||||
#[display(fmt = "ping timeout")]
|
||||
PingTimeout = 0x0b,
|
||||
/// Peer or local node violated a subprotocol-specific rule.
|
||||
#[display(fmt = "some other reason specific to a subprotocol")]
|
||||
SubprotocolSpecific = 0x10,
|
||||
}
|
||||
|
||||
/// This represents an unknown disconnect reason with the given code.
|
||||
#[derive(Debug, Clone, Error)]
|
||||
#[error("unknown disconnect reason: {0}")]
|
||||
pub struct UnknownDisconnectReason(u8);
|
||||
|
||||
impl TryFrom<u8> for DisconnectReason {
|
||||
// This error type should not be used to crash the node, but rather to log the error and
|
||||
// disconnect the peer.
|
||||
type Error = UnknownDisconnectReason;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
0x00 => Ok(Self::DisconnectRequested),
|
||||
0x01 => Ok(Self::TcpSubsystemError),
|
||||
0x02 => Ok(Self::ProtocolBreach),
|
||||
0x03 => Ok(Self::UselessPeer),
|
||||
0x04 => Ok(Self::TooManyPeers),
|
||||
0x05 => Ok(Self::AlreadyConnected),
|
||||
0x06 => Ok(Self::IncompatibleP2PProtocolVersion),
|
||||
0x07 => Ok(Self::NullNodeIdentity),
|
||||
0x08 => Ok(Self::ClientQuitting),
|
||||
0x09 => Ok(Self::UnexpectedHandshakeIdentity),
|
||||
0x0a => Ok(Self::ConnectedToSelf),
|
||||
0x0b => Ok(Self::PingTimeout),
|
||||
0x10 => Ok(Self::SubprotocolSpecific),
|
||||
_ => Err(UnknownDisconnectReason(value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for DisconnectReason {
|
||||
/// The [`Encodable`] implementation for [`DisconnectReason`] encodes the disconnect reason in
|
||||
/// a single-element RLP list.
|
||||
fn encode(&self, out: &mut dyn BufMut) {
|
||||
vec![*self as u8].encode(out);
|
||||
}
|
||||
fn length(&self) -> usize {
|
||||
vec![*self as u8].length()
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for DisconnectReason {
|
||||
/// The [`Decodable`] implementation for [`DisconnectReason`] supports either a disconnect
|
||||
/// reason encoded a single byte or a RLP list containing the disconnect reason.
|
||||
fn decode(buf: &mut &[u8]) -> alloy_rlp::Result<Self> {
|
||||
if buf.is_empty() {
|
||||
return Err(RlpError::InputTooShort)
|
||||
} else if buf.len() > 2 {
|
||||
return Err(RlpError::Overflow)
|
||||
}
|
||||
|
||||
if buf.len() > 1 {
|
||||
// this should be a list, so decode the list header. this should advance the buffer so
|
||||
// buf[0] is the first (and only) element of the list.
|
||||
let header = Header::decode(buf)?;
|
||||
|
||||
if !header.list {
|
||||
return Err(RlpError::UnexpectedString)
|
||||
}
|
||||
|
||||
if header.payload_length != 1 {
|
||||
return Err(RlpError::ListLengthMismatch { expected: 1, got: header.payload_length })
|
||||
}
|
||||
}
|
||||
|
||||
// geth rlp encodes [`DisconnectReason::DisconnectRequested`] as 0x00 and not as empty
|
||||
// string 0x80
|
||||
if buf[0] == 0x00 {
|
||||
buf.advance(1);
|
||||
Ok(Self::DisconnectRequested)
|
||||
} else {
|
||||
Self::try_from(u8::decode(buf)?)
|
||||
.map_err(|_| RlpError::Custom("unknown disconnect reason"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This trait is meant to allow higher level protocols like `eth` to disconnect from a peer, using
|
||||
/// lower-level disconnect functions (such as those that exist in the `p2p` protocol) if the
|
||||
/// underlying stream supports it.
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
//! Error handling for [`P2PStream`](crate::P2PStream).
|
||||
|
||||
use crate::{
|
||||
capability::SharedCapabilityError, disconnect::UnknownDisconnectReason, DisconnectReason,
|
||||
ProtocolVersion,
|
||||
};
|
||||
use reth_primitives::GotExpected;
|
||||
use std::io;
|
||||
|
||||
use reth_eth_wire_types::{DisconnectReason, UnknownDisconnectReason};
|
||||
use reth_primitives::GotExpected;
|
||||
|
||||
use crate::{capability::SharedCapabilityError, ProtocolVersion};
|
||||
|
||||
/// Errors when sending/receiving p2p messages. These should result in kicking the peer.
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum P2PStreamError {
|
||||
|
||||
@ -33,7 +33,7 @@ pub use tokio_util::codec::{
|
||||
|
||||
pub use crate::{
|
||||
capability::Capability,
|
||||
disconnect::{CanDisconnect, DisconnectReason},
|
||||
disconnect::CanDisconnect,
|
||||
ethstream::{EthStream, UnauthedEthStream, MAX_MESSAGE_SIZE},
|
||||
hello::{HelloMessage, HelloMessageBuilder, HelloMessageWithProtocols},
|
||||
p2pstream::{
|
||||
@ -45,5 +45,3 @@ pub use crate::{
|
||||
// Re-export wire types
|
||||
#[doc(inline)]
|
||||
pub use reth_eth_wire_types::*;
|
||||
|
||||
pub use disconnect::UnknownDisconnectReason;
|
||||
|
||||
Reference in New Issue
Block a user