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