2021-12-09 01:28:29 +00:00
|
|
|
use crate::prelude::*;
|
|
|
|
|
2021-12-09 03:11:28 +00:00
|
|
|
#[derive (Clone)]
|
2021-12-09 02:26:45 +00:00
|
|
|
struct Params {
|
|
|
|
common: app_common::Params,
|
2021-12-09 03:11:28 +00:00
|
|
|
bind_addrs: Vec <Ipv4Addr>,
|
2021-12-09 02:26:45 +00:00
|
|
|
nickname: String,
|
|
|
|
our_mac: Option <[u8; 6]>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn server <I: Iterator <Item=String>> (args: I) -> Result <(), AppError>
|
2021-12-09 01:28:29 +00:00
|
|
|
{
|
2021-12-09 16:46:55 +00:00
|
|
|
match get_mac_address() {
|
|
|
|
Ok(Some(ma)) => {
|
|
|
|
println!("Our MAC addr = {}", ma);
|
|
|
|
}
|
|
|
|
Ok(None) => println!("No MAC address found."),
|
|
|
|
Err(e) => println!("{:?}", e),
|
|
|
|
}
|
|
|
|
|
2021-12-09 02:26:45 +00:00
|
|
|
let params = configure (args)?;
|
|
|
|
|
2021-12-09 03:31:07 +00:00
|
|
|
let socket = UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, params.common.server_port)).await?;
|
2021-12-09 02:26:45 +00:00
|
|
|
|
2021-12-09 03:11:28 +00:00
|
|
|
for bind_addr in ¶ms.bind_addrs {
|
2021-12-09 03:48:41 +00:00
|
|
|
if let Err (e) = socket.join_multicast_v4 (params.common.multicast_addr, *bind_addr) {
|
|
|
|
println! ("Error joining multicast group with iface {}: {:?}", bind_addr, e);
|
|
|
|
}
|
2021-12-09 03:11:28 +00:00
|
|
|
}
|
2021-12-09 02:26:45 +00:00
|
|
|
|
2021-12-09 03:31:07 +00:00
|
|
|
serve_interface (params, socket).await?;
|
2021-12-09 02:26:45 +00:00
|
|
|
|
|
|
|
Ok (())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn configure <I: Iterator <Item=String>> (mut args: I) -> Result <Params, AppError>
|
|
|
|
{
|
|
|
|
let common = app_common::Params::default ();
|
2021-12-09 03:11:28 +00:00
|
|
|
let mut bind_addrs = vec![];
|
2021-12-09 01:28:29 +00:00
|
|
|
let mut nickname = String::new ();
|
|
|
|
|
2021-12-09 18:15:03 +00:00
|
|
|
if let Some (proj_dirs) = find_project_dirs () {
|
|
|
|
let mut ini = Ini::new_cs ();
|
2021-12-16 21:47:12 +00:00
|
|
|
let path = proj_dirs.config_local_dir ().join ("server.ini");
|
2021-12-09 18:15:03 +00:00
|
|
|
if ini.load (&path).is_ok () {
|
|
|
|
if let Some (x) = ini.get ("server", "nickname") {
|
|
|
|
nickname = x;
|
|
|
|
eprintln! ("Loaded nickname {:?}", nickname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
eprintln! ("Can't load ini from {:?}, didn't load default configs", path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
eprintln! ("Can't find config dir, didn't load default configs");
|
|
|
|
}
|
|
|
|
|
2021-12-09 01:28:29 +00:00
|
|
|
while let Some (arg) = args.next () {
|
|
|
|
match arg.as_str () {
|
|
|
|
"--bind-addr" => {
|
2021-12-09 03:11:28 +00:00
|
|
|
bind_addrs.push (match args.next () {
|
2021-12-09 01:28:29 +00:00
|
|
|
None => return Err (CliArgError::MissingArgumentValue (arg).into ()),
|
2021-12-09 02:26:45 +00:00
|
|
|
Some (x) => Ipv4Addr::from_str (&x)?,
|
2021-12-09 03:11:28 +00:00
|
|
|
});
|
2021-12-09 01:28:29 +00:00
|
|
|
},
|
|
|
|
"--nickname" => {
|
|
|
|
nickname = match args.next () {
|
|
|
|
None => return Err (CliArgError::MissingArgumentValue (arg).into ()),
|
|
|
|
Some (x) => x
|
|
|
|
};
|
|
|
|
},
|
|
|
|
_ => return Err (CliArgError::UnrecognizedArgument (arg).into ()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let our_mac = get_mac_address ()?.map (|x| x.bytes ());
|
|
|
|
if our_mac.is_none () {
|
|
|
|
println! ("Warning: Can't find our own MAC address. We won't be able to respond to MAC-specific lookaround requests");
|
|
|
|
}
|
|
|
|
|
2021-12-09 03:11:28 +00:00
|
|
|
if bind_addrs.is_empty () {
|
2021-12-09 03:40:03 +00:00
|
|
|
println! ("No bind addresses given, auto-detecting all local IPs");
|
2021-12-09 03:11:28 +00:00
|
|
|
bind_addrs = get_ips ()?;
|
|
|
|
}
|
|
|
|
|
2021-12-09 02:26:45 +00:00
|
|
|
Ok (Params {
|
|
|
|
common,
|
2021-12-09 03:11:28 +00:00
|
|
|
bind_addrs,
|
2021-12-09 02:26:45 +00:00
|
|
|
nickname,
|
|
|
|
our_mac,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-12-09 03:31:07 +00:00
|
|
|
async fn serve_interface (
|
|
|
|
params: Params,
|
|
|
|
socket: UdpSocket,
|
|
|
|
)
|
2021-12-09 02:26:45 +00:00
|
|
|
-> Result <(), AppError>
|
|
|
|
{
|
2021-12-09 01:28:29 +00:00
|
|
|
let mut recent_idem_ids = Vec::with_capacity (32);
|
|
|
|
|
|
|
|
loop {
|
2021-12-09 03:11:28 +00:00
|
|
|
println! ("Listening...");
|
2021-12-09 01:46:03 +00:00
|
|
|
let (req_msgs, remote_addr) = match recv_msg_from (&socket).await {
|
|
|
|
Ok (x) => x,
|
|
|
|
Err (e) => {
|
|
|
|
println! ("Error while receiving message: {:?}", e);
|
|
|
|
continue;
|
|
|
|
},
|
|
|
|
};
|
2021-12-09 01:28:29 +00:00
|
|
|
|
|
|
|
let req = match req_msgs.into_iter ().next () {
|
|
|
|
Some (x) => x,
|
|
|
|
_ => {
|
|
|
|
println! ("Don't know how to handle this message, ignoring");
|
|
|
|
continue;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
let resp = match req {
|
|
|
|
Message::Request1 {
|
|
|
|
mac: None,
|
|
|
|
idem_id,
|
|
|
|
} => {
|
|
|
|
if recent_idem_ids.contains (&idem_id) {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
recent_idem_ids.insert (0, idem_id);
|
|
|
|
recent_idem_ids.truncate (30);
|
|
|
|
Some (vec! [
|
2021-12-09 02:26:45 +00:00
|
|
|
Message::Response1 (params.our_mac),
|
2021-12-09 01:28:29 +00:00
|
|
|
Message::Response2 (message::Response2 {
|
|
|
|
idem_id,
|
2021-12-09 02:26:45 +00:00
|
|
|
nickname: params.nickname.clone (),
|
2021-12-09 01:28:29 +00:00
|
|
|
}),
|
|
|
|
])
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some (resp) = resp {
|
2021-12-09 01:39:54 +00:00
|
|
|
socket.send_to (&Message::many_to_vec (&resp)?, remote_addr).await?;
|
2021-12-09 01:28:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|