1#![allow(clippy::arithmetic_side_effects)]
2
3pub mod nonblocking;
4pub mod udp_client;
5
6use {
7 crate::{
8 nonblocking::udp_client::UdpClientConnection as NonblockingUdpConnection,
9 udp_client::UdpClientConnection as BlockingUdpConnection,
10 },
11 solana_connection_cache::{
12 connection_cache::{
13 BaseClientConnection, ClientError, ConnectionManager, ConnectionPool,
14 ConnectionPoolError, NewConnectionConfig, Protocol,
15 },
16 connection_cache_stats::ConnectionCacheStats,
17 },
18 solana_keypair::Keypair,
19 solana_net_utils::sockets::{self, SocketConfiguration},
20 std::{
21 net::{SocketAddr, UdpSocket},
22 sync::Arc,
23 },
24};
25
26pub struct UdpPool {
27 connections: Vec<Arc<Udp>>,
28}
29impl ConnectionPool for UdpPool {
30 type BaseClientConnection = Udp;
31 type NewConnectionConfig = UdpConfig;
32
33 fn add_connection(&mut self, config: &Self::NewConnectionConfig, addr: &SocketAddr) -> usize {
34 let connection = self.create_pool_entry(config, addr);
35 let idx = self.connections.len();
36 self.connections.push(connection);
37 idx
38 }
39
40 fn num_connections(&self) -> usize {
41 self.connections.len()
42 }
43
44 fn get(&self, index: usize) -> Result<Arc<Self::BaseClientConnection>, ConnectionPoolError> {
45 self.connections
46 .get(index)
47 .cloned()
48 .ok_or(ConnectionPoolError::IndexOutOfRange)
49 }
50
51 fn create_pool_entry(
52 &self,
53 config: &Self::NewConnectionConfig,
54 _addr: &SocketAddr,
55 ) -> Arc<Self::BaseClientConnection> {
56 Arc::new(Udp(config.udp_socket.clone()))
57 }
58}
59
60pub struct UdpConfig {
61 udp_socket: Arc<UdpSocket>,
62}
63
64impl NewConnectionConfig for UdpConfig {
65 fn new() -> Result<Self, ClientError> {
66 #[cfg(not(feature = "dev-context-only-utils"))]
69 let bind_ip = std::net::IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED);
70 #[cfg(feature = "dev-context-only-utils")]
71 let bind_ip = std::net::IpAddr::V4(std::net::Ipv4Addr::LOCALHOST);
72
73 let socket = sockets::bind_in_range_with_config(
76 bind_ip,
77 solana_net_utils::VALIDATOR_PORT_RANGE,
78 SocketConfiguration::default(),
79 )
80 .map_err(Into::<ClientError>::into)?;
81 Ok(Self {
82 udp_socket: Arc::new(socket.1),
83 })
84 }
85}
86
87pub struct Udp(Arc<UdpSocket>);
88impl BaseClientConnection for Udp {
89 type BlockingClientConnection = BlockingUdpConnection;
90 type NonblockingClientConnection = NonblockingUdpConnection;
91
92 fn new_blocking_connection(
93 &self,
94 addr: SocketAddr,
95 _stats: Arc<ConnectionCacheStats>,
96 ) -> Arc<Self::BlockingClientConnection> {
97 Arc::new(BlockingUdpConnection::new_from_addr(self.0.clone(), addr))
98 }
99
100 fn new_nonblocking_connection(
101 &self,
102 addr: SocketAddr,
103 _stats: Arc<ConnectionCacheStats>,
104 ) -> Arc<Self::NonblockingClientConnection> {
105 Arc::new(NonblockingUdpConnection::new_from_addr(
106 self.0.try_clone().unwrap(),
107 addr,
108 ))
109 }
110}
111
112#[derive(Default)]
113pub struct UdpConnectionManager {}
114
115impl ConnectionManager for UdpConnectionManager {
116 type ConnectionPool = UdpPool;
117 type NewConnectionConfig = UdpConfig;
118
119 const PROTOCOL: Protocol = Protocol::UDP;
120
121 fn new_connection_pool(&self) -> Self::ConnectionPool {
122 UdpPool {
123 connections: Vec::default(),
124 }
125 }
126
127 fn new_connection_config(&self) -> Self::NewConnectionConfig {
128 UdpConfig::new().unwrap()
129 }
130
131 fn update_key(&self, _key: &Keypair) -> Result<(), Box<dyn std::error::Error>> {
132 Ok(())
133 }
134}