11use std:: {
22 collections:: { hash_map, HashMap , HashSet } ,
3- net:: SocketAddr ,
3+ net:: { IpAddr , SocketAddr } ,
44 sync:: Arc ,
55} ;
66
@@ -13,6 +13,7 @@ use heed::{
1313use parking_lot:: RwLock ;
1414use quinn:: { ClientConfig , Endpoint , ServerConfig } ;
1515use tokio_stream:: StreamNotifyClose ;
16+ use tracing:: instrument;
1617
1718use crate :: {
1819 archive:: Archive ,
@@ -28,8 +29,8 @@ use peer::{
2829} ;
2930pub use peer:: {
3031 ConnectionError as PeerConnectionError , Info as PeerConnectionInfo ,
31- InternalMessage as PeerConnectionMessage , PeerStateId ,
32- Request as PeerRequest , Response as PeerResponse ,
32+ InternalMessage as PeerConnectionMessage , Peer , PeerConnectionStatus ,
33+ PeerStateId , Request as PeerRequest , Response as PeerResponse ,
3334} ;
3435
3536#[ derive( Debug , thiserror:: Error ) ]
@@ -54,6 +55,10 @@ pub enum Error {
5455 Io ( #[ from] std:: io:: Error ) ,
5556 #[ error( "peer connection not found for {0}" ) ]
5657 MissingPeerConnection ( SocketAddr ) ,
58+ /// Unspecified peer IP addresses cannot be connected to.
59+ /// `0.0.0.0` is one example of an "unspecified" IP.
60+ #[ error( "unspecified peer ip address (cannot connect to '{0}')" ) ]
61+ UnspecfiedPeerIP ( IpAddr ) ,
5762 #[ error( transparent) ]
5863 NoInitialCipherSuite ( #[ from] quinn:: crypto:: rustls:: NoInitialCipherSuite ) ,
5964 #[ error( "peer connection" ) ]
@@ -169,11 +174,13 @@ fn configure_server() -> Result<(ServerConfig, Vec<u8>), Error> {
169174///
170175/// - a stream of incoming QUIC connections
171176/// - server certificate serialized into DER format
172- #[ allow( unused) ]
173177pub fn make_server_endpoint (
174178 bind_addr : SocketAddr ,
175179) -> Result < ( Endpoint , Vec < u8 > ) , Error > {
176180 let ( server_config, server_cert) = configure_server ( ) ?;
181+
182+ tracing:: info!( "creating server endpoint: binding to {bind_addr}" , ) ;
183+
177184 let mut endpoint = Endpoint :: server ( server_config, bind_addr) ?;
178185 let client_cfg = configure_client ( ) ?;
179186 endpoint. set_default_client_config ( client_cfg) ;
@@ -184,9 +191,6 @@ pub fn make_server_endpoint(
184191pub type PeerInfoRx =
185192 mpsc:: UnboundedReceiver < ( SocketAddr , Option < PeerConnectionInfo > ) > ;
186193
187- // State.
188- // Archive.
189-
190194// Keep track of peer state
191195// Exchange metadata
192196// Bulk download
@@ -218,7 +222,6 @@ impl Net {
218222 peer_connection_handle : PeerConnectionHandle ,
219223 ) -> Result < ( ) , Error > {
220224 tracing:: trace!( %addr, "add active peer: starting" ) ;
221-
222225 let mut active_peers_write = self . active_peers . write ( ) ;
223226 match active_peers_write. entry ( addr) {
224227 hash_map:: Entry :: Occupied ( _) => {
@@ -241,20 +244,37 @@ impl Net {
241244 }
242245 }
243246
244- // TODO: This should have more context. Last received message, connection state, etc.
245- pub fn get_active_peers ( & self ) -> Vec < SocketAddr > {
246- self . active_peers . read ( ) . keys ( ) . copied ( ) . collect ( )
247+ // TODO: This should have more context.
248+ // Last received message, connection state, etc.
249+ pub fn get_active_peers ( & self ) -> Vec < Peer > {
250+ self . active_peers
251+ . read ( )
252+ . iter ( )
253+ . map ( |( addr, conn_handle) | Peer {
254+ address : * addr,
255+ status : conn_handle. connection_status ( ) ,
256+ } )
257+ . collect ( )
247258 }
248259
260+ #[ instrument( skip_all, fields( addr) , err( Debug ) ) ]
249261 pub fn connect_peer (
250262 & self ,
251263 env : heed:: Env ,
252264 addr : SocketAddr ,
253265 ) -> Result < ( ) , Error > {
254266 if self . active_peers . read ( ) . contains_key ( & addr) {
255- tracing:: error!( %addr , "connect peer: already connected" ) ;
267+ tracing:: error!( "connect peer: already connected" ) ;
256268 return Err ( Error :: AlreadyConnected ( addr) ) ;
257269 }
270+
271+ // This check happens within Quinn with a
272+ // generic "invalid remote address". We run the
273+ // same check, and provide a friendlier error
274+ // message.
275+ if addr. ip ( ) . is_unspecified ( ) {
276+ return Err ( Error :: UnspecfiedPeerIP ( addr. ip ( ) ) ) ;
277+ }
258278 let connecting = self . server . connect ( addr, "localhost" ) ?;
259279 let mut rwtxn = env. write_txn ( ) ?;
260280 self . known_peers . put ( & mut rwtxn, & addr, & ( ) ) ?;
@@ -264,9 +284,10 @@ impl Net {
264284 archive : self . archive . clone ( ) ,
265285 state : self . state . clone ( ) ,
266286 } ;
287+
267288 let ( connection_handle, info_rx) =
268289 peer:: connect ( connecting, connection_ctxt) ;
269- tracing:: trace!( %addr , "connect peer: spawning info rx" ) ;
290+ tracing:: trace!( "connect peer: spawning info rx" ) ;
270291 tokio:: spawn ( {
271292 let info_rx = StreamNotifyClose :: new ( info_rx)
272293 . map ( move |info| Ok ( ( addr, info) ) ) ;
@@ -277,7 +298,8 @@ impl Net {
277298 }
278299 }
279300 } ) ;
280- tracing:: trace!( %addr, "connect peer: adding to active peers" ) ;
301+
302+ tracing:: trace!( "connect peer: adding to active peers" ) ;
281303 self . add_active_peer ( addr, connection_handle) ?;
282304 Ok ( ( ) )
283305 }
@@ -426,6 +448,7 @@ impl Net {
426448 }
427449 }
428450 } ) ;
451+ // TODO: is this the right state?
429452 self . add_active_peer ( addr, connection_handle) ?;
430453 Ok ( Some ( addr) )
431454 }
@@ -437,9 +460,10 @@ impl Net {
437460 addr : SocketAddr ,
438461 ) -> Result < ( ) , Error > {
439462 let active_peers_read = self . active_peers . read ( ) ;
440- let Some ( peer_connection_handle) = active_peers_read. get ( & addr) else {
441- return Err ( Error :: MissingPeerConnection ( addr) ) ;
442- } ;
463+ let peer_connection_handle = active_peers_read
464+ . get ( & addr)
465+ . ok_or_else ( || Error :: MissingPeerConnection ( addr) ) ?;
466+
443467 if let Err ( send_err) = peer_connection_handle
444468 . internal_message_tx
445469 . unbounded_send ( message)
@@ -450,29 +474,6 @@ impl Net {
450474 Ok ( ( ) )
451475 }
452476
453- // Push a request to the specified peers
454- pub fn push_request (
455- & self ,
456- request : PeerRequest ,
457- peers : & HashSet < SocketAddr > ,
458- ) {
459- let active_peers_read = self . active_peers . read ( ) ;
460- for addr in peers {
461- let Some ( peer_connection_handle) = active_peers_read. get ( addr)
462- else {
463- continue ;
464- } ;
465- if let Err ( _send_err) = peer_connection_handle
466- . internal_message_tx
467- . unbounded_send ( request. clone ( ) . into ( ) )
468- {
469- tracing:: warn!(
470- "Failed to push request to peer at {addr}: {request:?}"
471- )
472- }
473- }
474- }
475-
476477 /// Push a tx to all active peers, except those in the provided set
477478 pub fn push_tx (
478479 & self ,
@@ -484,6 +485,13 @@ impl Net {
484485 . iter ( )
485486 . filter ( |( addr, _) | !exclude. contains ( addr) )
486487 . for_each ( |( addr, peer_connection_handle) | {
488+ match peer_connection_handle. connection_status ( ) {
489+ PeerConnectionStatus :: Connecting => {
490+ tracing:: trace!( %addr, "skipping peer at {addr} because it is not fully connected" ) ;
491+ return ;
492+ }
493+ PeerConnectionStatus :: Connected => { }
494+ }
487495 let request = PeerRequest :: PushTransaction {
488496 transaction : tx. clone ( ) ,
489497 } ;
0 commit comments