Skip to content

Commit 6d40944

Browse files
allow to listen and advertise on multiple SocketAddr
1 parent f89877e commit 6d40944

File tree

7 files changed

+66
-44
lines changed

7 files changed

+66
-44
lines changed

bindings/kotlin/ldk-node-android/lib/src/androidTest/kotlin/org/lightningdevkit/ldknode/AndroidLibTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ class AndroidLibTest {
2626
val listenAddress1 = "127.0.0.1:2323"
2727
val listenAddress2 = "127.0.0.1:2324"
2828

29-
val config1 = Config(tmpDir1, network, listenAddress1, 2048u)
30-
val config2 = Config(tmpDir2, network, listenAddress2, 2048u)
29+
val config1 = Config(tmpDir1, network, listOf(listenAddress1), 2048u)
30+
val config2 = Config(tmpDir2, network, listOf(listenAddress2), 2048u)
3131

3232
val builder1 = Builder.fromConfig(config1)
3333
val builder2 = Builder.fromConfig(config2)

bindings/kotlin/ldk-node-jvm/lib/src/test/kotlin/org/lightningdevkit/ldknode/LibraryTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,15 @@ class LibraryTest {
116116

117117
val config1 = Config()
118118
config1.storageDirPath = tmpDir1
119-
config1.listeningAddress = listenAddress1
119+
config1.listeningAddresses = listOf(listenAddress1)
120120
config1.network = Network.REGTEST
121121
config1.logLevel = LogLevel.TRACE
122122

123123
println("Config 1: $config1")
124124

125125
val config2 = Config()
126126
config2.storageDirPath = tmpDir2
127-
config2.listeningAddress = listenAddress2
127+
config2.listeningAddresses = listOf(listenAddress2)
128128
config2.network = Network.REGTEST
129129
config2.logLevel = LogLevel.TRACE
130130
println("Config 2: $config2")

bindings/ldk_node.udl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ dictionary Config {
66
string storage_dir_path = "/tmp/ldk_node/";
77
string? log_dir_path = null;
88
Network network = "Bitcoin";
9-
SocketAddress? listening_address = null;
9+
sequence<SocketAddress>? listening_addresses = null;
1010
u32 default_cltv_expiry_delta = 144;
1111
u64 onchain_wallet_sync_interval_secs = 80;
1212
u64 wallet_sync_interval_secs = 30;
@@ -29,7 +29,8 @@ interface Builder {
2929
void set_gossip_source_rgs(string rgs_server_url);
3030
void set_storage_dir_path(string storage_dir_path);
3131
void set_network(Network network);
32-
void set_listening_address(SocketAddress listening_address);
32+
[Throws=BuildError]
33+
void set_listening_addresses(sequence<SocketAddress> listening_addresses);
3334
[Throws=BuildError]
3435
LDKNode build();
3536
};
@@ -43,7 +44,7 @@ interface LDKNode {
4344
Event wait_next_event();
4445
void event_handled();
4546
PublicKey node_id();
46-
SocketAddress? listening_address();
47+
sequence<SocketAddress>? listening_addresses();
4748
[Throws=NodeError]
4849
Address new_onchain_address();
4950
[Throws=NodeError]
@@ -133,6 +134,7 @@ enum BuildError {
133134
"InvalidSeedFile",
134135
"InvalidSystemTime",
135136
"InvalidChannelMonitor",
137+
"InvalidListeningAddresses",
136138
"ReadFailed",
137139
"WriteFailed",
138140
"StoragePathAccessFailed",

src/builder.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ pub enum BuildError {
9090
InvalidSystemTime,
9191
/// The a read channel monitor is invalid.
9292
InvalidChannelMonitor,
93+
/// The given listening addresses are invalid, e.g. too many were passed.
94+
InvalidListeningAddresses,
9395
/// We failed to read data from the [`KVStore`].
9496
ReadFailed,
9597
/// We failed to write data to the [`KVStore`].
@@ -121,6 +123,7 @@ impl fmt::Display for BuildError {
121123
Self::KVStoreSetupFailed => write!(f, "Failed to setup KVStore."),
122124
Self::WalletSetupFailed => write!(f, "Failed to setup onchain wallet."),
123125
Self::LoggerSetupFailed => write!(f, "Failed to setup the logger."),
126+
Self::InvalidListeningAddresses => write!(f, "Given listening addresses are invalid."),
124127
}
125128
}
126129
}
@@ -231,9 +234,15 @@ impl NodeBuilder {
231234
}
232235

233236
/// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
234-
pub fn set_listening_address(&mut self, listening_address: SocketAddress) -> &mut Self {
235-
self.config.listening_address = Some(listening_address);
236-
self
237+
pub fn set_listening_addresses(
238+
&mut self, listening_addresses: Vec<SocketAddress>,
239+
) -> Result<&mut Self, BuildError> {
240+
if listening_addresses.len() > 100 {
241+
return Err(BuildError::InvalidListeningAddresses);
242+
}
243+
244+
self.config.listening_addresses = Some(listening_addresses);
245+
Ok(self)
237246
}
238247

239248
/// Sets the level at which [`Node`] will log messages.
@@ -386,8 +395,10 @@ impl ArcedNodeBuilder {
386395
}
387396

388397
/// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
389-
pub fn set_listening_address(&self, listening_address: SocketAddress) {
390-
self.inner.write().unwrap().set_listening_address(listening_address);
398+
pub fn set_listening_addresses(
399+
&self, listening_addresses: Vec<SocketAddress>,
400+
) -> Result<(), BuildError> {
401+
self.inner.write().unwrap().set_listening_addresses(listening_addresses).map(|_| ())
391402
}
392403

393404
/// Sets the level at which [`Node`] will log messages.

src/lib.rs

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ const WALLET_KEYS_SEED_LEN: usize = 64;
207207
/// | `storage_dir_path` | /tmp/ldk_node/ |
208208
/// | `log_dir_path` | None |
209209
/// | `network` | Bitcoin |
210-
/// | `listening_address` | None |
210+
/// | `listening_addresses` | None |
211211
/// | `default_cltv_expiry_delta` | 144 |
212212
/// | `onchain_wallet_sync_interval_secs` | 80 |
213213
/// | `wallet_sync_interval_secs` | 30 |
@@ -225,8 +225,8 @@ pub struct Config {
225225
pub log_dir_path: Option<String>,
226226
/// The used Bitcoin network.
227227
pub network: Network,
228-
/// The IP address and TCP port the node will listen on.
229-
pub listening_address: Option<SocketAddress>,
228+
/// The addresses on which the node will listen for incoming connections.
229+
pub listening_addresses: Option<Vec<SocketAddress>>,
230230
/// The default CLTV expiry delta to be used for payments.
231231
pub default_cltv_expiry_delta: u32,
232232
/// The time in-between background sync attempts of the onchain wallet, in seconds.
@@ -264,7 +264,7 @@ impl Default for Config {
264264
storage_dir_path: DEFAULT_STORAGE_DIR_PATH.to_string(),
265265
log_dir_path: None,
266266
network: DEFAULT_NETWORK,
267-
listening_address: None,
267+
listening_addresses: None,
268268
default_cltv_expiry_delta: DEFAULT_CLTV_EXPIRY_DELTA,
269269
onchain_wallet_sync_interval_secs: DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS,
270270
wallet_sync_interval_secs: DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS,
@@ -490,38 +490,34 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
490490
});
491491
}
492492

493-
if let Some(listening_address) = &self.config.listening_address {
493+
if let Some(listening_addresses) = &self.config.listening_addresses {
494494
// Setup networking
495495
let peer_manager_connection_handler = Arc::clone(&self.peer_manager);
496496
let mut stop_listen = self.stop_receiver.clone();
497-
let listening_address = listening_address.clone();
497+
let listening_addresses = listening_addresses.clone();
498498
let listening_logger = Arc::clone(&self.logger);
499499

500-
let bind_addr = listening_address
501-
.to_socket_addrs()
502-
.map_err(|_| {
503-
log_error!(
504-
self.logger,
505-
"Unable to resolve listing address: {:?}",
506-
listening_address
507-
);
508-
Error::InvalidSocketAddress
509-
})?
510-
.next()
511-
.ok_or_else(|| {
500+
let mut bind_addrs = Vec::with_capacity(listening_addresses.len());
501+
502+
for listening_addr in listening_addresses {
503+
let resolved_address = listening_addr.to_socket_addrs().map_err(|e| {
512504
log_error!(
513505
self.logger,
514-
"Unable to resolve listing address: {:?}",
515-
listening_address
506+
"Unable to resolve listening address: {:?}. Error details: {}",
507+
listening_addr,
508+
e,
516509
);
517510
Error::InvalidSocketAddress
518511
})?;
519512

513+
bind_addrs.extend(resolved_address);
514+
}
515+
520516
runtime.spawn(async move {
521517
let listener =
522-
tokio::net::TcpListener::bind(bind_addr).await
518+
tokio::net::TcpListener::bind(&*bind_addrs).await
523519
.unwrap_or_else(|e| {
524-
log_error!(listening_logger, "Failed to bind to listen address/port - is something else already listening on it?: {}", e);
520+
log_error!(listening_logger, "Failed to bind to listen addresses/ports - is something else already listening on it?: {}", e);
525521
panic!(
526522
"Failed to bind to listen address/port - is something else already listening on it?",
527523
);
@@ -632,7 +628,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
632628
}
633629

634630
let addresses =
635-
bcast_config.listening_address.iter().cloned().collect();
631+
bcast_config.listening_addresses.clone().unwrap_or(Vec::new());
636632
bcast_pm.broadcast_node_announcement([0; 3], [0; 32], addresses);
637633

638634
let unix_time_secs = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs();
@@ -781,9 +777,9 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
781777
self.channel_manager.get_our_node_id()
782778
}
783779

784-
/// Returns our own listening address.
785-
pub fn listening_address(&self) -> Option<SocketAddress> {
786-
self.config.listening_address.clone()
780+
/// Returns our own listening addresses.
781+
pub fn listening_addresses(&self) -> Option<Vec<SocketAddress>> {
782+
self.config.listening_addresses.clone()
787783
}
788784

789785
/// Retrieve a new on-chain/funding address.

src/test/functional_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ fn do_channel_full_cycle<K: KVStore + Sync + Send>(
7777
node_a
7878
.connect_open_channel(
7979
node_b.node_id(),
80-
node_b.listening_address().unwrap().into(),
80+
node_b.listening_addresses().unwrap().first().unwrap().clone(),
8181
funding_amount_sat,
8282
Some(push_msat),
8383
None,
@@ -332,7 +332,7 @@ fn channel_open_fails_when_funds_insufficient() {
332332
Err(Error::InsufficientFunds),
333333
node_a.connect_open_channel(
334334
node_b.node_id(),
335-
node_b.listening_address().unwrap().into(),
335+
node_b.listening_addresses().unwrap().first().unwrap().clone(),
336336
120000,
337337
None,
338338
None,

src/test/utils.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use electrum_client::ElectrumApi;
1212

1313
use regex;
1414

15+
use lightning::ln::msgs::SocketAddress;
1516
use rand::distributions::Alphanumeric;
1617
use rand::{thread_rng, Rng};
1718
use std::collections::HashMap;
@@ -134,6 +135,19 @@ pub fn random_port() -> u16 {
134135
rng.gen_range(5000..65535)
135136
}
136137

138+
pub fn random_listening_addresses() -> Vec<SocketAddress> {
139+
let num_addresses = 2;
140+
let mut listening_addresses = Vec::with_capacity(num_addresses);
141+
142+
for _ in 0..num_addresses {
143+
let rand_port = random_port();
144+
let address: SocketAddress = format!("127.0.0.1:{}", rand_port).parse().unwrap();
145+
listening_addresses.push(address);
146+
}
147+
148+
listening_addresses
149+
}
150+
137151
pub fn random_config() -> Config {
138152
let mut config = Config::default();
139153

@@ -144,10 +158,9 @@ pub fn random_config() -> Config {
144158
println!("Setting random LDK storage dir: {}", rand_dir.display());
145159
config.storage_dir_path = rand_dir.to_str().unwrap().to_owned();
146160

147-
let rand_port = random_port();
148-
println!("Setting random LDK listening port: {}", rand_port);
149-
let listening_address_str = format!("127.0.0.1:{}", rand_port);
150-
config.listening_address = Some(listening_address_str.parse().unwrap());
161+
let rand_listening_addresses = random_listening_addresses();
162+
println!("Setting random LDK listening addresses: {:?}", rand_listening_addresses);
163+
config.listening_addresses = Some(rand_listening_addresses);
151164

152165
config.log_level = Level::Trace;
153166

0 commit comments

Comments
 (0)