1use discv5::{enr, ConfigBuilder, Discv5, ListenConfig};
2use std::{
3 convert::TryInto,
4 net::{IpAddr, SocketAddrV4, SocketAddrV6},
5 process::exit,
6 sync::Arc,
7 time::Duration,
8};
9
10pub mod services;
12
13pub mod bootstrap;
15
16pub mod enr_build;
18
19pub mod keys;
21
22pub mod command;
24pub use command::*;
25
26pub async fn run(server: &Server) {
28 let peer_update_min = server.peer_update_min;
30
31 let enr_key = keys::generate(server).unwrap();
33 let enr = enr_build::build(server, &enr_key).unwrap();
34
35 let connect_enr = server.enr.as_ref().map(|enr| {
36 enr.parse::<enr::Enr<enr::CombinedKey>>()
37 .expect("Invalid base64 encoded ENR")
38 });
39
40 let mut ipv4_address = None;
41 let mut ipv6_address = None;
42 for address in server.listen_addresses.split(',') {
43 match address
44 .parse::<IpAddr>()
45 .expect("Invalid listening address")
46 {
47 IpAddr::V4(ip) => ipv4_address = Some(ip),
48 IpAddr::V6(ip) => ipv6_address = Some(ip),
49 }
50 }
51
52 let listen_port = server.listen_port;
53 let listen_port_v6 = server.listen_port_v6;
54
55 let listen_config = ListenConfig::from_two_sockets(
56 ipv4_address.map(|v| SocketAddrV4::new(v, listen_port)),
57 ipv6_address.map(|v| SocketAddrV6::new(v, listen_port_v6.unwrap_or(listen_port), 0, 0)),
58 );
59
60 log::info!("Server listening on {:?}", listen_config);
61 let config = ConfigBuilder::new(listen_config)
63 .request_timeout(Duration::from_secs(3))
64 .vote_duration(Duration::from_secs(120))
65 .enr_peer_update_min(peer_update_min.try_into().unwrap())
66 .build();
67 let mut discv5 = Discv5::new(enr, enr_key, config).unwrap();
68
69 if !server.no_search {
71 if let Some(connect_enr) = connect_enr {
72 log::info!(
73 "Connecting to ENR. ip: {:?}, udp_port: {:?}, tcp_port: {:?}",
74 connect_enr.ip4(),
75 connect_enr.udp4(),
76 connect_enr.tcp4()
77 );
78 if let Err(e) = discv5.add_enr(connect_enr) {
79 log::warn!("ENR not added: {:?}", e);
80 }
81 }
82 }
83
84 if bootstrap::boostrap(&mut discv5, server.bootstrap.clone())
86 .await
87 .is_err()
88 {
89 log::error!("Failed to bootstrap discv5 server with bootstrap file")
90 }
91
92 discv5
94 .start()
95 .await
96 .expect("Should be able to start the server");
97
98 let server_ref = Arc::new(discv5);
99 if server.stats > 0 {
100 services::stats::run(Arc::clone(&server_ref), None, server.stats);
101 }
102
103 if server.no_search {
104 log::info!("Running without query service, press CTRL-C to exit.");
105 let _ = tokio::signal::ctrl_c().await;
106 exit(0);
107 }
108
109 match server.service {
111 ServerSubcommand::Query => {
112 log::info!("Query service running...");
113 services::query::run(server_ref, Duration::from_secs(server.break_time)).await;
114 }
115 ServerSubcommand::Events => {
116 log::info!("Events service running...");
117 services::events::run(server_ref).await;
118 }
119 }
120}