harmony/harmony_inventory_agent/src/local_presence/advertise.rs

91 lines
2.9 KiB
Rust

use log::{debug, error, info, warn};
use mdns_sd::{ServiceDaemon, ServiceInfo};
use std::collections::HashMap;
use crate::{
hwinfo::PhysicalHost,
local_presence::{PresenceError, SERVICE_NAME, VERSION},
};
/// Advertises the agent's presence on the local network.
///
/// This function is synchronous and non-blocking. It spawns a background Tokio task
/// to handle the mDNS advertisement for the lifetime of the application.
pub fn advertise(service_port: u16) -> Result<(), PresenceError> {
let host_id = match PhysicalHost::gather() {
Ok(host) => Some(host.host_uuid),
Err(e) => {
error!("Could not build physical host, harmony presence id will be unavailable : {e}");
None
}
};
let instance_name = format!(
"inventory-agent-{}",
host_id.clone().unwrap_or("unknown".to_string())
);
let spawned_msg = format!("Spawned local presence advertisement task for '{instance_name}'.");
tokio::spawn(async move {
info!(
"Local presence task started. Advertising as '{}'.",
instance_name
);
// The ServiceDaemon must live for the entire duration of the advertisement.
// If it's dropped, the advertisement stops.
let mdns = match ServiceDaemon::new() {
Ok(daemon) => daemon,
Err(e) => {
warn!("Failed to create mDNS daemon: {}. Task shutting down.", e);
return;
}
};
let mut props = HashMap::new();
if let Some(host_id) = host_id {
props.insert("id".to_string(), host_id);
}
props.insert("version".to_string(), VERSION.to_string());
let local_ip: Box<dyn mdns_sd::AsIpAddrs> = match local_ip_address::local_ip() {
Ok(ip) => Box::new(ip),
Err(e) => {
error!(
"Could not figure out local ip, mdns will have to try to figure it out by itself : {e}"
);
Box::new(())
}
};
debug!("Using local ip {:?}", local_ip.as_ip_addrs());
let service_info = ServiceInfo::new(
SERVICE_NAME,
&instance_name,
&format!("{}.local.", instance_name),
local_ip,
service_port,
Some(props),
)
.expect("ServiceInfo creation should not fail with valid inputs");
// The registration handle must also be kept alive.
let _registration_handle = match mdns.register(service_info) {
Ok(handle) => {
info!("Service successfully registered on the local network.");
handle
}
Err(e) => {
warn!("Failed to register service: {}. Task shutting down.", e);
return;
}
};
});
info!("{spawned_msg}");
Ok(())
}