|
|
@ -5,7 +5,8 @@ use std::collections::{HashMap, HashSet}; |
|
|
|
use std::io; |
|
|
|
use std::io; |
|
|
|
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, ToSocketAddrs, UdpSocket}; |
|
|
|
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, ToSocketAddrs, UdpSocket}; |
|
|
|
use std::ops::Deref; |
|
|
|
use std::ops::Deref; |
|
|
|
use std::time::Instant; |
|
|
|
use std::sync::atomic::{AtomicBool, Ordering}; |
|
|
|
|
|
|
|
use std::time::{Duration, Instant}; |
|
|
|
|
|
|
|
|
|
|
|
use blake2b_simd::Params; |
|
|
|
use blake2b_simd::Params; |
|
|
|
use fastrand::Rng; |
|
|
|
use fastrand::Rng; |
|
|
@ -97,7 +98,7 @@ impl Counter { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct MasterServer { |
|
|
|
pub struct MasterServer { |
|
|
|
sock: UdpSocket, |
|
|
|
sock: UdpSocket, |
|
|
|
challenges: HashMap<SocketAddrV4, Entry<u32>>, |
|
|
|
challenges: HashMap<SocketAddrV4, Entry<u32>>, |
|
|
|
challenges_counter: Counter, |
|
|
|
challenges_counter: Counter, |
|
|
@ -137,38 +138,36 @@ where |
|
|
|
Ok(None) |
|
|
|
Ok(None) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl MasterServer { |
|
|
|
fn resolve_update_addr(cfg: &Config, local_addr: SocketAddr) -> SocketAddrV4 { |
|
|
|
fn new(cfg: Config) -> Result<Self, Error> { |
|
|
|
if let Some(s) = cfg.client.update_addr.as_deref() { |
|
|
|
let addr = SocketAddr::new(cfg.server.ip, cfg.server.port); |
|
|
|
let addr = if !s.contains(':') { |
|
|
|
info!("Listen address: {}", addr); |
|
|
|
format!("{}:{}", s, local_addr.port()) |
|
|
|
let sock = UdpSocket::bind(addr).map_err(Error::BindSocket)?; |
|
|
|
} else { |
|
|
|
|
|
|
|
s.to_owned() |
|
|
|
let update_addr = { |
|
|
|
}; |
|
|
|
let mut addr = None; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(update_addr) = cfg.client.update_addr { |
|
|
|
match resolve_socket_addr(&addr) { |
|
|
|
addr = match resolve_socket_addr(&*update_addr) { |
|
|
|
Ok(Some(x)) => return x, |
|
|
|
Ok(None) => { |
|
|
|
Ok(None) => error!("Update address: failed to resolve IPv4 for \"{}\"", addr), |
|
|
|
error!( |
|
|
|
Err(e) => error!("Update address: {}", e), |
|
|
|
"update address: failed to resolve IPv4 for \"{}\"", |
|
|
|
|
|
|
|
update_addr |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
None |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
Err(e) => { |
|
|
|
|
|
|
|
error!("update address: {}", e); |
|
|
|
|
|
|
|
None |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
Ok(addr) => addr, |
|
|
|
|
|
|
|
|
|
|
|
match local_addr { |
|
|
|
|
|
|
|
SocketAddr::V4(x) => x, |
|
|
|
|
|
|
|
SocketAddr::V6(_) => todo!(), |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// fallback to local address
|
|
|
|
impl MasterServer { |
|
|
|
addr.unwrap_or_else(|| match sock.local_addr().unwrap() { |
|
|
|
pub fn new(cfg: Config) -> Result<Self, Error> { |
|
|
|
SocketAddr::V4(a) => a, |
|
|
|
let addr = SocketAddr::new(cfg.server.ip, cfg.server.port); |
|
|
|
_ => todo!(), |
|
|
|
info!("Listen address: {}", addr); |
|
|
|
}) |
|
|
|
let sock = UdpSocket::bind(addr).map_err(Error::BindSocket)?; |
|
|
|
}; |
|
|
|
// make socket interruptable by singals
|
|
|
|
|
|
|
|
sock.set_read_timeout(Some(Duration::from_secs(u32::MAX as u64)))?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let update_addr = resolve_update_addr(&cfg, addr); |
|
|
|
|
|
|
|
|
|
|
|
Ok(Self { |
|
|
|
Ok(Self { |
|
|
|
sock, |
|
|
|
sock, |
|
|
@ -193,10 +192,40 @@ impl MasterServer { |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn run(&mut self) -> Result<(), Error> { |
|
|
|
pub fn update_config(&mut self, cfg: Config) -> Result<(), Error> { |
|
|
|
|
|
|
|
let local_addr = self.sock.local_addr()?; |
|
|
|
|
|
|
|
let addr = SocketAddr::new(cfg.server.ip, cfg.server.port); |
|
|
|
|
|
|
|
if local_addr != addr { |
|
|
|
|
|
|
|
info!("Listen address: {}", addr); |
|
|
|
|
|
|
|
self.sock = UdpSocket::bind(addr).map_err(Error::BindSocket)?; |
|
|
|
|
|
|
|
// make socket interruptable by singals
|
|
|
|
|
|
|
|
self.sock |
|
|
|
|
|
|
|
.set_read_timeout(Some(Duration::from_secs(u32::MAX as u64)))?; |
|
|
|
|
|
|
|
self.clear(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.update_addr = resolve_update_addr(&cfg, addr); |
|
|
|
|
|
|
|
self.timeout = cfg.server.timeout; |
|
|
|
|
|
|
|
self.clver = cfg.client.version; |
|
|
|
|
|
|
|
self.update_title = cfg.client.update_title; |
|
|
|
|
|
|
|
self.update_map = cfg.client.update_map; |
|
|
|
|
|
|
|
self.admin_list = cfg.admin_list; |
|
|
|
|
|
|
|
self.hash = cfg.hash; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn run(&mut self, sig_flag: &AtomicBool) -> Result<(), Error> { |
|
|
|
let mut buf = [0; MAX_PACKET_SIZE]; |
|
|
|
let mut buf = [0; MAX_PACKET_SIZE]; |
|
|
|
loop { |
|
|
|
while !sig_flag.load(Ordering::Relaxed) { |
|
|
|
let (n, from) = self.sock.recv_from(&mut buf)?; |
|
|
|
let (n, from) = match self.sock.recv_from(&mut buf) { |
|
|
|
|
|
|
|
Ok(x) => x, |
|
|
|
|
|
|
|
Err(e) => match e.kind() { |
|
|
|
|
|
|
|
io::ErrorKind::Interrupted => break, |
|
|
|
|
|
|
|
io::ErrorKind::TimedOut | io::ErrorKind::WouldBlock => continue, |
|
|
|
|
|
|
|
_ => Err(e)?, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
let from = match from { |
|
|
|
let from = match from { |
|
|
|
SocketAddr::V4(a) => a, |
|
|
|
SocketAddr::V4(a) => a, |
|
|
@ -210,6 +239,14 @@ impl MasterServer { |
|
|
|
error!("{}: {}", from, e); |
|
|
|
error!("{}: {}", from, e); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn clear(&mut self) { |
|
|
|
|
|
|
|
info!("Clear all servers and challenges"); |
|
|
|
|
|
|
|
self.challenges.clear(); |
|
|
|
|
|
|
|
self.servers.clear(); |
|
|
|
|
|
|
|
self.admin_challenges.clear(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn handle_packet(&mut self, from: SocketAddrV4, src: &[u8]) -> Result<(), Error> { |
|
|
|
fn handle_packet(&mut self, from: SocketAddrV4, src: &[u8]) -> Result<(), Error> { |
|
|
@ -505,7 +542,3 @@ impl MasterServer { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn run(cfg: Config) -> Result<(), Error> { |
|
|
|
|
|
|
|
MasterServer::new(cfg)?.run() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|