1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use std::{
collections::hash_map::DefaultHasher,
future::Future,
hash::{Hash, Hasher},
};
pub fn state() -> u64 {
let mut hash = DefaultHasher::new();
if let Ok(ifaces) = ifaces::Interface::get_all() {
for iface in ifaces {
iface.addr.hash(&mut hash);
}
}
hash.finish()
}
pub async fn watch_change() {
let current = state();
loop {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let new = state();
if new != current {
break;
}
}
}
pub async fn reconnect_on_change<Func, Fut, Res, Retry, Cont>(func: Func, cont: Retry) -> Res
where
Func: Fn() -> Fut,
Fut: Future<Output = Res>,
Retry: Fn() -> Cont,
Cont: Future<Output = Option<Res>>,
{
loop {
let changed = watch_change();
let future = func();
futures::pin_mut!(future);
futures::pin_mut!(changed);
use futures::future::Either;
match futures::future::select(future, changed).await {
Either::Left((result, _)) => break result,
Either::Right(_) => {
if let Some(result) = cont().await {
break result;
}
}
}
}
}