@@ -6,64 +6,142 @@ use lightning::ln::msgs::SocketAddress;
66
77use bitcoin:: secp256k1:: PublicKey ;
88
9+ use std:: collections:: hash_map:: { self , HashMap } ;
910use std:: net:: ToSocketAddrs ;
1011use std:: ops:: Deref ;
11- use std:: sync:: Arc ;
12+ use std:: sync:: { Arc , Mutex } ;
1213use std:: time:: Duration ;
1314
14- pub ( crate ) async fn connect_peer_if_necessary < L : Deref + Clone + Sync + Send > (
15- node_id : PublicKey , addr : SocketAddress , peer_manager : Arc < PeerManager > , logger : L ,
16- ) -> Result < ( ) , Error >
15+ pub ( crate ) struct ConnectionManager < L : Deref + Clone + Sync + Send >
1716where
1817 L :: Target : Logger ,
1918{
20- if peer_manager. peer_by_node_id ( & node_id) . is_some ( ) {
21- return Ok ( ( ) ) ;
22- }
23-
24- do_connect_peer ( node_id, addr, peer_manager, logger) . await
19+ pending_connections :
20+ Mutex < HashMap < PublicKey , Vec < tokio:: sync:: oneshot:: Sender < Result < ( ) , Error > > > > > ,
21+ peer_manager : Arc < PeerManager > ,
22+ logger : L ,
2523}
2624
27- pub ( crate ) async fn do_connect_peer < L : Deref + Clone + Sync + Send > (
28- node_id : PublicKey , addr : SocketAddress , peer_manager : Arc < PeerManager > , logger : L ,
29- ) -> Result < ( ) , Error >
25+ impl < L : Deref + Clone + Sync + Send > ConnectionManager < L >
3026where
3127 L :: Target : Logger ,
3228{
33- log_info ! ( logger, "Connecting to peer: {}@{}" , node_id, addr) ;
34-
35- let socket_addr = addr
36- . to_socket_addrs ( )
37- . map_err ( |e| {
38- log_error ! ( logger, "Failed to resolve network address: {}" , e) ;
39- Error :: InvalidSocketAddress
40- } ) ?
41- . next ( )
42- . ok_or ( Error :: ConnectionFailed ) ?;
43-
44- match lightning_net_tokio:: connect_outbound ( Arc :: clone ( & peer_manager) , node_id, socket_addr)
45- . await
46- {
47- Some ( connection_closed_future) => {
48- let mut connection_closed_future = Box :: pin ( connection_closed_future) ;
49- loop {
50- tokio:: select! {
51- _ = & mut connection_closed_future => {
52- log_info!( logger, "Peer connection closed: {}@{}" , node_id, addr) ;
53- return Err ( Error :: ConnectionFailed ) ;
54- } ,
55- _ = tokio:: time:: sleep( Duration :: from_millis( 10 ) ) => { } ,
56- } ;
57-
58- match peer_manager. peer_by_node_id ( & node_id) {
59- Some ( _) => return Ok ( ( ) ) ,
60- None => continue ,
29+ pub ( crate ) fn new ( peer_manager : Arc < PeerManager > , logger : L ) -> Self {
30+ let pending_connections = Mutex :: new ( HashMap :: new ( ) ) ;
31+ Self { pending_connections, peer_manager, logger }
32+ }
33+
34+ pub ( crate ) async fn connect_peer_if_necessary (
35+ & self , node_id : PublicKey , addr : SocketAddress ,
36+ ) -> Result < ( ) , Error > {
37+ if self . peer_manager . peer_by_node_id ( & node_id) . is_some ( ) {
38+ return Ok ( ( ) ) ;
39+ }
40+
41+ self . do_connect_peer ( node_id, addr) . await
42+ }
43+
44+ pub ( crate ) async fn do_connect_peer (
45+ & self , node_id : PublicKey , addr : SocketAddress ,
46+ ) -> Result < ( ) , Error > {
47+ // First, we check if there is already an outbound connection in flight, if so, we just
48+ // await on the corresponding watch channel. The task driving the connection future will
49+ // send us the result..
50+ let pending_ready_receiver_opt = self . register_or_subscribe_pending_connection ( & node_id) ;
51+ if let Some ( pending_connection_ready_receiver) = pending_ready_receiver_opt {
52+ return pending_connection_ready_receiver. await . map_err ( |e| {
53+ debug_assert ! ( false , "Failed to receive connection result: {:?}" , e) ;
54+ log_error ! ( self . logger, "Failed to receive connection result: {:?}" , e) ;
55+ Error :: ConnectionFailed
56+ } ) ?;
57+ }
58+
59+ log_info ! ( self . logger, "Connecting to peer: {}@{}" , node_id, addr) ;
60+
61+ let socket_addr = addr
62+ . to_socket_addrs ( )
63+ . map_err ( |e| {
64+ log_error ! ( self . logger, "Failed to resolve network address {}: {}" , addr, e) ;
65+ self . propagate_result_to_subscribers ( & node_id, Err ( Error :: InvalidSocketAddress ) ) ;
66+ Error :: InvalidSocketAddress
67+ } ) ?
68+ . next ( )
69+ . ok_or_else ( || {
70+ log_error ! ( self . logger, "Failed to resolve network address {}" , addr) ;
71+ self . propagate_result_to_subscribers ( & node_id, Err ( Error :: InvalidSocketAddress ) ) ;
72+ Error :: InvalidSocketAddress
73+ } ) ?;
74+
75+ let connection_future = lightning_net_tokio:: connect_outbound (
76+ Arc :: clone ( & self . peer_manager ) ,
77+ node_id,
78+ socket_addr,
79+ ) ;
80+
81+ let res = match connection_future. await {
82+ Some ( connection_closed_future) => {
83+ let mut connection_closed_future = Box :: pin ( connection_closed_future) ;
84+ loop {
85+ tokio:: select! {
86+ _ = & mut connection_closed_future => {
87+ log_info!( self . logger, "Peer connection closed: {}@{}" , node_id, addr) ;
88+ break Err ( Error :: ConnectionFailed ) ;
89+ } ,
90+ _ = tokio:: time:: sleep( Duration :: from_millis( 10 ) ) => { } ,
91+ } ;
92+
93+ match self . peer_manager . peer_by_node_id ( & node_id) {
94+ Some ( _) => break Ok ( ( ) ) ,
95+ None => continue ,
96+ }
6197 }
98+ } ,
99+ None => {
100+ log_error ! ( self . logger, "Failed to connect to peer: {}@{}" , node_id, addr) ;
101+ Err ( Error :: ConnectionFailed )
102+ } ,
103+ } ;
104+
105+ self . propagate_result_to_subscribers ( & node_id, res) ;
106+
107+ res
108+ }
109+
110+ fn register_or_subscribe_pending_connection (
111+ & self , node_id : & PublicKey ,
112+ ) -> Option < tokio:: sync:: oneshot:: Receiver < Result < ( ) , Error > > > {
113+ let mut pending_connections_lock = self . pending_connections . lock ( ) . unwrap ( ) ;
114+ match pending_connections_lock. entry ( * node_id) {
115+ hash_map:: Entry :: Occupied ( mut entry) => {
116+ let ( tx, rx) = tokio:: sync:: oneshot:: channel ( ) ;
117+ entry. get_mut ( ) . push ( tx) ;
118+ Some ( rx)
119+ } ,
120+ hash_map:: Entry :: Vacant ( entry) => {
121+ entry. insert ( Vec :: new ( ) ) ;
122+ None
123+ } ,
124+ }
125+ }
126+
127+ fn propagate_result_to_subscribers ( & self , node_id : & PublicKey , res : Result < ( ) , Error > ) {
128+ // Send the result to any other tasks that might be waiting on it by now.
129+ let mut pending_connections_lock = self . pending_connections . lock ( ) . unwrap ( ) ;
130+ if let Some ( connection_ready_senders) = pending_connections_lock. remove ( node_id) {
131+ for sender in connection_ready_senders {
132+ let _ = sender. send ( res) . map_err ( |e| {
133+ debug_assert ! (
134+ false ,
135+ "Failed to send connection result to subscribers: {:?}" ,
136+ e
137+ ) ;
138+ log_error ! (
139+ self . logger,
140+ "Failed to send connection result to subscribers: {:?}" ,
141+ e
142+ ) ;
143+ } ) ;
62144 }
63- } ,
64- None => {
65- log_error ! ( logger, "Failed to connect to peer: {}@{}" , node_id, addr) ;
66- Err ( Error :: ConnectionFailed )
67- } ,
145+ }
68146 }
69147}
0 commit comments