[omg] GUI, mDNS, list games on client start

This commit is contained in:
2024-11-10 15:11:22 +01:00
parent 70c327ff03
commit 89af1f9176
46 changed files with 5790 additions and 206 deletions

View File

@ -0,0 +1,9 @@
[package]
name = "lanspread-mdns"
version = "0.1.0"
edition = "2021"
[dependencies]
mdns-sd = "0.11"
eyre = { workspace = true }
tracing = { workspace = true }

View File

@ -0,0 +1,86 @@
use std::net::SocketAddr;
use eyre::bail;
pub use mdns_sd::DaemonEvent;
use mdns_sd::{Receiver, ServiceDaemon, ServiceEvent, ServiceInfo};
pub const LANSPREAD_SERVICE_TYPE: &str = "_lanspread._udp.local.";
pub const LANSPREAD_INSTANCE_NAME: &str = "softlan";
pub struct MdnsAdvertiser {
daemon: ServiceDaemon,
service_info: ServiceInfo,
pub monitor: Receiver<DaemonEvent>,
}
impl MdnsAdvertiser {
pub fn new(service_type: &str, instance_name: &str, address: SocketAddr) -> eyre::Result<Self> {
let host_name = format!("{}.local.", address.ip());
let daemon = ServiceDaemon::new()?;
let service_info = ServiceInfo::new(
service_type,
instance_name,
&host_name,
address.ip(),
address.port(),
None,
)?;
let monitor = daemon.monitor()?;
// Register the service
daemon.register(service_info.clone())?;
Ok(Self {
daemon,
service_info,
monitor,
})
}
}
impl Drop for MdnsAdvertiser {
fn drop(&mut self) {
let _ = self.daemon.unregister(self.service_info.get_fullname());
let _ = self.daemon.shutdown();
}
}
pub fn discover_service(
service_type: &str,
instance_name: Option<&str>,
) -> eyre::Result<SocketAddr> {
let mdns = ServiceDaemon::new().expect("Failed to create mDNS daemon.");
let receiver = mdns.browse(service_type)?;
while let Ok(event) = receiver.recv() {
match event {
ServiceEvent::ServiceResolved(info) => {
tracing::trace!(?info, "mdns ServiceResolved event");
if let Some(instance_name) = instance_name {
if info.get_fullname() != format!("{}.{}", instance_name, service_type) {
tracing::warn!(
"Found service with wrong instance name: {} (expected: {})",
info.get_fullname(),
instance_name,
);
continue;
}
}
if let Some(address) = info.get_addresses().iter().next() {
tracing::info!("Found server at {}:{}", address, info.get_port());
return Ok((*address, info.get_port()).into());
}
tracing::error!(?info, "No address found in mDNS response.");
}
other_event => {
tracing::trace!(?other_event, "mdns unrelated event");
}
}
}
bail!("No server found.")
}