crate::ix!();
impl AddrManInner {
pub fn add(&mut self,
addr: &Address,
source: &NetAddr,
n_key: &u256,
asmap: &Vec<bool>,
mut n_time_penalty: i64) -> bool {
if !addr.service.base.is_routable() {
return false;
}
let mut f_new: bool = false;
let mut n_id: i32 = 0;
let mut p_info: *mut AddrInfo = self.find(&addr.service, Some(&mut n_id));
if addr.service.base == *source {
n_time_penalty = 0;
}
if p_info != null_mut() {
let info = unsafe{ &mut *p_info };
let f_currently_online: bool = get_adjusted_time() - (addr.n_time as i64) < 24 * 60 * 60;
let n_update_interval: i64 = match f_currently_online {
true => 60 * 60,
false => 24 * 60 * 60,
};
let info_address_ntime: i64 = i64::from(info.address.n_time);
let positive_addr_ntime: bool = addr.n_time != 0;
let info_address_ntime_eq_0: bool = info.address.n_time == 0;
let addr_ntime: i64 = addr.n_time as i64;
if positive_addr_ntime &&
(info_address_ntime_eq_0 || info_address_ntime < addr_ntime - n_update_interval - n_time_penalty) {
info.address.n_time = std::cmp::max(0, (addr.n_time as i64) - n_time_penalty) as u32;
}
info.address.n_services
= ServiceFlags::from(info.address.n_services.bits() | addr.n_services.bits());
if addr.n_time == 0 || (info.address.n_time != 0 && addr.n_time <= info.address.n_time) {
return false;
}
if info.in_tried {
return false;
}
if info.n_ref_count == ADDRMAN_NEW_BUCKETS_PER_ADDRESS.try_into().unwrap() {
return false;
}
let mut n_factor: i32 = 1;
for n in 0..info.n_ref_count {
n_factor *= 2;
}
if n_factor > 1 && (self.insecure_rand.borrow_mut().randrange(n_factor.try_into().unwrap()) != 0) {
return false;
}
} else {
unsafe {
p_info = self.create(addr, source, Some(&mut n_id));
(*p_info).address.n_time
= std::cmp::max(
0,
((*p_info).address.n_time as u32) - (n_time_penalty as u32)
);
self.n_new += 1;
f_new = true;
}
}
let info = unsafe{ &mut *p_info };
let n_ubucket: usize = info.get_new_bucket_given_source(
n_key,
source,
asmap
).try_into().unwrap();
let n_ubucket_pos: usize = info.get_bucket_position(
n_key,
true,
n_ubucket
).try_into().unwrap();
if self.vv_new[n_ubucket][n_ubucket_pos] != n_id {
let mut f_insert: bool = self.vv_new[n_ubucket][n_ubucket_pos] == -1;
if !f_insert {
let infoExisting: &AddrInfo = &self.map_info[&self.vv_new[n_ubucket][n_ubucket_pos]];
if infoExisting.is_terrible(None)
|| (infoExisting.n_ref_count > 1 && info.n_ref_count == 0)
{
f_insert = true;
}
}
if f_insert {
self.clear_new(n_ubucket, n_ubucket_pos);
info.n_ref_count += 1;
self.vv_new[n_ubucket][n_ubucket_pos] = n_id;
log_print!{
BCLog::ADDRMAN,
"Added %s mapped to AS%i to new[%i][%i]\n",
addr.ToString(),
addr.get_mapped_as(asmap),
n_ubucket,
n_ubucket_pos
};
} else {
if info.n_ref_count == 0 {
self.delete(n_id);
}
}
}
f_new
}
}