Skip to content

Commit

Permalink
allow to listen and advertise on multiple SocketAddr
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderwiederin committed Nov 12, 2023
1 parent d955e62 commit 2f6efaf
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 44 deletions.
6 changes: 3 additions & 3 deletions bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ dictionary Config {
string storage_dir_path = "/tmp/ldk_node/";
string? log_dir_path = null;
Network network = "Bitcoin";
SocketAddress? listening_address = null;
sequence<SocketAddress>? listening_addresses = null;
u32 default_cltv_expiry_delta = 144;
u64 onchain_wallet_sync_interval_secs = 80;
u64 wallet_sync_interval_secs = 30;
Expand All @@ -29,7 +29,7 @@ interface Builder {
void set_gossip_source_rgs(string rgs_server_url);
void set_storage_dir_path(string storage_dir_path);
void set_network(Network network);
void set_listening_address(SocketAddress listening_address);
void set_listening_addresses(sequence<SocketAddress> listening_addresses);
[Throws=BuildError]
LDKNode build();
};
Expand All @@ -43,7 +43,7 @@ interface LDKNode {
Event wait_next_event();
void event_handled();
PublicKey node_id();
SocketAddress? listening_address();
sequence<SocketAddress>? listening_addresses();
[Throws=NodeError]
Address new_onchain_address();
[Throws=NodeError]
Expand Down
12 changes: 8 additions & 4 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,12 @@ impl NodeBuilder {
}

/// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
pub fn set_listening_address(&mut self, listening_address: SocketAddress) -> &mut Self {
self.config.listening_address = Some(listening_address);
pub fn set_listening_addresses(&mut self, listening_addresses: Vec<SocketAddress>) -> &mut Self {
if listening_addresses.len() > 100 {
panic!("Listening addresses can not exceed 100");
}

self.config.listening_addresses = Some(listening_addresses);
self
}

Expand Down Expand Up @@ -386,8 +390,8 @@ impl ArcedNodeBuilder {
}

/// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
pub fn set_listening_address(&self, listening_address: SocketAddress) {
self.inner.write().unwrap().set_listening_address(listening_address);
pub fn set_listening_addresses(&self, listening_addresses: Vec<SocketAddress>) {
self.inner.write().unwrap().set_listening_addresses(listening_addresses);
}

/// Sets the level at which [`Node`] will log messages.
Expand Down
61 changes: 30 additions & 31 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ use bitcoin::{Address, Txid};
use rand::Rng;

use std::default::Default;
use std::net::ToSocketAddrs;
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::{Arc, Mutex, RwLock};
use std::time::{Duration, Instant, SystemTime};

Expand Down Expand Up @@ -207,7 +207,7 @@ const WALLET_KEYS_SEED_LEN: usize = 64;
/// | `storage_dir_path` | /tmp/ldk_node/ |
/// | `log_dir_path` | None |
/// | `network` | Bitcoin |
/// | `listening_address` | None |
/// | `listening_addresses` | None |
/// | `default_cltv_expiry_delta` | 144 |
/// | `onchain_wallet_sync_interval_secs` | 80 |
/// | `wallet_sync_interval_secs` | 30 |
Expand All @@ -226,7 +226,7 @@ pub struct Config {
/// The used Bitcoin network.
pub network: Network,
/// The IP address and TCP port the node will listen on.
pub listening_address: Option<SocketAddress>,
pub listening_addresses: Option<Vec<SocketAddress>>,
/// The default CLTV expiry delta to be used for payments.
pub default_cltv_expiry_delta: u32,
/// The time in-between background sync attempts of the onchain wallet, in seconds.
Expand Down Expand Up @@ -264,7 +264,7 @@ impl Default for Config {
storage_dir_path: DEFAULT_STORAGE_DIR_PATH.to_string(),
log_dir_path: None,
network: DEFAULT_NETWORK,
listening_address: None,
listening_addresses: None,
default_cltv_expiry_delta: DEFAULT_CLTV_EXPIRY_DELTA,
onchain_wallet_sync_interval_secs: DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS,
wallet_sync_interval_secs: DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS,
Expand Down Expand Up @@ -490,38 +490,37 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
});
}

if let Some(listening_address) = &self.config.listening_address {
if let Some(listening_addresses) = &self.config.listening_addresses {
// Setup networking
let peer_manager_connection_handler = Arc::clone(&self.peer_manager);
let mut stop_listen = self.stop_receiver.clone();
let listening_address = listening_address.clone();
let listening_addresses = listening_addresses.clone();
let listening_logger = Arc::clone(&self.logger);

let bind_addr = listening_address
.to_socket_addrs()
.map_err(|_| {
log_error!(
self.logger,
"Unable to resolve listing address: {:?}",
listening_address
);
Error::InvalidSocketAddress
})?
.next()
.ok_or_else(|| {
log_error!(
self.logger,
"Unable to resolve listing address: {:?}",
listening_address
);
Error::InvalidSocketAddress
})?;
let collected_addrs: Vec<SocketAddr> = listening_addresses
.iter()
.flat_map(|socket_address| {
socket_address.to_socket_addrs().map_err(|_| {
log_error!(
self.logger,
"Unable to resolve listing address: {:?}",
socket_address
);
Error::InvalidSocketAddress
})
})
.flatten()
.collect::<Vec<SocketAddr>>();

assert!(!collected_addrs.is_empty());

let bind_addrs: Arc<[SocketAddr]> = collected_addrs.clone().into();

runtime.spawn(async move {
let listener =
tokio::net::TcpListener::bind(bind_addr).await
tokio::net::TcpListener::bind(&*bind_addrs).await
.unwrap_or_else(|e| {
log_error!(listening_logger, "Failed to bind to listen address/port - is something else already listening on it?: {}", e);
log_error!(listening_logger, "Failed to bind to listen addresses/ports - is something else already listening on it?: {}", e);
panic!(
"Failed to bind to listen address/port - is something else already listening on it?",
);
Expand Down Expand Up @@ -632,7 +631,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
}

let addresses =
bcast_config.listening_address.iter().cloned().collect();
bcast_config.listening_addresses.clone().unwrap();
bcast_pm.broadcast_node_announcement([0; 3], [0; 32], addresses);

let unix_time_secs = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs();
Expand Down Expand Up @@ -781,9 +780,9 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
self.channel_manager.get_our_node_id()
}

/// Returns our own listening address.
pub fn listening_address(&self) -> Option<SocketAddress> {
self.config.listening_address.clone()
/// Returns our own listening addresses.
pub fn listening_addresses(&self) -> Option<Vec<SocketAddress>> {
self.config.listening_addresses.clone()
}

/// Retrieve a new on-chain/funding address.
Expand Down
4 changes: 2 additions & 2 deletions src/test/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ fn do_channel_full_cycle<K: KVStore + Sync + Send>(
node_a
.connect_open_channel(
node_b.node_id(),
node_b.listening_address().unwrap().into(),
node_b.listening_addresses().unwrap().first().unwrap().clone(),
funding_amount_sat,
Some(push_msat),
None,
Expand Down Expand Up @@ -332,7 +332,7 @@ fn channel_open_fails_when_funds_insufficient() {
Err(Error::InsufficientFunds),
node_a.connect_open_channel(
node_b.node_id(),
node_b.listening_address().unwrap().into(),
node_b.listening_addresses().unwrap().first().unwrap().clone(),
120000,
None,
None,
Expand Down
23 changes: 19 additions & 4 deletions src/test/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use std::path::PathBuf;
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
use lightning::ln::msgs::SocketAddress;

macro_rules! expect_event {
($node: expr, $event_type: ident) => {{
Expand Down Expand Up @@ -134,6 +135,21 @@ pub fn random_port() -> u16 {
rng.gen_range(5000..65535)
}

pub fn random_listening_addresses() -> Vec<SocketAddress> {
let mut rng = thread_rng();
let num_addresses = rng.gen_range(1..=3);

let listening_addresses: Vec<SocketAddress> = (0..num_addresses)
.map(|_| {
let rand_port = random_port();
println!("Setting random LDK listening port: {}", rand_port);
format!("127.0.0.1:{}", rand_port).parse().unwrap()
})
.collect();

listening_addresses
}

pub fn random_config() -> Config {
let mut config = Config::default();

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

let rand_port = random_port();
println!("Setting random LDK listening port: {}", rand_port);
let listening_address_str = format!("127.0.0.1:{}", rand_port);
config.listening_address = Some(listening_address_str.parse().unwrap());
let rand_listening_addresses = random_listening_addresses();
println!("Setting random LDK listening addresses: {:?}", rand_listening_addresses);
config.listening_addresses = Some(rand_listening_addresses);

config.log_level = Level::Trace;

Expand Down

0 comments on commit 2f6efaf

Please sign in to comment.