/* Hurry Curry! - a game about cooking Copyright 2024 metamuffin This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License only. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ use crate::server::Server; use anyhow::Result; use get_if_addrs::get_if_addrs; use hurrycurry_protocol::VERSION; use log::{info, warn}; use mdns_sd::{ServiceDaemon, ServiceInfo}; use rand::random; use std::{collections::HashMap, net::SocketAddr, sync::Arc, time::Duration}; use tokio::{sync::RwLock, time::interval}; pub async fn mdns_loop(name: String, listen_addr: SocketAddr, state: Arc>) { let d = match ServiceDaemon::new() { Ok(d) => d, Err(e) => { warn!("mDNS daemon failed to start: {e}"); return; } }; let mut interval = interval(Duration::from_secs(60)); let hostname = format!("hks-{}.local.", random::()); loop { interval.tick().await; if let Err(e) = update_service(&d, &state, &name, &hostname, listen_addr).await { warn!("mDNS service update failed: {e}"); } info!("updated mDNS service record"); } } async fn update_service( d: &ServiceDaemon, state: &Arc>, name: &str, hostname: &str, listen_addr: SocketAddr, ) -> Result<()> { let addrs = get_if_addrs()? .into_iter() .map(|e| e.addr.ip()) .filter(|a| !a.is_loopback()) .filter(|a| { (a.is_ipv6() && listen_addr.is_ipv6()) || (a.is_ipv4() && listen_addr.is_ipv4()) || (a.is_ipv4() && listen_addr.is_ipv6() && !cfg!(windows)) }) .collect::>(); let players = state.read().await.count_chefs(); d.register(ServiceInfo::new( "_hurrycurry._tcp.local.", name, hostname, &*addrs, listen_addr.port(), HashMap::from_iter([ ("players".to_string(), players.to_string()), ("version".to_string(), env!("CARGO_PKG_VERSION").to_string()), ( "protocol".to_string(), format!("{}.{}", VERSION.0, VERSION.1), ), ]), )?)?; Ok(()) }