66// accordance with one or both of these licenses.
77
88use std:: collections:: hash_map:: { self , HashMap } ;
9- use std:: net:: ToSocketAddrs ;
109use std:: ops:: Deref ;
1110use std:: sync:: { Arc , Mutex } ;
1211use std:: time:: Duration ;
@@ -15,7 +14,7 @@ use bitcoin::secp256k1::PublicKey;
1514use lightning:: ln:: msgs:: SocketAddress ;
1615
1716use crate :: config:: TorConfig ;
18- use crate :: logger:: { log_error, log_info, LdkLogger } ;
17+ use crate :: logger:: { log_debug , log_error, log_info, LdkLogger } ;
1918use crate :: types:: { KeysManager , PeerManager } ;
2019use crate :: Error ;
2120
5655
5756 pub ( crate ) async fn do_connect_peer (
5857 & self , node_id : PublicKey , addr : SocketAddress ,
58+ ) -> Result < ( ) , Error > {
59+ let res = self . do_connect_peer_internal ( node_id, addr) . await ;
60+ self . propagate_result_to_subscribers ( & node_id, res) ;
61+ res
62+ }
63+
64+ async fn do_connect_peer_internal (
65+ & self , node_id : PublicKey , addr : SocketAddress ,
5966 ) -> Result < ( ) , Error > {
6067 // First, we check if there is already an outbound connection in flight, if so, we just
6168 // await on the corresponding watch channel. The task driving the connection future will
@@ -71,15 +78,14 @@ where
7178
7279 log_info ! ( self . logger, "Connecting to peer: {}@{}" , node_id, addr) ;
7380
74- let res = match addr {
81+ match addr {
7582 SocketAddress :: OnionV2 ( old_onion_addr) => {
7683 log_error ! (
77- self . logger,
78- "Failed to resolve network address {:?}: Resolution of OnionV2 addresses is currently unsupported." ,
79- old_onion_addr
80- ) ;
81- self . propagate_result_to_subscribers ( & node_id, Err ( Error :: InvalidSocketAddress ) ) ;
82- return Err ( Error :: InvalidSocketAddress ) ;
84+ self . logger,
85+ "Failed to resolve network address {:?}: Resolution of OnionV2 addresses is currently unsupported." ,
86+ old_onion_addr
87+ ) ;
88+ Err ( Error :: InvalidSocketAddress )
8389 } ,
8490 SocketAddress :: OnionV3 { .. } => {
8591 let proxy_config = self . tor_proxy_config . as_ref ( ) . ok_or_else ( || {
@@ -88,87 +94,113 @@ where
8894 "Failed to resolve network address {:?}: Tor usage is not configured." ,
8995 addr
9096 ) ;
91- self . propagate_result_to_subscribers (
92- & node_id,
93- Err ( Error :: InvalidSocketAddress ) ,
94- ) ;
9597 Error :: InvalidSocketAddress
9698 } ) ?;
97- let proxy_addr = proxy_config
98- . proxy_address
99- . to_socket_addrs ( )
100- . map_err ( |e| {
101- log_error ! (
102- self . logger,
103- "Failed to resolve Tor proxy network address {}: {}" ,
104- proxy_config. proxy_address,
105- e
106- ) ;
107- self . propagate_result_to_subscribers (
108- & node_id,
109- Err ( Error :: InvalidSocketAddress ) ,
110- ) ;
111- Error :: InvalidSocketAddress
112- } ) ?
113- . next ( )
114- . ok_or_else ( || {
115- log_error ! (
116- self . logger,
117- "Failed to resolve Tor proxy network address {}" ,
118- proxy_config. proxy_address
119- ) ;
120- self . propagate_result_to_subscribers (
121- & node_id,
122- Err ( Error :: InvalidSocketAddress ) ,
123- ) ;
124- Error :: InvalidSocketAddress
125- } ) ?;
126- let connection_future = lightning_net_tokio:: tor_connect_outbound (
127- Arc :: clone ( & self . peer_manager ) ,
128- node_id,
129- addr. clone ( ) ,
130- proxy_addr,
131- Arc :: clone ( & self . keys_manager ) ,
132- ) ;
133- self . await_connection ( connection_future, node_id, addr) . await
99+ let resolved_addrs: Vec < _ > =
100+ tokio:: net:: lookup_host ( proxy_config. proxy_address . to_string ( ) )
101+ . await
102+ . map_err ( |e| {
103+ log_error ! (
104+ self . logger,
105+ "Failed to resolve Tor proxy network address {}: {}" ,
106+ proxy_config. proxy_address,
107+ e
108+ ) ;
109+ Error :: InvalidSocketAddress
110+ } ) ?
111+ . collect ( ) ;
112+
113+ if resolved_addrs. is_empty ( ) {
114+ log_error ! (
115+ self . logger,
116+ "Failed to resolve Tor proxy network address {}" ,
117+ proxy_config. proxy_address
118+ ) ;
119+ return Err ( Error :: InvalidSocketAddress ) ;
120+ }
121+
122+ let mut res = Err ( Error :: ConnectionFailed ) ;
123+ let mut had_failures = false ;
124+ for proxy_addr in resolved_addrs {
125+ let connection_future = lightning_net_tokio:: tor_connect_outbound (
126+ Arc :: clone ( & self . peer_manager ) ,
127+ node_id,
128+ addr. clone ( ) ,
129+ proxy_addr,
130+ Arc :: clone ( & self . keys_manager ) ,
131+ ) ;
132+ res = self . await_connection ( connection_future, node_id, addr. clone ( ) ) . await ;
133+ if res. is_ok ( ) {
134+ if had_failures {
135+ log_info ! (
136+ self . logger,
137+ "Successfully connected to peer {}@{} via resolved proxy address {} after previous attempts failed." ,
138+ node_id, addr, proxy_addr
139+ ) ;
140+ }
141+ break ;
142+ }
143+ had_failures = true ;
144+ log_debug ! (
145+ self . logger,
146+ "Failed to connect to peer {}@{} via resolved proxy address {}." ,
147+ node_id,
148+ addr,
149+ proxy_addr
150+ ) ;
151+ }
152+ res
134153 } ,
135154 _ => {
136- let socket_addr = addr
137- . to_socket_addrs ( )
155+ let resolved_addrs : Vec < _ > = tokio :: net :: lookup_host ( addr. to_string ( ) )
156+ . await
138157 . map_err ( |e| {
139158 log_error ! (
140159 self . logger,
141160 "Failed to resolve network address {}: {}" ,
142161 addr,
143162 e
144163 ) ;
145- self . propagate_result_to_subscribers (
146- & node_id,
147- Err ( Error :: InvalidSocketAddress ) ,
148- ) ;
149164 Error :: InvalidSocketAddress
150165 } ) ?
151- . next ( )
152- . ok_or_else ( || {
153- log_error ! ( self . logger, "Failed to resolve network address {}" , addr) ;
154- self . propagate_result_to_subscribers (
155- & node_id,
156- Err ( Error :: InvalidSocketAddress ) ,
157- ) ;
158- Error :: InvalidSocketAddress
159- } ) ?;
160- let connection_future = lightning_net_tokio:: connect_outbound (
161- Arc :: clone ( & self . peer_manager ) ,
162- node_id,
163- socket_addr,
164- ) ;
165- self . await_connection ( connection_future, node_id, addr) . await
166- } ,
167- } ;
166+ . collect ( ) ;
168167
169- self . propagate_result_to_subscribers ( & node_id, res) ;
168+ if resolved_addrs. is_empty ( ) {
169+ log_error ! ( self . logger, "Failed to resolve network address {}" , addr) ;
170+ return Err ( Error :: InvalidSocketAddress ) ;
171+ }
170172
171- res
173+ let mut res = Err ( Error :: ConnectionFailed ) ;
174+ let mut had_failures = false ;
175+ for socket_addr in resolved_addrs {
176+ let connection_future = lightning_net_tokio:: connect_outbound (
177+ Arc :: clone ( & self . peer_manager ) ,
178+ node_id,
179+ socket_addr,
180+ ) ;
181+ res = self . await_connection ( connection_future, node_id, addr. clone ( ) ) . await ;
182+ if res. is_ok ( ) {
183+ if had_failures {
184+ log_info ! (
185+ self . logger,
186+ "Successfully connected to peer {}@{} via resolved address {} after previous attempts failed." ,
187+ node_id, addr, socket_addr
188+ ) ;
189+ }
190+ break ;
191+ }
192+ had_failures = true ;
193+ log_debug ! (
194+ self . logger,
195+ "Failed to connect to peer {}@{} via resolved address {}." ,
196+ node_id,
197+ addr,
198+ socket_addr
199+ ) ;
200+ }
201+ res
202+ } ,
203+ }
172204 }
173205
174206 async fn await_connection < F , CF > (
0 commit comments