1use std::{
5 collections::{BTreeSet, HashMap, HashSet, VecDeque},
6 net::{IpAddr, SocketAddr},
7 sync::{Arc, Mutex, RwLock},
8 time::Instant,
9};
10
11use chrono::Utc;
12use tokio::sync::watch;
13use tracing::Span;
14
15use zakura_chain::{parameters::Network, serialization::DateTime32};
16
17use crate::{
18 constants::{self, ADDR_RESPONSE_LIMIT_DENOMINATOR, MAX_ADDRS_IN_MESSAGE},
19 meta_addr::MetaAddrChange,
20 peer_registry::PeerRegistry,
21 protocol::external::{canonical_ip, canonical_peer_addr, canonical_socket_addr},
22 types::{MetaAddr, PeerServices},
23 AddressBookPeers, PeerAddrState, PeerSocketAddr,
24};
25
26#[cfg(test)]
27mod tests;
28
29#[derive(Clone, Debug, Default)]
31pub struct BannedIps {
32 inner: Arc<RwLock<BanList>>,
33}
34
35#[derive(Debug, Default)]
37struct BanList {
38 ips: HashSet<IpAddr>,
40
41 insertion_order: VecDeque<IpAddr>,
43}
44
45impl BanList {
46 fn insert(&mut self, ip: IpAddr) {
48 let ip = canonical_ip(ip);
49
50 if !self.ips.insert(ip) {
51 return;
52 }
53
54 self.insertion_order.push_back(ip);
55
56 if self.ips.len() > constants::MAX_BANNED_IPS {
57 let oldest = self
58 .insertion_order
59 .pop_front()
60 .expect("ban order has an entry for every banned IP");
61
62 self.ips.remove(&oldest);
63 }
64 }
65}
66
67impl BannedIps {
68 pub fn contains(&self, ip: IpAddr) -> bool {
70 let ip = canonical_ip(ip);
71
72 self.inner
73 .read()
74 .expect("ban list lock should not be poisoned")
75 .ips
76 .contains(&ip)
77 }
78
79 #[cfg(test)]
80 pub(crate) fn with_banned_ip(ip: IpAddr) -> Self {
81 let bans = Self::default();
82 bans.inner
83 .write()
84 .expect("ban list lock should not be poisoned")
85 .insert(ip);
86 bans
87 }
88}
89
90#[derive(Clone, Debug, Default)]
92struct AddressBookIndex {
93 by_addr: HashMap<PeerSocketAddr, MetaAddr>,
95
96 by_priority: BTreeSet<MetaAddr>,
98
99 by_ip: HashMap<IpAddr, HashSet<PeerSocketAddr>>,
101}
102
103impl AddressBookIndex {
104 fn len(&self) -> usize {
105 self.by_addr.len()
106 }
107
108 fn get(&self, addr: &PeerSocketAddr) -> Option<MetaAddr> {
109 self.by_addr.get(addr).copied()
110 }
111
112 fn insert(&mut self, meta_addr: MetaAddr) {
113 let addr = meta_addr.addr;
114 let previous = self.by_addr.insert(addr, meta_addr);
115 if let Some(previous) = previous {
116 assert!(
117 self.by_priority.remove(&previous),
118 "replaced peer must exist in the priority index"
119 );
120 } else {
121 assert!(
122 self.by_ip.entry(addr.ip()).or_default().insert(addr),
123 "new peer must not exist in the IP index"
124 );
125 }
126
127 assert!(
128 self.by_priority.insert(meta_addr),
129 "new peer metadata must be unique in the priority index"
130 );
131 }
132
133 fn remove(&mut self, addr: &PeerSocketAddr) -> Option<MetaAddr> {
134 let removed = self.by_addr.remove(addr)?;
135
136 assert!(
137 self.by_priority.remove(&removed),
138 "removed peer must exist in the priority index"
139 );
140
141 let remove_ip = {
142 let Some(same_ip_addrs) = self.by_ip.get_mut(&addr.ip()) else {
143 panic!("removed peer IP must exist in the IP index");
144 };
145 assert!(
146 same_ip_addrs.remove(addr),
147 "removed peer must exist in the IP index"
148 );
149 same_ip_addrs.is_empty()
150 };
151 if remove_ip {
152 self.by_ip.remove(&addr.ip());
153 }
154
155 Some(removed)
156 }
157
158 fn remove_ip(&mut self, ip: IpAddr) {
159 let ip = canonical_ip(ip);
160 let Some(addrs) = self.by_ip.remove(&ip) else {
161 return;
162 };
163
164 for addr in addrs {
165 let removed = self
166 .by_addr
167 .remove(&addr)
168 .expect("IP index peer must exist in the address index");
169 assert!(
170 self.by_priority.remove(&removed),
171 "IP index peer must exist in the priority index"
172 );
173 }
174 }
175
176 fn ordered_values(&self) -> impl DoubleEndedIterator<Item = &MetaAddr> {
177 self.by_priority.iter()
178 }
179
180 #[cfg(test)]
181 fn assert_consistent(&self) {
182 assert_eq!(self.by_addr.len(), self.by_priority.len());
183 assert_eq!(
184 self.by_addr.len(),
185 self.by_ip.values().map(HashSet::len).sum::<usize>()
186 );
187
188 for (addr, meta_addr) in &self.by_addr {
189 assert_eq!(*addr, meta_addr.addr);
190 assert!(self.by_priority.contains(meta_addr));
191 assert!(self
192 .by_ip
193 .get(&addr.ip())
194 .is_some_and(|same_ip_addrs| same_ip_addrs.contains(addr)));
195 }
196
197 for meta_addr in self.ordered_values() {
198 assert_eq!(self.by_addr.get(&meta_addr.addr), Some(meta_addr));
199 }
200
201 for (ip, addrs) in &self.by_ip {
202 for addr in addrs {
203 assert_eq!(&addr.ip(), ip);
204 assert!(self.by_addr.contains_key(addr));
205 }
206 }
207
208 let peers: Vec<_> = self.ordered_values().copied().collect();
209 assert!(peers.windows(2).all(|pair| pair[0] <= pair[1]));
210 }
211}
212
213#[derive(Debug)]
247pub struct AddressBook {
248 peers: AddressBookIndex,
255
256 most_recent_by_ip: Option<HashMap<IpAddr, MetaAddr>>,
263
264 bans_by_ip: BannedIps,
266
267 local_listener: SocketAddr,
269
270 local_listener_services: PeerServices,
277
278 network: Network,
280
281 peer_registry: Option<PeerRegistry>,
283
284 addr_limit: usize,
289
290 span: Span,
292
293 expose_peer_addresses: bool,
295
296 address_metrics_tx: watch::Sender<AddressMetrics>,
298
299 address_metrics_dirty: bool,
301
302 #[cfg(test)]
303 address_metrics_update_count: usize,
304
305 last_address_log: Option<Instant>,
307}
308
309#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
311pub struct AddressMetrics {
312 pub responded: usize,
314
315 pub never_attempted_gossiped: usize,
317
318 pub failed: usize,
320
321 pub attempt_pending: usize,
323
324 pub recently_live: usize,
326
327 pub recently_stopped_responding: usize,
329
330 pub num_addresses: usize,
332
333 pub address_limit: usize,
335}
336
337#[allow(clippy::len_without_is_empty)]
338impl AddressBook {
339 pub fn new(
343 local_listener: SocketAddr,
344 network: &Network,
345 max_connections_per_ip: usize,
346 span: Span,
347 ) -> AddressBook {
348 let constructor_span = span.clone();
349 let _guard = constructor_span.enter();
350
351 let instant_now = Instant::now();
352 let chrono_now = Utc::now();
353
354 let (address_metrics_tx, _address_metrics_rx) = watch::channel(AddressMetrics::default());
357
358 let should_limit_outbound_conns_per_ip = max_connections_per_ip == 1;
360 let mut new_book = AddressBook {
361 peers: AddressBookIndex::default(),
362 local_listener: canonical_socket_addr(local_listener),
363 local_listener_services: PeerServices::NODE_NETWORK,
366 network: network.clone(),
367 peer_registry: None,
368 addr_limit: constants::MAX_ADDRS_IN_ADDRESS_BOOK,
369 span,
370 expose_peer_addresses: false,
371 address_metrics_tx,
372 address_metrics_dirty: false,
373 #[cfg(test)]
374 address_metrics_update_count: 0,
375 last_address_log: None,
376 most_recent_by_ip: should_limit_outbound_conns_per_ip.then(HashMap::new),
377 bans_by_ip: Default::default(),
378 };
379
380 new_book.update_metrics(instant_now, chrono_now);
381 new_book
382 }
383
384 #[must_use]
388 pub fn with_local_listener_services(mut self, services: PeerServices) -> Self {
389 self.local_listener_services = services;
390 self
391 }
392
393 #[must_use]
395 pub(crate) fn with_expose_peer_addresses(mut self, expose_peer_addresses: bool) -> Self {
396 self.expose_peer_addresses = expose_peer_addresses;
397 self
398 }
399
400 #[must_use]
402 pub(crate) fn with_peer_registry(mut self, peer_registry: PeerRegistry) -> Self {
403 self.peer_registry = Some(peer_registry);
404 self
405 }
406
407 #[cfg(any(test, feature = "proptest-impl"))]
419 pub fn new_with_addrs(
420 local_listener: SocketAddr,
421 network: &Network,
422 max_connections_per_ip: usize,
423 addr_limit: usize,
424 span: Span,
425 addrs: impl IntoIterator<Item = MetaAddr>,
426 ) -> AddressBook {
427 let constructor_span = span.clone();
428 let _guard = constructor_span.enter();
429
430 let instant_now = Instant::now();
431 let chrono_now = Utc::now();
432
433 assert!(addr_limit > 0);
435
436 let mut new_book = AddressBook::new(local_listener, network, max_connections_per_ip, span);
437 new_book.addr_limit = addr_limit;
438
439 let addrs = addrs
440 .into_iter()
441 .map(|mut meta_addr| {
442 meta_addr.addr = canonical_peer_addr(meta_addr.addr);
443 meta_addr
444 })
445 .filter(|meta_addr| meta_addr.address_is_valid_for_outbound(network))
446 .map(|meta_addr| (meta_addr.addr, meta_addr));
447
448 for (socket_addr, meta_addr) in addrs {
449 new_book.peers.insert(meta_addr);
451 if new_book.should_update_most_recent_by_ip(meta_addr) {
453 new_book
454 .most_recent_by_ip
455 .as_mut()
456 .expect("should be some when should_update_most_recent_by_ip is true")
457 .insert(socket_addr.ip(), meta_addr);
458 }
459 if new_book.peers.len() >= addr_limit {
461 break;
462 }
463 }
464
465 new_book.update_metrics(instant_now, chrono_now);
466 new_book
467 }
468
469 pub fn address_metrics_watcher(&self) -> watch::Receiver<AddressMetrics> {
477 self.address_metrics_tx.subscribe()
478 }
479
480 #[cfg(any(test, feature = "proptest-impl"))]
482 pub fn set_local_listener(&mut self, addr: SocketAddr) {
483 self.local_listener = addr;
484 }
485
486 pub fn local_listener_meta_addr(&self, now: chrono::DateTime<Utc>) -> MetaAddr {
490 let now: DateTime32 = now.try_into().expect("will succeed until 2038");
491
492 MetaAddr::new_local_listener_change(self.local_listener, self.local_listener_services)
493 .local_listener_into_new_meta_addr(now)
494 }
495
496 pub fn local_listener_socket_addr(&self) -> SocketAddr {
498 self.local_listener
499 }
500
501 pub fn fresh_get_addr_response(&self) -> Vec<MetaAddr> {
506 let now = Utc::now();
507 let mut peers = self.sanitized(now);
508 let address_limit = peers.len().div_ceil(ADDR_RESPONSE_LIMIT_DENOMINATOR);
509 peers.truncate(MAX_ADDRS_IN_MESSAGE.min(address_limit));
510
511 peers
512 }
513
514 pub(crate) fn sanitized(&self, now: chrono::DateTime<Utc>) -> Vec<MetaAddr> {
517 use rand::seq::SliceRandom;
518 let _guard = self.span.enter();
519
520 let mut peers = self.peers.clone();
521
522 let local_listener = self.local_listener_meta_addr(now);
526 peers.insert(local_listener);
527
528 let mut peers: Vec<MetaAddr> = peers
530 .ordered_values()
531 .filter_map(|meta_addr| meta_addr.sanitize(&self.network))
532 .filter(|addr| addr.is_active_for_gossip(now))
542 .collect();
543
544 peers.shuffle(&mut rand::thread_rng());
545
546 peers
547 }
548
549 pub fn cacheable(&self, now: chrono::DateTime<Utc>) -> Vec<MetaAddr> {
552 let _guard = self.span.enter();
553
554 let peers = self.peers.clone();
555
556 peers
558 .ordered_values()
559 .filter(|addr| addr.is_active_for_gossip(now))
568 .cloned()
569 .collect()
570 }
571
572 pub fn get(&mut self, addr: PeerSocketAddr) -> Option<MetaAddr> {
576 let addr = canonical_peer_addr(*addr);
577 self.peers.get(&addr)
578 }
579
580 fn should_update_most_recent_by_ip(&self, updated: MetaAddr) -> bool {
593 let Some(most_recent_by_ip) = self.most_recent_by_ip.as_ref() else {
594 return false;
595 };
596
597 if let Some(previous) = most_recent_by_ip.get(&updated.addr.ip()) {
598 updated.last_connection_state == PeerAddrState::Responded
599 && updated.last_response() > previous.last_response()
600 } else {
601 updated.last_connection_state == PeerAddrState::Responded
602 }
603 }
604
605 fn should_remove_most_recent_by_ip(&self, addr: PeerSocketAddr) -> bool {
608 let Some(most_recent_by_ip) = self.most_recent_by_ip.as_ref() else {
609 return false;
610 };
611
612 if let Some(previous) = most_recent_by_ip.get(&addr.ip()) {
613 previous.addr == addr
614 } else {
615 false
616 }
617 }
618
619 pub fn update(&mut self, change: MetaAddrChange) -> Option<MetaAddr> {
639 let updated = self.update_inner(change);
640 self.publish_metrics();
641 updated
642 }
643
644 #[allow(clippy::unwrap_in_result)]
646 fn update_inner(&mut self, change: MetaAddrChange) -> Option<MetaAddr> {
647 let addr_label = change.addr().addr_label(self.expose_peer_addresses);
648
649 if self.bans_by_ip.contains(change.addr().ip()) {
650 tracing::warn!(
651 peer = %addr_label,
652 ?change,
653 "attempted to add a banned peer addr to address book"
654 );
655 return None;
656 }
657
658 let previous = self.get(change.addr());
659
660 let _guard = self.span.enter();
661
662 let instant_now = Instant::now();
663 let chrono_now = Utc::now();
664
665 let updated = change.apply_to_meta_addr(previous, instant_now, chrono_now);
666
667 trace!(
668 peer = %addr_label,
669 ?change,
670 ?updated,
671 ?previous,
672 total_peers = self.peers.len(),
673 recent_peers = self.recently_live_peers(chrono_now).len(),
674 "calculated updated address book entry",
675 );
676
677 if let Some(updated) = updated {
678 if updated.misbehavior() >= constants::MAX_PEER_MISBEHAVIOR_SCORE {
679 let banned_ip = updated.addr.ip();
681 {
682 let mut bans_by_ip = self
683 .bans_by_ip
684 .inner
685 .write()
686 .expect("ban list lock should not be poisoned");
687
688 bans_by_ip.insert(banned_ip);
689 }
690
691 if let Some(most_recent_by_ip) = self.most_recent_by_ip.as_mut() {
696 most_recent_by_ip.remove(&banned_ip);
697 }
698
699 self.peers.remove_ip(banned_ip);
700 self.address_metrics_dirty = true;
701
702 warn!(
703 peer = %addr_label,
704 ?updated,
705 total_peers = self.peers.len(),
706 recent_peers = self.recently_live_peers(chrono_now).len(),
707 "banned ip and removed banned peer addresses from address book",
708 );
709
710 return None;
711 }
712
713 if !updated.address_is_valid_for_outbound(&self.network) {
716 return None;
717 }
718
719 if !updated.last_known_info_is_valid_for_outbound(&self.network)
725 && updated.last_connection_state.is_never_attempted()
726 {
727 return None;
728 }
729
730 self.peers.insert(updated);
731 self.address_metrics_dirty = true;
732
733 if self.should_update_most_recent_by_ip(updated) {
736 self.most_recent_by_ip
737 .as_mut()
738 .expect("should be some when should_update_most_recent_by_ip is true")
739 .insert(updated.addr.ip(), updated);
740 }
741
742 debug!(
743 peer = %addr_label,
744 ?change,
745 ?updated,
746 ?previous,
747 total_peers = self.peers.len(),
748 recent_peers = self.recently_live_peers(chrono_now).len(),
749 "updated address book entry",
750 );
751
752 while self.peers.len() > self.addr_limit {
760 let surplus_peer = self
761 .peers()
762 .next_back()
763 .expect("just checked there is at least one peer");
764
765 self.peers.remove(&surplus_peer.addr);
766
767 if self.should_remove_most_recent_by_ip(surplus_peer.addr) {
770 self.most_recent_by_ip
771 .as_mut()
772 .expect("should be some when should_remove_most_recent_by_ip is true")
773 .remove(&surplus_peer.addr.ip());
774 }
775
776 debug!(
777 surplus = ?surplus_peer,
778 ?updated,
779 total_peers = self.peers.len(),
780 recent_peers = self.recently_live_peers(chrono_now).len(),
781 "removed surplus address book entry",
782 );
783 }
784
785 assert!(self.len() <= self.addr_limit);
786 }
787
788 updated
789 }
790
791 #[allow(dead_code)]
798 fn take(&mut self, removed_addr: PeerSocketAddr) -> Option<MetaAddr> {
799 let _guard = self.span.enter();
800
801 let chrono_now = Utc::now();
802
803 trace!(
804 ?removed_addr,
805 total_peers = self.peers.len(),
806 recent_peers = self.recently_live_peers(chrono_now).len(),
807 );
808
809 if let Some(entry) = self.peers.remove(&removed_addr) {
810 self.address_metrics_dirty = true;
811
812 if self.should_remove_most_recent_by_ip(entry.addr) {
815 if let Some(most_recent_by_ip) = self.most_recent_by_ip.as_mut() {
816 most_recent_by_ip.remove(&entry.addr.ip());
817 }
818 }
819
820 std::mem::drop(_guard);
821 self.publish_metrics();
822 Some(entry)
823 } else {
824 None
825 }
826 }
827
828 pub fn pending_reconnection_addr(&mut self, addr: PeerSocketAddr) -> bool {
831 let meta_addr = self.get(addr);
832
833 let _guard = self.span.enter();
834 match meta_addr {
835 None => false,
836 Some(peer) => peer.last_connection_state == PeerAddrState::AttemptPending,
837 }
838 }
839
840 pub fn peers(&'_ self) -> impl DoubleEndedIterator<Item = MetaAddr> + '_ {
844 let _guard = self.span.enter();
845 self.peers.ordered_values().cloned()
846 }
847
848 fn is_ready_for_connection_attempt_with_ip(
853 &self,
854 ip: &IpAddr,
855 chrono_now: chrono::DateTime<Utc>,
856 ) -> bool {
857 let Some(most_recent_by_ip) = self.most_recent_by_ip.as_ref() else {
858 return true;
860 };
861 let Some(same_ip_peer) = most_recent_by_ip.get(ip) else {
862 return true;
864 };
865 !same_ip_peer.has_connection_recently_responded(chrono_now)
866 }
867
868 pub fn reconnection_peers(
871 &'_ self,
872 instant_now: Instant,
873 chrono_now: chrono::DateTime<Utc>,
874 ) -> impl DoubleEndedIterator<Item = MetaAddr> + '_ {
875 let _guard = self.span.enter();
876
877 self.peers
880 .ordered_values()
881 .filter(move |peer| {
882 peer.is_ready_for_connection_attempt(instant_now, chrono_now, &self.network)
883 && self.is_ready_for_connection_attempt_with_ip(&peer.addr.ip(), chrono_now)
884 })
885 .cloned()
886 }
887
888 pub fn state_peers(
891 &'_ self,
892 state: PeerAddrState,
893 ) -> impl DoubleEndedIterator<Item = MetaAddr> + '_ {
894 let _guard = self.span.enter();
895
896 self.peers
897 .ordered_values()
898 .filter(move |peer| peer.last_connection_state == state)
899 .cloned()
900 }
901
902 pub fn maybe_connected_peers(
905 &'_ self,
906 instant_now: Instant,
907 chrono_now: chrono::DateTime<Utc>,
908 ) -> impl DoubleEndedIterator<Item = MetaAddr> + '_ {
909 let _guard = self.span.enter();
910
911 self.peers
912 .ordered_values()
913 .filter(move |peer| {
914 !peer.is_ready_for_connection_attempt(instant_now, chrono_now, &self.network)
915 })
916 .cloned()
917 }
918
919 pub fn bans(&self) -> BannedIps {
921 self.bans_by_ip.clone()
922 }
923
924 #[cfg(feature = "internal-bench")]
926 #[doc(hidden)]
927 pub fn clone_with_fresh_bans_for_benchmark(&self) -> Self {
928 let mut address_book = self.clone();
929 address_book.bans_by_ip = BannedIps::default();
930 address_book
931 }
932
933 pub fn len(&self) -> usize {
935 self.peers.len()
936 }
937
938 #[cfg(test)]
946 pub fn address_metrics(&self, now: chrono::DateTime<Utc>) -> AddressMetrics {
947 self.address_metrics_internal(now)
948 }
949
950 fn address_metrics_internal(&self, now: chrono::DateTime<Utc>) -> AddressMetrics {
958 let responded = self.state_peers(PeerAddrState::Responded).count();
959 let never_attempted_gossiped = self
960 .state_peers(PeerAddrState::NeverAttemptedGossiped)
961 .count();
962 let failed = self.state_peers(PeerAddrState::Failed).count();
963 let attempt_pending = self.state_peers(PeerAddrState::AttemptPending).count();
964
965 let recently_live = self.recently_live_peers(now).len();
966 let recently_stopped_responding = responded
967 .checked_sub(recently_live)
968 .expect("all recently live peers must have responded");
969
970 let num_addresses = self.len();
971
972 AddressMetrics {
973 responded,
974 never_attempted_gossiped,
975 failed,
976 attempt_pending,
977 recently_live,
978 recently_stopped_responding,
979 num_addresses,
980 address_limit: self.addr_limit,
981 }
982 }
983
984 fn publish_metrics(&mut self) {
986 if !self.address_metrics_dirty {
987 return;
988 }
989
990 self.address_metrics_dirty = false;
991 self.update_metrics(Instant::now(), Utc::now());
992 }
993
994 fn update_metrics(&mut self, instant_now: Instant, chrono_now: chrono::DateTime<Utc>) {
996 let _guard = self.span.enter();
997
998 #[cfg(test)]
999 {
1000 self.address_metrics_update_count += 1;
1001 }
1002
1003 let m = self.address_metrics_internal(chrono_now);
1004
1005 let _ = self.address_metrics_tx.send(m);
1007
1008 metrics::gauge!("candidate_set.responded").set(m.responded as f64);
1010 metrics::gauge!("candidate_set.gossiped").set(m.never_attempted_gossiped as f64);
1011 metrics::gauge!("candidate_set.failed").set(m.failed as f64);
1012 metrics::gauge!("candidate_set.pending").set(m.attempt_pending as f64);
1013
1014 metrics::gauge!("candidate_set.recently_live").set(m.recently_live as f64);
1016 metrics::gauge!("candidate_set.disconnected").set(m.recently_stopped_responding as f64);
1018
1019 std::mem::drop(_guard);
1020 self.log_metrics(&m, instant_now);
1021 }
1022
1023 fn log_metrics(&mut self, m: &AddressMetrics, now: Instant) {
1025 let _guard = self.span.enter();
1026
1027 trace!(
1028 address_metrics = ?m,
1029 );
1030
1031 if m.responded > 0 {
1032 return;
1033 }
1034
1035 if let Some(last_address_log) = self.last_address_log {
1039 if now.saturating_duration_since(last_address_log).as_secs() < 60 {
1041 return;
1042 }
1043 } else {
1044 self.last_address_log = Some(now);
1048 return;
1049 }
1050
1051 self.last_address_log = Some(now);
1052 if m.responded + m.attempt_pending + m.never_attempted_gossiped == 0 {
1054 warn!(
1055 address_metrics = ?m,
1056 "all peer addresses have failed. Hint: check your network connection"
1057 );
1058 } else {
1059 info!(
1060 address_metrics = ?m,
1061 "no active peer connections: trying gossiped addresses"
1062 );
1063 }
1064 }
1065}
1066
1067impl AddressBookPeers for AddressBook {
1068 fn recently_live_peers(&self, now: chrono::DateTime<Utc>) -> Vec<MetaAddr> {
1069 let _guard = self.span.enter();
1070
1071 self.peers
1072 .ordered_values()
1073 .filter(|peer| peer.was_recently_live(now))
1074 .cloned()
1075 .collect()
1076 }
1077
1078 fn connected_peers(&self) -> Option<Vec<crate::ConnectedPeer>> {
1079 self.peer_registry
1080 .as_ref()
1081 .map(PeerRegistry::connected_peers)
1082 }
1083
1084 fn add_peer(&mut self, peer: PeerSocketAddr) -> bool {
1085 if self.get(peer).is_some() {
1086 return false;
1088 }
1089 self.update(MetaAddr::new_initial_peer(peer)).is_some()
1090 }
1091}
1092
1093impl AddressBookPeers for Arc<Mutex<AddressBook>> {
1094 fn recently_live_peers(&self, now: chrono::DateTime<Utc>) -> Vec<MetaAddr> {
1095 self.lock()
1096 .expect("panic in a previous thread that was holding the mutex")
1097 .recently_live_peers(now)
1098 }
1099
1100 fn connected_peers(&self) -> Option<Vec<crate::ConnectedPeer>> {
1101 self.lock()
1102 .expect("panic in a previous thread that was holding the mutex")
1103 .connected_peers()
1104 }
1105
1106 fn add_peer(&mut self, peer: PeerSocketAddr) -> bool {
1107 self.lock()
1108 .expect("panic in a previous thread that was holding the mutex")
1109 .add_peer(peer)
1110 }
1111}
1112
1113impl Extend<MetaAddrChange> for AddressBook {
1114 fn extend<T>(&mut self, iter: T)
1115 where
1116 T: IntoIterator<Item = MetaAddrChange>,
1117 {
1118 for change in iter.into_iter() {
1121 self.update_inner(change);
1122 }
1123
1124 self.publish_metrics();
1125 }
1126}
1127
1128impl Clone for AddressBook {
1129 fn clone(&self) -> AddressBook {
1135 let (address_metrics_tx, _address_metrics_rx) =
1138 watch::channel(*self.address_metrics_tx.borrow());
1139
1140 AddressBook {
1141 peers: self.peers.clone(),
1142 local_listener: self.local_listener,
1143 local_listener_services: self.local_listener_services,
1144 network: self.network.clone(),
1145 peer_registry: self.peer_registry.clone(),
1146 addr_limit: self.addr_limit,
1147 span: self.span.clone(),
1148 expose_peer_addresses: self.expose_peer_addresses,
1149 address_metrics_tx,
1150 address_metrics_dirty: false,
1151 #[cfg(test)]
1152 address_metrics_update_count: 0,
1153 last_address_log: None,
1154 most_recent_by_ip: self.most_recent_by_ip.clone(),
1155 bans_by_ip: self.bans_by_ip.clone(),
1156 }
1157 }
1158}