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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
crate::ix!();
impl AddrManInner {
pub fn select(&self, new_only: bool) -> (Address,i64) {
if self.random.borrow().is_empty() {
return Default::default();
}
if new_only && self.n_new == 0 {
return Default::default();
}
// Use a 50% chance for choosing between
// tried and new table entries.
if !new_only && (self.n_tried > 0 && (self.n_new == 0 || self.insecure_rand.borrow_mut().randbool() == false)) {
// use a tried node
let mut chance_factor: f64 = 1.0;
loop {
// Pick a tried bucket, and an
// initial position in that
// bucket.
let n_kbucket: usize = self.insecure_rand.borrow_mut().randrange(ADDRMAN_TRIED_BUCKET_COUNT as u64).try_into().unwrap();
let n_kbucket_pos: usize = self.insecure_rand.borrow_mut().randrange(ADDRMAN_BUCKET_SIZE as u64).try_into().unwrap();
// Iterate over the positions of
// that bucket, starting at the
// initial one, and looping
// around.
let mut i = 0;
for i in 0..ADDRMAN_BUCKET_SIZE {
if self.vv_tried[n_kbucket][(n_kbucket_pos + i) % ADDRMAN_BUCKET_SIZE] != -1 {
break;
}
}
// If the bucket is entirely
// empty, start over with
// a (likely) different one.
if i == ADDRMAN_BUCKET_SIZE {
continue;
}
// Find the entry to return.
let n_id: i32 = self.vv_tried[n_kbucket][(n_kbucket_pos + i) % ADDRMAN_BUCKET_SIZE];;
let it_found = self.map_info.get(&n_id);
assert!(it_found.is_some());
let info: &AddrInfo = it_found.unwrap();
// With probability GetChance()
// * fChanceFactor, return the
// entry.
if (self.insecure_rand.borrow_mut().randbits(30) as f64) < chance_factor * info.get_chance(None) * ((1 << 30) as f64) {
log_print!(
bc_log::addrman,
"Selected %s from tried\n",
info.to_string()
);
return (info.address.clone(), info.n_last_try);
}
// Otherwise start over with
// a (likely) different bucket,
// and increased chance factor.
chance_factor *= 1.2;
}
} else {
// use a new node
let mut chance_factor: f64 = 1.0;;
loop {
// Pick a new bucket, and an
// initial position in that
// bucket.
let n_ubucket: usize = self.insecure_rand.borrow_mut().randrange(ADDRMAN_NEW_BUCKET_COUNT as u64).try_into().unwrap();
let n_ubucket_pos: usize = self.insecure_rand.borrow_mut().randrange(ADDRMAN_BUCKET_SIZE as u64).try_into().unwrap();
// Iterate over the positions of
// that bucket, starting at the
// initial one, and looping
// around.
let mut i = 0;
for i in 0..ADDRMAN_BUCKET_SIZE {
if self.vv_new[n_ubucket][(n_ubucket_pos + i) % ADDRMAN_BUCKET_SIZE] != -1 {
break;
}
}
// If the bucket is entirely
// empty, start over with
// a (likely) different one.
if i == ADDRMAN_BUCKET_SIZE {
continue;
}
// Find the entry to return.
let n_id: usize = {
let idx: usize = (n_ubucket_pos + i) % ADDRMAN_BUCKET_SIZE;
self.vv_new[n_ubucket][idx].try_into().unwrap()
};
let it_found = self.map_info.get(&n_id.try_into().unwrap());
assert!(it_found.is_some());
let info: &AddrInfo = it_found.unwrap();
// With probability GetChance()
// * fChanceFactor, return the
// entry.
if (self.insecure_rand.borrow_mut().randbits(30) as f64) < chance_factor * info.get_chance(None) * ((1 << 30) as f64) {
log_print!(
bc_log::addrman,
"Selected %s from new\n",
info.to_string()
);
return (info.address.clone(), info.n_last_try);
}
// Otherwise start over with
// a (likely) different bucket,
// and increased chance factor.
chance_factor *= 1.2;
}
}
}
}