I am trying to write a discovery function in Rust that discovers the device IP in LAN, this function should sends HTTP requests for all possible IPs in the IP space and once receives 200 status return the value and cancels all others requests (by dropping the future in case reqwest used)
async fn discover() -> Result<String, ()> {
for i in 0..256 {
tokio::spawn(async move {
let url = format!("http://192.168.0.{i}:8000/ping");
reqwest::get(url).await;
});
}
}
once receives 200 status return the value and cancels all others requests
We would like to also validate the response content to make sure that this is the correct device and not someone who is trying to spy on the network we will validate the response by verifying the JWT token returning from the /ping
endpoint, how can we do this
This may be achievable with the futures
-crate and select_ok()
.
You can do the following:
convert the range in an Iterator
and map each element i
into a reqwest request. select_ok
needs the Futures in the Vec
to implement UnPin
; that's why I used .boxed()
here.
pass the Vec
of futures into select_ok
the response
will contain the first succesful future result
we can use the remaining_futures
to cancel the remaining requests with drop
(I am not sure if that works, you need to test this)
use futures::{future::select_ok, FutureExt};
async fn discover() {
let futures = (0..256)
.into_iter()
.map(|i| {
let url = format!("http://192.168.0.{i}:8000/ping");
return reqwest::get(url).boxed();
})
.collect::<Vec<_>>();
let (response, mut remaining_futures) = select_ok(futures).await.unwrap();
remaining_futures.iter_mut().for_each(|f| drop(f));
}