use {
super::{Network, NetworkId, error::Error},
crate::{
SecretKey,
discovery::{self, Discovery},
groups::{self, Groups},
network::{LocalNode, ProtocolProvider},
streams::{self, Streams},
},
core::net::SocketAddr,
derive_builder::Builder,
iroh::{
Endpoint,
address_lookup::{MemoryLookup, mdns::MdnsAddressLookupBuilder},
endpoint::presets::N0,
protocol::Router,
},
std::collections::BTreeSet,
};
#[derive(Debug, Clone, Builder)]
#[builder(
pattern = "owned",
name = NetworkBuilder,
setter(prefix = with),
build_fn(private, name = compile)
)]
pub struct NetworkConfig {
#[builder(setter(into))]
pub network_id: NetworkId,
#[builder(default = "iroh::RelayMode::Default")]
pub relay_mode: iroh::RelayMode,
#[builder(default = "false")]
pub mdns_discovery: bool,
#[builder(setter(into), default = "BTreeSet::new()")]
pub addresses: BTreeSet<SocketAddr>,
#[builder(setter(into), default = "SecretKey::generate(&mut rand::rng())")]
pub secret_key: SecretKey,
#[builder(default = "discovery::Config::builder()")]
pub discovery: discovery::ConfigBuilder,
#[builder(default = "streams::Config::builder()")]
pub streams: streams::ConfigBuilder,
#[builder(default = "groups::Config::builder()")]
pub groups: groups::ConfigBuilder,
}
impl NetworkBuilder {
pub async fn build(self) -> Result<Network, Error> {
let compiled = self.compile().map_err(|_| Error::MissingNetworkId)?;
let endpoint = compiled.bind_endpoint().await?;
let local = LocalNode::new(compiled.network_id, endpoint);
let mut protocols = Router::builder(local.endpoint().clone());
let config = compiled.discovery.build()?;
let discovery = Discovery::new(local.clone(), config);
protocols = discovery.install(protocols);
let config = compiled.streams.build()?;
let streams = Streams::new(local.clone(), &discovery, config);
protocols = streams.install(protocols);
let config = compiled.groups.build()?;
let groups = Groups::new(local.clone(), &discovery, config);
protocols = groups.install(protocols);
let router = protocols.spawn();
local.mark_ready();
local.online().await;
Ok(Network {
local,
discovery,
streams,
groups,
router,
})
}
}
impl NetworkConfig {
async fn bind_endpoint(&self) -> Result<Endpoint, Error> {
let mut endpoint_builder = Endpoint::builder(N0)
.secret_key(self.secret_key.clone())
.relay_mode(self.relay_mode.clone())
.address_lookup(MemoryLookup::new());
if self.mdns_discovery {
endpoint_builder =
endpoint_builder.address_lookup(MdnsAddressLookupBuilder::default());
}
for addr in &self.addresses {
endpoint_builder = endpoint_builder.bind_addr(*addr)?;
}
Ok(endpoint_builder.bind().await?)
}
}