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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use std::time::{Duration, Instant};
use std::net::IpAddr;
use indexmap::IndexMap;
use rand::Rng;
#[derive(Debug, Clone, Copy)]
pub struct ValidUntil(pub Instant);
impl ValidUntil {
#[inline]
pub fn new(offset_seconds: u64) -> Self {
Self(Instant::now() + Duration::from_secs(offset_seconds))
}
}
#[inline]
pub fn extract_response_peers<K, V, R, F>(
rng: &mut impl Rng,
peer_map: &IndexMap<K, V>,
max_num_peers_to_take: usize,
sender_peer_map_key: K,
peer_conversion_function: F
) -> Vec<R>
where
K: Eq + ::std::hash::Hash,
F: Fn(&V) -> R
{
let peer_map_len = peer_map.len();
if peer_map_len <= max_num_peers_to_take + 1 {
peer_map.iter()
.filter_map(|(k, v)|{
if *k == sender_peer_map_key {
None
} else {
Some(peer_conversion_function(v))
}
})
.collect()
} else {
let half_num_to_take = max_num_peers_to_take / 2;
let half_peer_map_len = peer_map_len / 2;
let offset_first_half = rng.gen_range(
0,
(half_peer_map_len + (peer_map_len % 2)) - half_num_to_take
);
let offset_second_half = rng.gen_range(
half_peer_map_len,
peer_map_len - half_num_to_take
);
let end_first_half = offset_first_half + half_num_to_take;
let end_second_half = offset_second_half + half_num_to_take + (max_num_peers_to_take % 2);
let mut peers: Vec<R> = Vec::with_capacity(max_num_peers_to_take);
for i in offset_first_half..end_first_half {
if let Some((k, peer)) = peer_map.get_index(i){
if *k != sender_peer_map_key {
peers.push(peer_conversion_function(peer))
}
}
}
for i in offset_second_half..end_second_half {
if let Some((k, peer)) = peer_map.get_index(i){
if *k != sender_peer_map_key {
peers.push(peer_conversion_function(peer))
}
}
}
peers
}
}
#[inline]
pub fn convert_ipv4_mapped_ipv6(ip_address: IpAddr) -> IpAddr {
if let IpAddr::V6(ip) = ip_address {
if let [0, 0, 0, 0, 0, 0xffff, ..] = ip.segments(){
ip.to_ipv4().expect("convert ipv4-mapped ip").into()
} else {
ip_address
}
} else {
ip_address
}
}