use std::collections::HashMap;
use std::sync::Arc;
use ntk_neighborhood::{
IcmpRttProbe, LocalNic, NeighborhoodConfig, NeighborhoodRpcHandler, NeighborhoodTiming, NodeId,
};
use ntk_netlink::RealNetlink;
use ntk_rpc::{TcpServer, UdpBroadcaster};
use tokio::task::JoinSet;
use tokio_util::sync::CancellationToken;
use crate::kernel::config::NtkdConfig;
use crate::node::ip_route::RealIpRouteManager;
use crate::node::lifecycle::{
self, NodeInputs, StartedNode, TcpDialer, linklocal_allocator, synthetic_mac,
};
use crate::node::peers::PeerLinks;
use crate::node::registry::LinkRegistry;
use crate::node::stubs::NeighborhoodStubFactoryAdapter;
const MAX_ARCS: usize = 64;
pub async fn start(
config: NtkdConfig,
nics: &[String],
tasks: &mut JoinSet<()>,
cancel: CancellationToken,
) -> anyhow::Result<StartedNode<RealNetlink>> {
let registry = Arc::new(LinkRegistry::new());
let links = Arc::new(PeerLinks::new());
let mut broadcasters = HashMap::new();
for nic in nics {
let broadcaster = Arc::new(UdpBroadcaster::bind(Some(nic), config.port(), 1 << 16)?);
broadcasters.insert(nic.clone(), broadcaster);
}
let neighborhood_stub_factory = Arc::new(NeighborhoodStubFactoryAdapter {
broadcasters: broadcasters.clone(),
links: links.clone(),
registry: registry.clone(),
});
let my_id = NodeId::generate();
let signing_key = match config.node_key_path() {
Some(path) => Some(crate::node::andna_key::load_or_generate(path)?),
None => None,
};
let neighborhood_config = NeighborhoodConfig {
my_id,
max_arcs: MAX_ARCS,
kernel: RealNetlink::new()?,
stub_factory: neighborhood_stub_factory,
ip_route_manager: Arc::new(RealIpRouteManager {
kernel: RealNetlink::new()?,
}),
rtt_probe: Arc::new(IcmpRttProbe),
timing: NeighborhoodTiming::default(),
new_linklocal_address: linklocal_allocator(my_id),
signing_key,
require_auth: config.require_auth(),
};
let (neighborhood, neighborhood_join) =
ntk_neighborhood::Manager::spawn(neighborhood_config, cancel.child_token());
tasks.spawn(async move {
let _ = neighborhood_join.await;
});
for nic in nics {
neighborhood
.start_monitor(LocalNic {
dev: nic.clone(),
mac: synthetic_mac(nic, my_id),
})
.await?;
}
let routing_kernel = Arc::new(RealNetlink::new()?);
let started = lifecycle::run(
NodeInputs {
config: config.clone(),
neighborhood: neighborhood.clone(),
registry,
links,
routing_kernel,
dialer: Arc::new(TcpDialer::default()),
initial_position: None,
preformed: None,
my_id,
},
tasks,
cancel.clone(),
)
.await?;
let server = TcpServer::bind(format!("0.0.0.0:{}", config.port()).parse()?, 1 << 20).await?;
let dispatcher = started.dispatcher.clone();
let server_cancel = cancel.child_token();
tasks.spawn(async move {
server.serve(dispatcher, server_cancel).await;
});
for (dev, broadcaster) in broadcasters {
let handler = Arc::new(NeighborhoodRpcHandler::for_broadcast(
neighborhood.clone(),
dev,
));
let broadcast_cancel = cancel.child_token();
tasks.spawn(async move {
ntk_neighborhood::serve_broadcast(broadcaster, handler, broadcast_cancel).await;
});
}
Ok(started)
}