diff --git a/hyperswarm-bootstrap/Cargo.toml b/hyperswarm-bootstrap/Cargo.toml index c49799c..d80d2ff 100644 --- a/hyperswarm-bootstrap/Cargo.toml +++ b/hyperswarm-bootstrap/Cargo.toml @@ -10,4 +10,6 @@ edition = "2018" hyperswarm = { path = "..", default-features = false } async-std = { version = "1.9.0", features = ["unstable"] } env_logger = "0.8.3" -clap = "3.0.0-beta.2" +log = "0.4.14" +anyhow = "1.0.39" +clap = { version = "3.1.7", features = ["derive"] } diff --git a/hyperswarm-bootstrap/README.md b/hyperswarm-bootstrap/README.md new file mode 100644 index 0000000..477b8ee --- /dev/null +++ b/hyperswarm-bootstrap/README.md @@ -0,0 +1,17 @@ +# hyperswarm-bootstrap + +Simple binary to run a bootstrap node. + +``` +$ cargo run -- --help +hyperswarm-bootstrap +Run a Hyperswarm bootstrap node + +USAGE: + hyperswarm-bootstrap [OPTIONS] + +OPTIONS: + -a, --address
Local address to bind bootstrap node on [default: 0.0.0.0:49737] + -b, --bootstrap Bootstrap addresses + -h, --help Print help information +``` diff --git a/hyperswarm-bootstrap/src/main.rs b/hyperswarm-bootstrap/src/main.rs index c61fa53..7724963 100644 --- a/hyperswarm-bootstrap/src/main.rs +++ b/hyperswarm-bootstrap/src/main.rs @@ -1,31 +1,80 @@ +use anyhow::Context; use async_std::task; -use clap::Clap; +use clap::Parser; +use log::*; use std::io; -use std::net::SocketAddr; +use std::net::{SocketAddr, ToSocketAddrs}; -use hyperswarm::run_bootstrap_node; +use hyperswarm::{BootstrapNode, DhtConfig}; -/// Options for the storage daemon -#[derive(Clap, Debug)] +/// Run a Hyperswarm bootstrap node. +#[derive(Parser, Debug)] struct Options { /// Local address to bind bootstrap node on. - #[clap(short, long)] - address: Option, + #[clap(short, long, default_value = "0.0.0.0:49737")] + address: SocketAddr, /// Bootstrap addresses #[clap(short, long)] - bootstrap: Vec, + bootstrap: Vec, } fn main() -> io::Result<()> { env_logger::init(); - task::block_on(async_main()) + match task::block_on(async_main()) { + Err(e) => { + debug!("{:?}", e); + eprintln!("Error: {}", e); + std::process::exit(1); + } + Ok(()) => Ok(()), + } } -async fn async_main() -> io::Result<()> { +async fn async_main() -> anyhow::Result<()> { let opts: Options = Options::parse(); - let (addr, task) = run_bootstrap_node(opts.address).await?; - println!("listening on {}", addr); + + let config = DhtConfig::default() + .set_bootstrap_nodes(&opts.bootstrap[..]) + .set_ephemeral(false); + + let mut config = if opts.bootstrap.len() > 0 { + let mut addrs = vec![]; + for addr in opts.bootstrap.iter() { + for addr in addr + .to_socket_addrs() + .with_context(|| format!("Invalid socket address \"{}\"", addr))? + { + if addr.is_ipv4() { + addrs.push(addr); + } + } + } + config.set_bootstrap_nodes(&addrs[..]) + } else { + config + }; + + let bootstrap_addrs: Vec = config + .bootstrap_nodes() + .map(|v| v.clone().iter().map(|s| s.to_string()).collect()) + .unwrap_or_else(|| { + hyperswarm::DEFAULT_BOOTSTRAP + .to_vec() + .iter() + .map(|s| s.to_string()) + .collect() + }); + + let node = BootstrapNode::new(config, Some(opts.address)); + let (addr, task) = node.run().await?; + + println!("DHT listening on {}", addr); + debug!( + "Bootstrapping DHT via nodes: {}", + bootstrap_addrs.join(", ") + ); + task.await?; Ok(()) }