forked from dylanmckay/mdns
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add methods for resolving known hosts instead of discovering all hosts
- Loading branch information
1 parent
470b01f
commit e14ae12
Showing
3 changed files
with
108 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
use mdns::Error; | ||
use std::time::Duration; | ||
|
||
const SERVICE_NAME: &'static str = "_http._tcp.local"; | ||
const HOSTS: [&'static str; 2] = ["server1._http._tcp.local", "server2._http._tcp.local"]; | ||
|
||
#[tokio::main] | ||
async fn main() -> Result<(), Error> { | ||
let responses = mdns::resolve::multiple(SERVICE_NAME, &HOSTS, Duration::from_secs(15)).await?; | ||
|
||
for response in responses { | ||
if let (Some(host), Some(ip)) = (response.hostname(), response.ip_addr()) { | ||
println!("found host {} at {}", host, ip) | ||
} | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
//! Utilities for resolving a devices on the LAN. | ||
//! | ||
//! Examples | ||
//! | ||
//! ```rust,no_run | ||
//! use mdns::Error; | ||
//! use std::time::Duration; | ||
//! | ||
//! const SERVICE_NAME: &'static str = "_googlecast._tcp.local"; | ||
//! const HOST: &'static str = "mycast._googlecast._tcp.local"; | ||
//! | ||
//! #[tokio::main] | ||
//! async fn main() -> Result<(), Error> { | ||
//! if let Some(response) = mdns::resolve::one(SERVICE_NAME, HOST, Duration::from_secs(15)).await? { | ||
//! println!("{:?}", response); | ||
//! } | ||
//! | ||
//! Ok(()) | ||
//! } | ||
//! ``` | ||
use crate::{Error, Response}; | ||
use futures_util::pin_mut; | ||
use futures_util::StreamExt; | ||
use std::time::Duration; | ||
|
||
/// Resolve a single device by hostname | ||
pub async fn one<S>( | ||
service_name: &str, | ||
host_name: S, | ||
timeout: Duration, | ||
) -> Result<Option<Response>, Error> | ||
where | ||
S: AsRef<str>, | ||
{ | ||
// by setting the query interval higher than the timeout we ensure we only make one query | ||
let stream = crate::discover::all(service_name, timeout * 2)?.listen(); | ||
pin_mut!(stream); | ||
|
||
let process = async { | ||
while let Some(Ok(response)) = stream.next().await { | ||
match response.hostname() { | ||
Some(found_host) if found_host == host_name.as_ref() => return Some(response), | ||
_ => {} | ||
} | ||
} | ||
|
||
None | ||
}; | ||
|
||
Ok(match tokio::time::timeout(timeout, process).await { | ||
Ok(result) => result, | ||
Err(_) => None, | ||
}) | ||
} | ||
|
||
/// Resolve multiple devices by hostname | ||
pub async fn multiple<S>( | ||
service_name: &str, | ||
host_names: &[S], | ||
timeout: Duration, | ||
) -> Result<Vec<Response>, Error> | ||
where | ||
S: AsRef<str>, | ||
{ | ||
// by setting the query interval higher than the timeout we ensure we only make one query | ||
let stream = crate::discover::all(service_name, timeout * 2)?.listen(); | ||
pin_mut!(stream); | ||
|
||
let mut found = Vec::new(); | ||
|
||
let process = async { | ||
while let Some(Ok(response)) = stream.next().await { | ||
match response.hostname() { | ||
Some(found_host) if host_names.iter().any(|s| s.as_ref() == found_host) => { | ||
found.push(response); | ||
|
||
if found.len() == host_names.len() { | ||
return; | ||
} | ||
} | ||
_ => {} | ||
} | ||
} | ||
}; | ||
|
||
let _ = tokio::time::timeout(timeout, process).await; | ||
Ok(found) | ||
} |