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(
78 self,
79 direction: Direction,
80 peer_id: PeerId,
81 conn: ProtocolConnection,
82 ) -> Self::Connection;
83}
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
87pub enum OnNotSupported {
88 #[default]
90 KeepAlive,
91 Disconnect,
93}
94
95#[derive(Debug)]
97pub struct RlpxSubProtocol(Box<dyn DynProtocolHandler>);
98
99pub trait IntoRlpxSubProtocol {
101 fn into_rlpx_sub_protocol(self) -> RlpxSubProtocol;
103}
104
105impl<T> IntoRlpxSubProtocol for T
106where
107 T: ProtocolHandler,
108{
109 fn into_rlpx_sub_protocol(self) -> RlpxSubProtocol {
110 RlpxSubProtocol(Box::new(self))
111 }
112}
113
114impl IntoRlpxSubProtocol for RlpxSubProtocol {
115 fn into_rlpx_sub_protocol(self) -> RlpxSubProtocol {
116 self
117 }
118}
119
120#[derive(Debug, Default)]
122pub struct RlpxSubProtocols {
123 protocols: Vec<RlpxSubProtocol>,
125}
126
127impl RlpxSubProtocols {
128 pub fn push(&mut self, protocol: impl IntoRlpxSubProtocol) {
130 self.protocols.push(protocol.into_rlpx_sub_protocol());
131 }
132
133 pub(crate) fn on_incoming(&self, socket_addr: SocketAddr) -> RlpxSubProtocolHandlers {
136 RlpxSubProtocolHandlers(
137 self.protocols
138 .iter()
139 .filter_map(|protocol| protocol.0.on_incoming(socket_addr))
140 .collect(),
141 )
142 }
143
144 pub(crate) fn on_outgoing(
147 &self,
148 socket_addr: SocketAddr,
149 peer_id: PeerId,
150 ) -> RlpxSubProtocolHandlers {
151 RlpxSubProtocolHandlers(
152 self.protocols
153 .iter()
154 .filter_map(|protocol| protocol.0.on_outgoing(socket_addr, peer_id))
155 .collect(),
156 )
157 }
158}
159
160#[derive(Default)]
162pub(crate) struct RlpxSubProtocolHandlers(pub(crate) Vec<Box<dyn DynConnectionHandler>>);
163
164impl RlpxSubProtocolHandlers {
165 pub(crate) fn into_iter(self) -> impl Iterator<Item = Box<dyn DynConnectionHandler>> {
167 self.0.into_iter()
168 }
169}
170
171impl Deref for RlpxSubProtocolHandlers {
172 type Target = Vec<Box<dyn DynConnectionHandler>>;
173
174 fn deref(&self) -> &Self::Target {
175 &self.0
176 }
177}
178
179impl DerefMut for RlpxSubProtocolHandlers {
180 fn deref_mut(&mut self) -> &mut Self::Target {
181 &mut self.0
182 }
183}
184
185pub(crate) trait DynProtocolHandler: fmt::Debug + Send + Sync + 'static {
186 fn on_incoming(&self, socket_addr: SocketAddr) -> Option<Box<dyn DynConnectionHandler>>;
187
188 fn on_outgoing(
189 &self,
190 socket_addr: SocketAddr,
191 peer_id: PeerId,
192 ) -> Option<Box<dyn DynConnectionHandler>>;
193}
194
195impl<T: ProtocolHandler> DynProtocolHandler for T {
196 fn on_incoming(&self, socket_addr: SocketAddr) -> Option<Box<dyn DynConnectionHandler>> {
197 T::on_incoming(self, socket_addr)
198 .map(|handler| Box::new(handler) as Box<dyn DynConnectionHandler>)
199 }
200
201 fn on_outgoing(
202 &self,
203 socket_addr: SocketAddr,
204 peer_id: PeerId,
205 ) -> Option<Box<dyn DynConnectionHandler>> {
206 T::on_outgoing(self, socket_addr, peer_id)
207 .map(|handler| Box::new(handler) as Box<dyn DynConnectionHandler>)
208 }
209}
210
211pub(crate) trait DynConnectionHandler: Send + Sync + 'static {
213 fn protocol(&self) -> Protocol;
214
215 fn inbound_limits(&self) -> ProtocolIngressLimits;
216
217 fn on_unsupported_by_peer(
218 self: Box<Self>,
219 supported: &SharedCapabilities,
220 direction: Direction,
221 peer_id: PeerId,
222 ) -> OnNotSupported;
223
224 fn into_connection(
225 self: Box<Self>,
226 direction: Direction,
227 peer_id: PeerId,
228 conn: ProtocolConnection,
229 ) -> Pin<Box<dyn Stream<Item = BytesMut> + Send + 'static>>;
230}
231
232impl<T: ConnectionHandler> DynConnectionHandler for T {
233 fn protocol(&self) -> Protocol {
234 T::protocol(self)
235 }
236
237 fn inbound_limits(&self) -> ProtocolIngressLimits {
238 T::inbound_limits(self)
239 }
240
241 fn on_unsupported_by_peer(
242 self: Box<Self>,
243 supported: &SharedCapabilities,
244 direction: Direction,
245 peer_id: PeerId,
246 ) -> OnNotSupported {
247 T::on_unsupported_by_peer(*self, supported, direction, peer_id)
248 }
249
250 fn into_connection(
251 self: Box<Self>,
252 direction: Direction,
253 peer_id: PeerId,
254 conn: ProtocolConnection,
255 ) -> Pin<Box<dyn Stream<Item = BytesMut> + Send + 'static>> {
256 Box::pin(T::into_connection(*self, direction, peer_id, conn))
257 }
258}