use discv5::{enr, enr::CombinedKey, Discv5, Discv5Config, Discv5Event};
use std::net::{Ipv4Addr, SocketAddr};
#[tokio::main]
async fn main() {
let filter_layer = tracing_subscriber::EnvFilter::try_from_default_env()
.or_else(|_| tracing_subscriber::EnvFilter::try_new("info"))
.unwrap();
let _ = tracing_subscriber::fmt()
.with_env_filter(filter_layer)
.try_init();
let address = std::env::args()
.nth(1)
.map(|addr| addr.parse::<Ipv4Addr>().unwrap());
let port = {
if let Some(udp_port) = std::env::args().nth(2) {
udp_port.parse().unwrap()
} else {
9000
}
};
let listen_addr = "0.0.0.0:9000".parse::<SocketAddr>().unwrap();
let enr_key = CombinedKey::generate_secp256k1();
let enr = {
let mut builder = enr::EnrBuilder::new("v4");
if let Some(external_address) = address {
builder.ip4(external_address);
}
if std::env::args().nth(2).is_some() {
builder.udp4(port);
}
builder.build(&enr_key).unwrap()
};
println!("Node Id: {}", enr.node_id());
if enr.udp4_socket().is_some() {
println!("Base64 ENR: {}", enr.to_base64());
println!(
"IP: {}, UDP_PORT:{}",
enr.ip4().unwrap(),
enr.udp4().unwrap()
);
} else {
println!("ENR is not printed as no IP:PORT was specified");
}
let config = Discv5Config::default();
let mut discv5 = Discv5::new(enr, enr_key, config).unwrap();
if let Some(base64_enr) = std::env::args().nth(3) {
match base64_enr.parse::<enr::Enr<enr::CombinedKey>>() {
Ok(enr) => {
println!(
"ENR Read. ip: {:?}, udp_port {:?}, tcp_port: {:?}",
enr.ip4(),
enr.udp4(),
enr.tcp4()
);
if let Err(e) = discv5.add_enr(enr) {
println!("ENR was not added: {}", e);
}
}
Err(e) => panic!("Decoding ENR failed: {}", e),
}
}
discv5.start(listen_addr).await.unwrap();
println!("Server started");
let mut event_stream = discv5.event_stream().await.unwrap();
loop {
match event_stream.recv().await {
Some(Discv5Event::SocketUpdated(addr)) => {
println!("Nodes ENR socket address has been updated to: {:?}", addr);
}
Some(Discv5Event::Discovered(enr)) => {
println!("A peer has been discovered: {}", enr.node_id());
}
_ => {}
}
}
}