1use alloy_primitives::bytes::BytesMut;
6use futures::Stream;
7use reth_eth_wire::{
8 capability::SharedCapabilities,
9 multiplex::ProtocolConnection,
10 protocol::{Protocol, ProtocolIngressLimits},
11};
12use reth_network_api::{Direction, PeerId};
13use std::{
14 fmt,
15 net::SocketAddr,
16 ops::{Deref, DerefMut},
17 pin::Pin,
18};
19
20pub trait ProtocolHandler: fmt::Debug + Send + Sync + 'static {
23 type ConnectionHandler: ConnectionHandler;
25
26 fn on_incoming(&self, socket_addr: SocketAddr) -> Option<Self::ConnectionHandler>;
31
32 fn on_outgoing(
37 &self,
38 socket_addr: SocketAddr,
39 peer_id: PeerId,
40 ) -> Option<Self::ConnectionHandler>;
41}
42
43pub trait ConnectionHandler: Send + Sync + 'static {
45 type Connection: Stream<Item = BytesMut> + Send + 'static;
49
50 fn protocol(&self) -> Protocol;
54
55 fn inbound_limits(&self) -> ProtocolIngressLimits {
57 ProtocolIngressLimits::default()
58 }
59
60 fn on_unsupported_by_peer(
63 self,
64 supported: &SharedCapabilities,
65 direction: Direction,
66 peer_id: PeerId,
67 ) -> OnNotSupported;
68
69 fn into_connection(
73 self,
74 direction: Direction,
75 peer_id: PeerId,
76 conn: ProtocolConnection,
77 ) -> Self::Connection;
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
82pub enum OnNotSupported {
83 #[default]
85 KeepAlive,
86 Disconnect,
88}
89
90#[derive(Debug)]
92pub struct RlpxSubProtocol(Box<dyn DynProtocolHandler>);
93
94pub trait IntoRlpxSubProtocol {
96 fn into_rlpx_sub_protocol(self) -> RlpxSubProtocol;
98}
99
100impl<T> IntoRlpxSubProtocol for T
101where
102 T: ProtocolHandler + Send + Sync + 'static,
103{
104 fn into_rlpx_sub_protocol(self) -> RlpxSubProtocol {
105 RlpxSubProtocol(Box::new(self))
106 }
107}
108
109impl IntoRlpxSubProtocol for RlpxSubProtocol {
110 fn into_rlpx_sub_protocol(self) -> RlpxSubProtocol {
111 self
112 }
113}
114
115#[derive(Debug, Default)]
117pub struct RlpxSubProtocols {
118 protocols: Vec<RlpxSubProtocol>,
120}
121
122impl RlpxSubProtocols {
123 pub fn push(&mut self, protocol: impl IntoRlpxSubProtocol) {
125 self.protocols.push(protocol.into_rlpx_sub_protocol());
126 }
127
128 pub(crate) fn on_incoming(&self, socket_addr: SocketAddr) -> RlpxSubProtocolHandlers {
131 RlpxSubProtocolHandlers(
132 self.protocols
133 .iter()
134 .filter_map(|protocol| protocol.0.on_incoming(socket_addr))
135 .collect(),
136 )
137 }
138
139 pub(crate) fn on_outgoing(
142 &self,
143 socket_addr: SocketAddr,
144 peer_id: PeerId,
145 ) -> RlpxSubProtocolHandlers {
146 RlpxSubProtocolHandlers(
147 self.protocols
148 .iter()
149 .filter_map(|protocol| protocol.0.on_outgoing(socket_addr, peer_id))
150 .collect(),
151 )
152 }
153}
154
155#[derive(Default)]
157pub(crate) struct RlpxSubProtocolHandlers(pub(crate) Vec<Box<dyn DynConnectionHandler>>);
158
159impl RlpxSubProtocolHandlers {
160 pub(crate) fn into_iter(self) -> impl Iterator<Item = Box<dyn DynConnectionHandler>> {
162 self.0.into_iter()
163 }
164}
165
166impl Deref for RlpxSubProtocolHandlers {
167 type Target = Vec<Box<dyn DynConnectionHandler>>;
168
169 fn deref(&self) -> &Self::Target {
170 &self.0
171 }
172}
173
174impl DerefMut for RlpxSubProtocolHandlers {
175 fn deref_mut(&mut self) -> &mut Self::Target {
176 &mut self.0
177 }
178}
179
180pub(crate) trait DynProtocolHandler: fmt::Debug + Send + Sync + 'static {
181 fn on_incoming(&self, socket_addr: SocketAddr) -> Option<Box<dyn DynConnectionHandler>>;
182
183 fn on_outgoing(
184 &self,
185 socket_addr: SocketAddr,
186 peer_id: PeerId,
187 ) -> Option<Box<dyn DynConnectionHandler>>;
188}
189
190impl<T: ProtocolHandler> DynProtocolHandler for T {
191 fn on_incoming(&self, socket_addr: SocketAddr) -> Option<Box<dyn DynConnectionHandler>> {
192 T::on_incoming(self, socket_addr)
193 .map(|handler| Box::new(handler) as Box<dyn DynConnectionHandler>)
194 }
195
196 fn on_outgoing(
197 &self,
198 socket_addr: SocketAddr,
199 peer_id: PeerId,
200 ) -> Option<Box<dyn DynConnectionHandler>> {
201 T::on_outgoing(self, socket_addr, peer_id)
202 .map(|handler| Box::new(handler) as Box<dyn DynConnectionHandler>)
203 }
204}
205
206pub(crate) trait DynConnectionHandler: Send + Sync + 'static {
208 fn protocol(&self) -> Protocol;
209
210 fn inbound_limits(&self) -> ProtocolIngressLimits;
211
212 fn on_unsupported_by_peer(
213 self: Box<Self>,
214 supported: &SharedCapabilities,
215 direction: Direction,
216 peer_id: PeerId,
217 ) -> OnNotSupported;
218
219 fn into_connection(
220 self: Box<Self>,
221 direction: Direction,
222 peer_id: PeerId,
223 conn: ProtocolConnection,
224 ) -> Pin<Box<dyn Stream<Item = BytesMut> + Send + 'static>>;
225}
226
227impl<T: ConnectionHandler> DynConnectionHandler for T {
228 fn protocol(&self) -> Protocol {
229 T::protocol(self)
230 }
231
232 fn inbound_limits(&self) -> ProtocolIngressLimits {
233 T::inbound_limits(self)
234 }
235
236 fn on_unsupported_by_peer(
237 self: Box<Self>,
238 supported: &SharedCapabilities,
239 direction: Direction,
240 peer_id: PeerId,
241 ) -> OnNotSupported {
242 T::on_unsupported_by_peer(*self, supported, direction, peer_id)
243 }
244
245 fn into_connection(
246 self: Box<Self>,
247 direction: Direction,
248 peer_id: PeerId,
249 conn: ProtocolConnection,
250 ) -> Pin<Box<dyn Stream<Item = BytesMut> + Send + 'static>> {
251 Box::pin(T::into_connection(*self, direction, peer_id, conn))
252 }
253}