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