1use crate::errors::Error;
3#[cfg(not(target_family = "wasm"))]
4use crate::errors::P2PError;
5use crate::peer_registry::{ConnectionStatus, PeerRegistry};
6use crate::peer_store::{
7 PeerStore,
8 types::{AddrInfo, BannedAddr},
9};
10use crate::protocols::{
11 disconnect_message::DisconnectMessageProtocol,
12 discovery::{DiscoveryAddressManager, DiscoveryProtocol},
13 feeler::Feeler,
14 identify::{Flags, IdentifyCallback, IdentifyProtocol},
15 ping::PingHandler,
16 support_protocols::SupportProtocols,
17};
18use crate::services::{
19 dump_peer_store::DumpPeerStoreService, outbound_peer::OutboundPeerService,
20 protocol_type_checker::ProtocolTypeCheckerService,
21};
22use crate::{Behaviour, CKBProtocol, Peer, PeerIndex, ProtocolId, ServiceControl};
23use ckb_app_config::{NetworkConfig, SupportProtocol, default_support_all_protocols};
24use ckb_logger::{debug, error, info, trace, warn};
25use ckb_spawn::Spawn;
26use ckb_stop_handler::{CancellationToken, broadcast_exit_signals, new_tokio_exit_rx};
27use ckb_systemtime::{Duration, Instant};
28use ckb_util::{Condvar, Mutex, RwLock};
29use futures::{Future, channel::mpsc::Sender};
30use ipnetwork::IpNetwork;
31use p2p::{
32 SessionId, async_trait,
33 builder::ServiceBuilder,
34 bytes::Bytes,
35 context::{ServiceContext, SessionContext},
36 error::{DialerErrorKind, HandshakeErrorKind, ProtocolHandleErrorKind, SendErrorKind},
37 multiaddr::{Multiaddr, Protocol},
38 secio::{self, PeerId, SecioKeyPair, error::SecioError},
39 service::{
40 ProtocolHandle, Service, ServiceAsyncControl, ServiceError, ServiceEvent, TargetProtocol,
41 TargetSession,
42 },
43 traits::ServiceHandle,
44 utils::{extract_peer_id, is_reachable, multiaddr_to_socketaddr},
45 yamux::config::Config as YamuxConfig,
46};
47use rand::prelude::IteratorRandom;
48#[cfg(feature = "with_sentry")]
49use sentry::{Level, capture_message, with_scope};
50#[cfg(not(target_family = "wasm"))]
51use std::sync::mpsc;
52use std::{
53 borrow::Cow,
54 cmp::max,
55 collections::{HashMap, HashSet},
56 pin::Pin,
57 sync::{
58 Arc,
59 atomic::{AtomicBool, Ordering},
60 },
61 thread,
62};
63use tokio::{self, sync::oneshot};
64
65const P2P_SEND_TIMEOUT: Duration = Duration::from_secs(6);
66const P2P_TRY_SEND_INTERVAL: Duration = Duration::from_millis(100);
67const DIAL_HANG_TIMEOUT: Duration = Duration::from_secs(300);
69
70pub struct NetworkState {
72 pub(crate) peer_registry: RwLock<PeerRegistry>,
73 pub(crate) peer_store: Mutex<PeerStore>,
74 pub(crate) listened_addrs: RwLock<Vec<Multiaddr>>,
76 dialing_addrs: RwLock<HashMap<PeerId, Instant>>,
77 public_addrs: HashSet<Multiaddr>,
79 observed_addrs: RwLock<HashMap<PeerIndex, Multiaddr>>,
80 local_private_key: secio::SecioKeyPair,
81 local_peer_id: PeerId,
82 pub(crate) bootnodes: Vec<Multiaddr>,
83 pub(crate) config: NetworkConfig,
84 pub(crate) active: AtomicBool,
85 pub(crate) protocols: RwLock<Vec<(ProtocolId, String, Vec<String>)>>,
88 pub(crate) required_flags: Flags,
89
90 pub(crate) ckb2023: AtomicBool,
91}
92
93impl NetworkState {
94 #[cfg(not(target_family = "wasm"))]
96 pub fn from_config(config: NetworkConfig) -> Result<NetworkState, Error> {
97 config.create_dir_if_not_exists()?;
98 let local_private_key = config.fetch_private_key()?;
99 let local_peer_id = local_private_key.peer_id();
100 let public_addrs: HashSet<Multiaddr> = config
102 .listen_addresses
103 .iter()
104 .chain(config.public_addresses.iter())
105 .cloned()
106 .filter_map(|mut addr| match multiaddr_to_socketaddr(&addr) {
107 Some(socket_addr) if !is_reachable(socket_addr.ip()) => None,
108 _ => {
109 match extract_peer_id(&addr) {
110 Some(peer_id) if peer_id != local_peer_id => {
111 error!("Don't include addresses that not associated with this node in the public_addresses list: {:?}", addr);
112 std::process::exit(1);
113 }
114 Some(_) => (),
115 None => addr.push(Protocol::P2P(Cow::Borrowed(local_peer_id.as_bytes()))),
116 }
117 Some(addr)
118 }
119 })
120 .collect();
121 info!("Loading the peer store. This process may take a few seconds to complete.");
122
123 let peer_store = Mutex::new(PeerStore::load_from_dir_or_default(
124 config.peer_store_path(),
125 ));
126 let bootnodes = config.bootnodes();
127
128 let peer_registry = PeerRegistry::new(
129 config.max_inbound_peers(),
130 config.max_outbound_peers(),
131 config.whitelist_only,
132 config.whitelist_peers(),
133 );
134
135 Ok(NetworkState {
136 peer_store,
137 config,
138 bootnodes,
139 peer_registry: RwLock::new(peer_registry),
140 dialing_addrs: RwLock::new(HashMap::default()),
141 public_addrs,
142 listened_addrs: RwLock::new(Vec::new()),
143 observed_addrs: RwLock::new(HashMap::default()),
144 local_private_key,
145 local_peer_id,
146 active: AtomicBool::new(true),
147 protocols: RwLock::new(Vec::new()),
148 required_flags: Flags::SYNC | Flags::DISCOVERY | Flags::RELAY,
149 ckb2023: AtomicBool::new(false),
150 })
151 }
152
153 #[cfg(target_family = "wasm")]
154 pub async fn from_config(config: NetworkConfig) -> Result<NetworkState, Error> {
155 let local_private_key = config.fetch_private_key()?;
156 let local_peer_id = local_private_key.peer_id();
157 let public_addrs: HashSet<Multiaddr> = config
159 .listen_addresses
160 .iter()
161 .chain(config.public_addresses.iter())
162 .cloned()
163 .filter_map(|mut addr| match multiaddr_to_socketaddr(&addr) {
164 Some(socket_addr) if !is_reachable(socket_addr.ip()) => None,
165 _ => {
166 if extract_peer_id(&addr).is_none() {
167 addr.push(Protocol::P2P(Cow::Borrowed(local_peer_id.as_bytes())));
168 }
169 Some(addr)
170 }
171 })
172 .collect();
173 info!("Loading the peer store. This process may take a few seconds to complete.");
174 let peer_store = Mutex::new(PeerStore::load_from_idb(config.peer_store_path()).await);
175 let bootnodes = config.bootnodes();
176
177 let peer_registry = PeerRegistry::new(
178 config.max_inbound_peers(),
179 config.max_outbound_peers(),
180 config.whitelist_only,
181 config.whitelist_peers(),
182 );
183 Ok(NetworkState {
184 peer_store,
185 config,
186 bootnodes,
187 peer_registry: RwLock::new(peer_registry),
188 dialing_addrs: RwLock::new(HashMap::default()),
189 public_addrs,
190 listened_addrs: RwLock::new(Vec::new()),
191 observed_addrs: RwLock::new(HashMap::default()),
192 local_private_key,
193 local_peer_id,
194 active: AtomicBool::new(true),
195 protocols: RwLock::new(Vec::new()),
196 required_flags: Flags::SYNC | Flags::DISCOVERY | Flags::RELAY,
197 ckb2023: AtomicBool::new(false),
198 })
199 }
200
201 pub fn ckb2023(self, init: bool) -> Self {
203 self.ckb2023.store(init, Ordering::SeqCst);
204 self
205 }
206
207 pub fn required_flags(mut self, flags: Flags) -> Self {
210 self.required_flags = flags;
211 self
212 }
213
214 pub(crate) fn report_session(
215 &self,
216 p2p_control: &ServiceControl,
217 session_id: SessionId,
218 behaviour: Behaviour,
219 ) {
220 if let Some(addr) = self.with_peer_registry(|reg| {
221 reg.get_peer(session_id)
222 .filter(|peer| !peer.is_whitelist)
223 .map(|peer| peer.connected_addr.clone())
224 }) {
225 trace!("Report {:?} because {:?}", addr, behaviour);
226 let report_result = self.peer_store.lock().report(&addr, behaviour);
227 if report_result.is_banned() {
228 if let Err(err) = disconnect_with_message(p2p_control, session_id, "banned") {
229 debug!("Disconnect failed {:?}, error: {:?}", session_id, err);
230 }
231 }
232 } else {
233 debug!(
234 "Report {} failure: not found in peer registry or it is on the whitelist",
235 session_id
236 );
237 }
238 }
239
240 pub(crate) fn ban_session(
241 &self,
242 p2p_control: &ServiceControl,
243 session_id: SessionId,
244 duration: Duration,
245 reason: String,
246 ) {
247 if let Some(addr) = self.with_peer_registry(|reg| {
248 reg.get_peer(session_id)
249 .filter(|peer| !peer.is_whitelist)
250 .map(|peer| peer.connected_addr.clone())
251 }) {
252 info!(
253 "Ban peer {:?} for {} seconds, reason: {}",
254 addr,
255 duration.as_secs(),
256 reason
257 );
258 if let Some(metrics) = ckb_metrics::handle() {
259 metrics.ckb_network_ban_peer.inc();
260 }
261 if let Some(peer) = self.with_peer_registry_mut(|reg| reg.remove_peer(session_id)) {
262 let message = format!("Ban for {} seconds, reason: {}", duration.as_secs(), reason);
263 self.peer_store.lock().ban_addr(
264 &peer.connected_addr,
265 duration.as_millis() as u64,
266 reason,
267 );
268 if let Err(err) =
269 disconnect_with_message(p2p_control, peer.session_id, message.as_str())
270 {
271 debug!("Disconnect failed {:?}, error: {:?}", peer.session_id, err);
272 }
273 }
274 } else {
275 debug!(
276 "Ban session({}) failed: not found in peer registry or it is on the whitelist",
277 session_id
278 );
279 }
280 }
281
282 pub(crate) fn accept_peer(
283 &self,
284 session_context: &SessionContext,
285 ) -> Result<Option<Peer>, Error> {
286 let mut peer_store = self.peer_store.lock();
289 let accept_peer_result = {
290 self.peer_registry.write().accept_peer(
291 session_context.address.clone(),
292 session_context.id,
293 session_context.ty,
294 &mut peer_store,
295 )
296 };
297 accept_peer_result
298 }
299
300 pub fn with_peer_registry<F, T>(&self, callback: F) -> T
302 where
303 F: FnOnce(&PeerRegistry) -> T,
304 {
305 callback(&self.peer_registry.read())
306 }
307
308 pub(crate) fn with_peer_registry_mut<F, T>(&self, callback: F) -> T
310 where
311 F: FnOnce(&mut PeerRegistry) -> T,
312 {
313 callback(&mut self.peer_registry.write())
314 }
315
316 pub(crate) fn with_peer_store_mut<F, T>(&self, callback: F) -> T
318 where
319 F: FnOnce(&mut PeerStore) -> T,
320 {
321 callback(&mut self.peer_store.lock())
322 }
323
324 pub fn local_peer_id(&self) -> &PeerId {
326 &self.local_peer_id
327 }
328
329 pub fn local_private_key(&self) -> &secio::SecioKeyPair {
331 &self.local_private_key
332 }
333
334 pub fn node_id(&self) -> String {
336 self.local_peer_id().to_base58()
337 }
338
339 pub(crate) fn public_addrs(&self, count: usize) -> Vec<Multiaddr> {
340 if self.public_addrs.len() <= count {
341 return self.public_addrs.iter().cloned().collect();
342 } else {
343 self.public_addrs
344 .iter()
345 .cloned()
346 .choose_multiple(&mut rand::thread_rng(), count)
347 }
348 }
349
350 pub(crate) fn connection_status(&self) -> ConnectionStatus {
351 self.peer_registry.read().connection_status()
352 }
353
354 pub fn public_urls(&self, max_urls: usize) -> Vec<(String, u8)> {
356 let listened_addrs = self.listened_addrs.read();
357 self.public_addrs(max_urls.saturating_sub(listened_addrs.len()))
358 .into_iter()
359 .filter_map(|addr| {
360 if !listened_addrs.contains(&addr) {
361 Some((addr, 1))
362 } else {
363 None
364 }
365 })
366 .chain(listened_addrs.iter().map(|addr| (addr.to_owned(), 1)))
367 .map(|(addr, score)| (addr.to_string(), score))
368 .collect()
369 }
370
371 pub(crate) fn add_node(&self, p2p_control: &ServiceControl, address: Multiaddr) {
372 self.dial_identify(p2p_control, address);
373 }
374
375 pub fn get_protocol_ids<F: Fn(ProtocolId) -> bool>(&self, filter: F) -> Vec<ProtocolId> {
377 self.protocols
378 .read()
379 .iter()
380 .filter_map(|&(id, _, _)| if filter(id) { Some(id) } else { None })
381 .collect::<Vec<_>>()
382 }
383
384 pub(crate) fn can_dial(&self, addr: &Multiaddr) -> bool {
385 let peer_id = extract_peer_id(addr);
386 if peer_id.is_none() {
387 error!("Do not dial addr without peer id, addr: {}", addr);
388 return false;
389 }
390 let peer_id = peer_id.as_ref().unwrap();
391
392 if self.local_peer_id() == peer_id {
393 trace!("Do not dial self: {:?}, {}", peer_id, addr);
394 return false;
395 }
396 if self.public_addrs.contains(addr) {
397 trace!(
398 "Do not dial listened address(self): {:?}, {}",
399 peer_id, addr
400 );
401 return false;
402 }
403
404 let peer_in_registry = self.with_peer_registry(|reg| {
405 reg.get_key_by_peer_id(peer_id).is_some() || reg.is_feeler(addr)
406 });
407 if peer_in_registry {
408 trace!("Do not dial peer in registry: {:?}, {}", peer_id, addr);
409 return false;
410 }
411
412 if let Some(dial_started) = self.dialing_addrs.read().get(peer_id) {
413 trace!(
414 "Do not send repeated dial commands to network service: {:?}, {}",
415 peer_id, addr
416 );
417 if Instant::now().saturating_duration_since(*dial_started) > DIAL_HANG_TIMEOUT {
418 #[cfg(feature = "with_sentry")]
419 with_scope(
420 |scope| scope.set_fingerprint(Some(&["ckb-network", "dialing-timeout"])),
421 || {
422 capture_message(
423 &format!(
424 "Dialing {:?}, {:?} for more than {} seconds, \
425 something is wrong in network service",
426 peer_id,
427 addr,
428 DIAL_HANG_TIMEOUT.as_secs(),
429 ),
430 Level::Warning,
431 )
432 },
433 );
434 }
435 return false;
436 }
437
438 true
439 }
440
441 pub(crate) fn dial_success(&self, addr: &Multiaddr) {
442 if let Some(peer_id) = extract_peer_id(addr) {
443 self.dialing_addrs.write().remove(&peer_id);
444 }
445 }
446
447 pub(crate) fn dial_failed(&self, addr: &Multiaddr) {
448 self.with_peer_registry_mut(|reg| {
449 reg.remove_feeler(addr);
450 });
451
452 if let Some(peer_id) = extract_peer_id(addr) {
453 self.dialing_addrs.write().remove(&peer_id);
454 }
455 }
456
457 fn dial_inner(
460 &self,
461 p2p_control: &ServiceControl,
462 addr: Multiaddr,
463 target: TargetProtocol,
464 ) -> Result<(), Error> {
465 if !self.can_dial(&addr) {
466 return Err(Error::Dial(format!("ignore dialing addr {addr}")));
467 }
468
469 debug!("Dialing {addr}");
470 p2p_control.dial(addr.clone(), target)?;
471 self.dialing_addrs.write().insert(
472 extract_peer_id(&addr).expect("verified addr"),
473 Instant::now(),
474 );
475 Ok(())
476 }
477
478 pub fn dial_identify(&self, p2p_control: &ServiceControl, addr: Multiaddr) {
480 if let Err(err) = self.dial_inner(
481 p2p_control,
482 addr,
483 TargetProtocol::Single(SupportProtocols::Identify.protocol_id()),
484 ) {
485 debug!("dial_identify error: {err}");
486 }
487 }
488
489 pub fn dial_feeler(&self, p2p_control: &ServiceControl, addr: Multiaddr) {
491 if let Err(err) = self.dial_inner(
492 p2p_control,
493 addr.clone(),
494 TargetProtocol::Single(SupportProtocols::Identify.protocol_id()),
495 ) {
496 debug!("dial_feeler error {err}");
497 } else {
498 self.with_peer_registry_mut(|reg| {
499 reg.add_feeler(&addr);
500 });
501 }
502 }
503
504 pub(crate) fn add_observed_addr(&self, session_id: SessionId, addr: Multiaddr) {
506 let mut pending_observed_addrs = self.observed_addrs.write();
507 pending_observed_addrs.insert(session_id, addr);
508 }
509
510 pub(crate) fn observed_addrs(&self, count: usize) -> Vec<Multiaddr> {
512 let observed_addrs = self
513 .observed_addrs
514 .read()
515 .values()
516 .cloned()
517 .collect::<HashSet<_>>();
518 if observed_addrs.len() <= count {
519 return observed_addrs.into_iter().collect();
520 } else {
521 observed_addrs
522 .into_iter()
523 .choose_multiple(&mut rand::thread_rng(), count)
524 }
525 }
526
527 pub fn is_active(&self) -> bool {
529 self.active.load(Ordering::Acquire)
530 }
531}
532
533pub struct EventHandler {
535 pub(crate) network_state: Arc<NetworkState>,
536}
537
538impl EventHandler {
539 pub fn new(network_state: Arc<NetworkState>) -> Self {
541 Self { network_state }
542 }
543}
544
545pub trait ExitHandler: Send + Unpin + 'static {
547 fn notify_exit(&self);
549}
550
551#[derive(Clone, Default)]
553pub struct DefaultExitHandler {
554 lock: Arc<Mutex<()>>,
555 exit: Arc<Condvar>,
556}
557
558impl DefaultExitHandler {
559 pub fn wait_for_exit(&self) {
561 self.exit.wait(&mut self.lock.lock());
562 }
563}
564
565impl ExitHandler for DefaultExitHandler {
566 fn notify_exit(&self) {
567 self.exit.notify_all();
568 }
569}
570
571impl EventHandler {
572 fn inbound_eviction(&self) -> Vec<PeerIndex> {
573 if self.network_state.config.bootnode_mode {
574 let status = self.network_state.connection_status();
575
576 if status.max_inbound <= status.non_whitelist_inbound.saturating_add(10) {
577 self.network_state
578 .with_peer_registry(|registry| {
579 registry
580 .peers()
581 .values()
582 .filter(|peer| peer.is_inbound() && !peer.is_whitelist)
583 .map(|peer| peer.session_id)
584 .collect::<Vec<SessionId>>()
585 })
586 .into_iter()
587 .enumerate()
588 .filter_map(|(index, peer)| if index & 0x1 != 0 { Some(peer) } else { None })
589 .collect()
590 } else {
591 Vec::new()
592 }
593 } else {
594 Vec::new()
595 }
596 }
597}
598
599#[async_trait]
600impl ServiceHandle for EventHandler {
601 async fn handle_error(&mut self, context: &mut ServiceContext, error: ServiceError) {
602 match error {
603 ServiceError::DialerError { address, error } => {
604 match error {
605 DialerErrorKind::HandshakeError(HandshakeErrorKind::SecioError(
606 SecioError::ConnectSelf,
607 )) => {
608 debug!("dial observed address success: {:?}", address);
609 }
610 DialerErrorKind::IoError(e)
611 if e.kind() == std::io::ErrorKind::AddrNotAvailable =>
612 {
613 warn!("DialerError({}) {}", address, e);
614 }
615 _ => {
616 debug!("DialerError({}) {}", address, error);
617 }
618 }
619 self.network_state.dial_failed(&address);
620 }
621 ServiceError::ProtocolError {
622 id,
623 proto_id,
624 error,
625 } => {
626 debug!("ProtocolError({}, {}) {}", id, proto_id, error);
627 let message = format!("ProtocolError id={proto_id}");
628 self.network_state.ban_session(
630 &context.control().clone().into(),
631 id,
632 Duration::from_secs(300),
633 message,
634 );
635 }
636 ServiceError::SessionTimeout { session_context } => {
637 debug!(
638 "SessionTimeout({}, {})",
639 session_context.id, session_context.address,
640 );
641 }
642 ServiceError::MuxerError {
643 session_context,
644 error,
645 } => {
646 debug!(
647 "MuxerError({}, {}), substream error {}, disconnect it",
648 session_context.id, session_context.address, error,
649 );
650 }
651 ServiceError::ListenError { address, error } => {
652 debug!("ListenError: address={:?}, error={:?}", address, error);
653 }
654 ServiceError::ProtocolSelectError {
655 proto_name,
656 session_context,
657 } => {
658 debug!(
659 "ProtocolSelectError: proto_name={:?}, session_id={}",
660 proto_name, session_context.id,
661 );
662 }
663 ServiceError::SessionBlocked { session_context } => {
664 debug!("SessionBlocked: {}", session_context.id);
665 }
666 ServiceError::ProtocolHandleError { proto_id, error } => {
667 debug!("ProtocolHandleError: {:?}, proto_id: {}", error, proto_id);
668
669 let ProtocolHandleErrorKind::AbnormallyClosed(opt_session_id) = error;
670 {
671 if let Some(id) = opt_session_id {
672 self.network_state.ban_session(
673 &context.control().clone().into(),
674 id,
675 Duration::from_secs(300),
676 format!("protocol {proto_id} panic when process peer message"),
677 );
678 }
679 #[cfg(feature = "with_sentry")]
680 with_scope(
681 |scope| scope.set_fingerprint(Some(&["ckb-network", "p2p-service-error"])),
682 || {
683 capture_message(
684 &format!(
685 "ProtocolHandleError: AbnormallyClosed, proto_id: {opt_session_id:?}, session id: {opt_session_id:?}"
686 ),
687 Level::Warning,
688 )
689 },
690 );
691 error!(
692 "ProtocolHandleError: AbnormallyClosed, proto_id: {opt_session_id:?}, session id: {opt_session_id:?}"
693 );
694
695 broadcast_exit_signals();
696 }
697 }
698 }
699 }
700
701 async fn handle_event(&mut self, context: &mut ServiceContext, event: ServiceEvent) {
702 match event {
704 ServiceEvent::SessionOpen { session_context } => {
705 debug!(
706 "SessionOpen({}, {})",
707 session_context.id, session_context.address,
708 );
709
710 self.network_state.dial_success(&session_context.address);
711
712 let iter = self.inbound_eviction();
713
714 let control = context.control().clone().into();
715
716 for peer in iter {
717 if let Err(err) =
718 disconnect_with_message(&control, peer, "bootnode random eviction")
719 {
720 debug!("Inbound eviction failed {:?}, error: {:?}", peer, err);
721 }
722 }
723
724 if self
725 .network_state
726 .with_peer_registry(|reg| reg.is_feeler(&session_context.address))
727 {
728 debug!(
729 "Feeler connected {} => {}",
730 session_context.id, session_context.address,
731 );
732 } else {
733 match self.network_state.accept_peer(&session_context) {
734 Ok(Some(evicted_peer)) => {
735 debug!(
736 "Disconnect peer, {} => {}",
737 evicted_peer.session_id, evicted_peer.connected_addr,
738 );
739 if let Err(err) = disconnect_with_message(
740 &control,
741 evicted_peer.session_id,
742 "evict because accepted better peer",
743 ) {
744 debug!(
745 "Disconnect failed {:?}, error: {:?}",
746 evicted_peer.session_id, err
747 );
748 }
749 }
750 Ok(None) => debug!(
751 "{} open, registry {} success",
752 session_context.id, session_context.address,
753 ),
754 Err(err) => {
755 debug!(
756 "Peer registry failed {:?}. Disconnect {} => {}",
757 err, session_context.id, session_context.address,
758 );
759 if let Err(err) = disconnect_with_message(
760 &control,
761 session_context.id,
762 "reject peer connection",
763 ) {
764 debug!(
765 "Disconnect failed {:?}, error: {:?}",
766 session_context.id, err
767 );
768 }
769 }
770 }
771 }
772 }
773 ServiceEvent::SessionClose { session_context } => {
774 debug!(
775 "SessionClose({}, {})",
776 session_context.id, session_context.address,
777 );
778 let peer_exists = self.network_state.with_peer_registry_mut(|reg| {
779 reg.remove_feeler(&session_context.address);
781 reg.remove_peer(session_context.id).is_some()
782 });
783 if peer_exists {
784 debug!(
785 "{} closed. Remove {} from peer_registry",
786 session_context.id, session_context.address,
787 );
788 self.network_state.with_peer_store_mut(|peer_store| {
789 peer_store.remove_disconnected_peer(&session_context.address);
790 });
791 }
792 self.network_state
793 .observed_addrs
794 .write()
795 .remove(&session_context.id);
796 }
797 _ => {
798 info!("p2p service event: {:?}", event);
799 }
800 }
801 }
802}
803
804pub struct NetworkService {
806 p2p_service: Service<EventHandler, SecioKeyPair>,
807 network_state: Arc<NetworkState>,
808 ping_controller: Option<Sender<()>>,
809 bg_services: Vec<Pin<Box<dyn Future<Output = ()> + 'static + Send>>>,
811 version: String,
812}
813
814impl NetworkService {
815 pub fn new(
817 network_state: Arc<NetworkState>,
818 protocols: Vec<CKBProtocol>,
819 required_protocol_ids: Vec<ProtocolId>,
820 identify_announce: (String, String, Flags),
822 transport_type: TransportType,
823 ) -> Self {
824 let config = &network_state.config;
825
826 if config.support_protocols.iter().collect::<HashSet<_>>()
827 != default_support_all_protocols()
828 .iter()
829 .collect::<HashSet<_>>()
830 {
831 warn!(
832 "Customized supported protocols: {:?}",
833 config.support_protocols
834 );
835 }
836
837 let mut protocol_metas = protocols
839 .into_iter()
840 .map(CKBProtocol::build)
841 .collect::<Vec<_>>();
842
843 let identify_callback = IdentifyCallback::new(
847 Arc::clone(&network_state),
848 identify_announce.0,
849 identify_announce.1.clone(),
850 identify_announce.2,
851 );
852 let identify_meta = SupportProtocols::Identify.build_meta_with_service_handle(move || {
853 ProtocolHandle::Callback(Box::new(IdentifyProtocol::new(identify_callback)))
854 });
855 protocol_metas.push(identify_meta);
856
857 let ping_controller = if config.support_protocols.contains(&SupportProtocol::Ping) {
859 let ping_interval = Duration::from_secs(config.ping_interval_secs);
860 let ping_timeout = Duration::from_secs(config.ping_timeout_secs);
861
862 let ping_network_state = Arc::clone(&network_state);
863 let (ping_handler, ping_controller) =
864 PingHandler::new(ping_interval, ping_timeout, ping_network_state);
865 let ping_meta = SupportProtocols::Ping.build_meta_with_service_handle(move || {
866 ProtocolHandle::Callback(Box::new(ping_handler))
867 });
868 protocol_metas.push(ping_meta);
869 Some(ping_controller)
870 } else {
871 None
872 };
873
874 if config
876 .support_protocols
877 .contains(&SupportProtocol::Discovery)
878 {
879 let addr_mgr = DiscoveryAddressManager {
880 network_state: Arc::clone(&network_state),
881 discovery_local_address: config.discovery_local_address,
882 };
883 let disc_meta = SupportProtocols::Discovery.build_meta_with_service_handle(move || {
884 ProtocolHandle::Callback(Box::new(DiscoveryProtocol::new(
885 addr_mgr,
886 config
887 .discovery_announce_check_interval_secs
888 .map(Duration::from_secs),
889 )))
890 });
891 protocol_metas.push(disc_meta);
892 }
893
894 if config.support_protocols.contains(&SupportProtocol::Feeler) {
896 let feeler_meta = SupportProtocols::Feeler.build_meta_with_service_handle({
897 let network_state = Arc::clone(&network_state);
898 move || ProtocolHandle::Callback(Box::new(Feeler::new(Arc::clone(&network_state))))
899 });
900 protocol_metas.push(feeler_meta);
901 }
902
903 if config
905 .support_protocols
906 .contains(&SupportProtocol::DisconnectMessage)
907 {
908 let disconnect_message_state = Arc::clone(&network_state);
909 let disconnect_message_meta = SupportProtocols::DisconnectMessage
910 .build_meta_with_service_handle(move || {
911 ProtocolHandle::Callback(Box::new(DisconnectMessageProtocol::new(
912 disconnect_message_state,
913 )))
914 });
915 protocol_metas.push(disconnect_message_meta);
916 }
917
918 #[cfg(not(target_family = "wasm"))]
920 if config
921 .support_protocols
922 .contains(&SupportProtocol::HolePunching)
923 {
924 let hole_punching_state = Arc::clone(&network_state);
925 let hole_punching_meta =
926 SupportProtocols::HolePunching.build_meta_with_service_handle(move || {
927 ProtocolHandle::Callback(Box::new(
928 crate::protocols::hole_punching::HolePunching::new(hole_punching_state),
929 ))
930 });
931 protocol_metas.push(hole_punching_meta);
932 }
933
934 let mut service_builder = ServiceBuilder::default();
935 let yamux_config = YamuxConfig {
936 max_stream_count: protocol_metas.len(),
937 max_stream_window_size: 1024 * 1024,
938 ..Default::default()
939 };
940 for meta in protocol_metas.into_iter() {
941 network_state
942 .protocols
943 .write()
944 .push((meta.id(), meta.name(), meta.support_versions()));
945 service_builder = service_builder.insert_protocol(meta);
946 }
947 let event_handler = EventHandler {
948 network_state: Arc::clone(&network_state),
949 };
950 service_builder = service_builder
951 .handshake_type(network_state.local_private_key.clone().into())
952 .yamux_config(yamux_config)
953 .forever(true)
954 .max_connection_number(1024)
955 .set_send_buffer_size(config.max_send_buffer())
956 .set_channel_size(config.channel_size())
957 .timeout(Duration::from_secs(5));
958
959 #[cfg(not(target_family = "wasm"))]
960 {
961 service_builder = service_builder.upnp(config.upnp);
962 }
963
964 #[cfg(target_os = "linux")]
965 let p2p_service = {
966 if config.reuse_port_on_linux {
967 let iter = config.listen_addresses.iter();
968
969 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
970 enum BindType {
971 None,
972 Ws,
973 Tcp,
974 Both,
975 }
976 impl BindType {
977 fn transform(&mut self, other: TransportType) {
978 match (&self, other) {
979 (BindType::None, TransportType::Ws) => *self = BindType::Ws,
980 (BindType::None, TransportType::Tcp) => *self = BindType::Tcp,
981 (BindType::Ws, TransportType::Tcp) => *self = BindType::Both,
982 (BindType::Tcp, TransportType::Ws) => *self = BindType::Both,
983 _ => (),
984 }
985 }
986
987 fn is_ready(&self) -> bool {
988 matches!(self, BindType::Both)
990 }
991 }
992
993 let mut init = BindType::None;
994
995 for multi_addr in iter {
996 if init.is_ready() {
997 break;
998 }
999 match find_type(multi_addr) {
1000 TransportType::Tcp => {
1001 if matches!(init, BindType::Tcp) {
1003 continue;
1004 }
1005 if let Some(addr) = multiaddr_to_socketaddr(multi_addr) {
1006 let domain = socket2::Domain::for_address(addr);
1007 let bind_fn = move |socket: p2p::service::TcpSocket, ctxt: p2p::service::TransformerContext| {
1008 let socket_ref = socket2::SockRef::from(&socket);
1009 #[cfg(all(
1010 unix,
1011 not(target_os = "solaris"),
1012 not(target_os = "illumos")
1013 ))]
1014 socket_ref.set_reuse_port(true)?;
1015 socket_ref.set_reuse_address(true)?;
1016 match ctxt.state {
1017 p2p::service::SocketState::Listen => {
1018 Ok(socket)
1019 }
1020 p2p::service::SocketState::Dial => {
1021 if socket_ref.domain()? == domain {
1022 socket_ref.bind(&addr.into())?;
1023 }
1024 Ok(socket)
1025 }
1026 }
1027 };
1028 init.transform(TransportType::Tcp);
1029 service_builder = service_builder.tcp_config(bind_fn);
1030 }
1031 }
1032 TransportType::Ws | TransportType::Wss => {
1033 if matches!(init, BindType::Ws) {
1035 continue;
1036 }
1037 if let Some(addr) = multiaddr_to_socketaddr(multi_addr) {
1038 let domain = socket2::Domain::for_address(addr);
1039 let bind_fn = move |socket: p2p::service::TcpSocket, ctxt: p2p::service::TransformerContext| {
1040 let socket_ref = socket2::SockRef::from(&socket);
1041 #[cfg(all(
1042 unix,
1043 not(target_os = "solaris"),
1044 not(target_os = "illumos")
1045 ))]
1046 socket_ref.set_reuse_port(true)?;
1047 socket_ref.set_reuse_address(true)?;
1048 match ctxt.state {
1049 p2p::service::SocketState::Listen => {
1050 Ok(socket)
1051 }
1052 p2p::service::SocketState::Dial => {
1053 if socket_ref.domain()? == domain {
1054 socket_ref.bind(&addr.into())?;
1055 }
1056 Ok(socket)
1057 }
1058 }
1059 };
1060 init.transform(TransportType::Ws);
1061 service_builder = service_builder.tcp_config_on_ws(bind_fn);
1062 }
1063 }
1064 }
1065 }
1066 }
1067
1068 service_builder.build(event_handler)
1069 };
1070
1071 #[cfg(not(target_os = "linux"))]
1072 let p2p_service = service_builder.build(event_handler);
1079
1080 let dump_peer_store_service = DumpPeerStoreService::new(Arc::clone(&network_state));
1082 let protocol_type_checker_service = ProtocolTypeCheckerService::new(
1083 Arc::clone(&network_state),
1084 p2p_service.control().to_owned().into(),
1085 required_protocol_ids,
1086 );
1087 let mut bg_services = vec![
1088 Box::pin(dump_peer_store_service) as Pin<Box<_>>,
1089 Box::pin(protocol_type_checker_service) as Pin<Box<_>>,
1090 ];
1091 if config.outbound_peer_service_enabled() {
1092 let outbound_peer_service = OutboundPeerService::new(
1093 Arc::clone(&network_state),
1094 p2p_service.control().to_owned().into(),
1095 Duration::from_secs(config.connect_outbound_interval_secs),
1096 transport_type,
1097 );
1098 bg_services.push(Box::pin(outbound_peer_service) as Pin<Box<_>>);
1099 };
1100
1101 #[cfg(feature = "with_dns_seeding")]
1102 if config.dns_seeding_service_enabled() {
1103 let dns_seeding_service = crate::services::dns_seeding::DnsSeedingService::new(
1104 Arc::clone(&network_state),
1105 config.dns_seeds.clone(),
1106 );
1107 bg_services.push(Box::pin(dns_seeding_service.start()) as Pin<Box<_>>);
1108 };
1109
1110 NetworkService {
1111 p2p_service,
1112 network_state,
1113 ping_controller,
1114 bg_services,
1115 version: identify_announce.1,
1116 }
1117 }
1118
1119 pub fn start<S: Spawn>(self, handle: &S) -> Result<NetworkController, Error> {
1121 let config = self.network_state.config.clone();
1122
1123 let p2p_control: ServiceControl = self.p2p_service.control().to_owned().into();
1124
1125 for addr in self.network_state.config.whitelist_peers() {
1127 debug!("Dial whitelist_peers {:?}", addr);
1128 self.network_state.dial_identify(&p2p_control, addr);
1129 }
1130
1131 let target = &self.network_state.required_flags;
1132
1133 let bootnodes = self.network_state.with_peer_store_mut(|peer_store| {
1136 let count = max((config.max_outbound_peers >> 1) as usize, 1);
1137 let mut addrs: Vec<_> = peer_store
1138 .fetch_addrs_to_attempt(count, *target, |_| true)
1139 .into_iter()
1140 .map(|paddr| paddr.addr)
1141 .collect();
1142 let bootnodes = self
1144 .network_state
1145 .bootnodes
1146 .iter()
1147 .choose_multiple(&mut rand::thread_rng(), count.saturating_sub(addrs.len()))
1148 .into_iter()
1149 .cloned();
1150 addrs.extend(bootnodes);
1151 addrs
1152 });
1153
1154 for addr in bootnodes {
1156 debug!("Dial bootnode {:?}", addr);
1157 self.network_state.dial_identify(&p2p_control, addr);
1158 }
1159
1160 let Self {
1161 mut p2p_service,
1162 network_state,
1163 ping_controller,
1164 bg_services,
1165 version,
1166 } = self;
1167
1168 let (bg_signals, bg_receivers): (Vec<_>, Vec<_>) = bg_services
1170 .into_iter()
1171 .map(|bg_service| {
1172 let (signal_sender, signal_receiver) = oneshot::channel::<()>();
1173 (signal_sender, (bg_service, signal_receiver))
1174 })
1175 .unzip();
1176
1177 let receiver: CancellationToken = new_tokio_exit_rx();
1178 #[cfg(not(target_family = "wasm"))]
1179 let (start_sender, start_receiver) = mpsc::channel();
1180 {
1181 #[cfg(not(target_family = "wasm"))]
1182 let network_state = Arc::clone(&network_state);
1183 let p2p_control: ServiceAsyncControl = p2p_control.clone().into();
1184 handle.spawn_task(async move {
1185 #[cfg(not(target_family = "wasm"))]
1186 {
1187 let listen_addresses = {
1188 let mut addresses = config.listen_addresses.clone();
1189 if config.reuse_tcp_with_ws {
1190 let ws_listens = addresses
1191 .iter()
1192 .cloned()
1193 .filter_map(|mut addr| {
1194 if matches!(find_type(&addr), TransportType::Tcp) {
1195 addr.push(Protocol::Ws);
1196 Some(addr)
1197 } else {
1198 None
1199 }
1200 })
1201 .collect::<Vec<_>>();
1202
1203 addresses.extend(ws_listens);
1204 }
1205 let mut addresses = addresses
1206 .into_iter()
1207 .collect::<HashSet<_>>()
1208 .into_iter()
1209 .collect::<Vec<_>>();
1210 addresses.sort_by(|a, b| {
1211 let ty_a = find_type(a);
1212 let ty_b = find_type(b);
1213
1214 ty_a.cmp(&ty_b)
1215 });
1216
1217 addresses
1218 };
1219
1220 for addr in &listen_addresses {
1221 match p2p_service.listen(addr.to_owned()).await {
1222 Ok(listen_address) => {
1223 info!("Listen on address: {}", listen_address);
1224 network_state
1225 .listened_addrs
1226 .write()
1227 .push(listen_address.clone());
1228 }
1229 Err(err) => {
1230 warn!(
1231 "Listen on address {} failed, due to error: {}",
1232 addr.clone(),
1233 err
1234 );
1235 start_sender
1236 .send(Err(Error::P2P(P2PError::Transport(err))))
1237 .expect("channel abnormal shutdown");
1238 return;
1239 }
1240 };
1241 }
1242 start_sender.send(Ok(())).unwrap();
1243 }
1244
1245 p2p::runtime::spawn(async move { p2p_service.run().await });
1246 tokio::select! {
1247 _ = receiver.cancelled() => {
1248 info!("NetworkService receive exit signal, start shutdown...");
1249 let _ = p2p_control.shutdown().await;
1250 drop(bg_signals);
1252
1253 info!("NetworkService shutdown now");
1254 },
1255 else => {
1256 let _ = p2p_control.shutdown().await;
1257 drop(bg_signals);
1259 },
1260 }
1261 });
1262 }
1263 for (mut service, mut receiver) in bg_receivers {
1264 handle.spawn_task(async move {
1265 loop {
1266 tokio::select! {
1267 _ = &mut service => {},
1268 _ = &mut receiver => break
1269 }
1270 }
1271 });
1272 }
1273 #[cfg(not(target_family = "wasm"))]
1274 if let Ok(Err(e)) = start_receiver.recv() {
1275 return Err(e);
1276 }
1277
1278 Ok(NetworkController {
1279 version,
1280 network_state,
1281 p2p_control,
1282 ping_controller,
1283 })
1284 }
1285}
1286
1287#[derive(Clone)]
1289pub struct NetworkController {
1290 version: String,
1291 network_state: Arc<NetworkState>,
1292 p2p_control: ServiceControl,
1293 ping_controller: Option<Sender<()>>,
1294}
1295
1296impl NetworkController {
1297 pub fn init_ckb2023(&self) {
1299 self.network_state.ckb2023.store(true, Ordering::SeqCst);
1300 }
1301
1302 pub fn load_ckb2023(&self) -> bool {
1304 self.network_state.ckb2023.load(Ordering::SeqCst)
1305 }
1306
1307 pub fn public_urls(&self, max_urls: usize) -> Vec<(String, u8)> {
1309 self.network_state.public_urls(max_urls)
1310 }
1311
1312 pub fn version(&self) -> &String {
1314 &self.version
1315 }
1316
1317 pub fn node_id(&self) -> String {
1319 self.network_state.node_id()
1320 }
1321
1322 pub fn p2p_control(&self) -> &ServiceControl {
1324 &self.p2p_control
1325 }
1326
1327 pub fn add_node(&self, address: Multiaddr) {
1329 self.network_state.add_node(&self.p2p_control, address)
1330 }
1331
1332 pub fn remove_node(&self, peer_id: &PeerId) {
1334 if let Some(session_id) = self
1335 .network_state
1336 .peer_registry
1337 .read()
1338 .get_key_by_peer_id(peer_id)
1339 {
1340 if let Err(err) =
1341 disconnect_with_message(&self.p2p_control, session_id, "disconnect manually")
1342 {
1343 debug!("Disconnect failed {:?}, error: {:?}", session_id, err);
1344 }
1345 } else {
1346 error!("Cannot find peer {:?}", peer_id);
1347 }
1348 }
1349
1350 pub fn get_banned_addrs(&self) -> Vec<BannedAddr> {
1352 self.network_state
1353 .peer_store
1354 .lock()
1355 .ban_list()
1356 .get_banned_addrs()
1357 }
1358
1359 pub fn clear_banned_addrs(&self) {
1361 self.network_state.peer_store.lock().clear_ban_list();
1362 }
1363
1364 pub fn addr_info(&self, addr: &Multiaddr) -> Option<AddrInfo> {
1366 self.network_state
1367 .peer_store
1368 .lock()
1369 .addr_manager()
1370 .get(addr)
1371 .cloned()
1372 }
1373
1374 pub fn ban(&self, address: IpNetwork, ban_until: u64, ban_reason: String) {
1376 self.disconnect_peers_in_ip_range(address, &ban_reason);
1377 self.network_state
1378 .peer_store
1379 .lock()
1380 .ban_network(address, ban_until, ban_reason)
1381 }
1382
1383 pub fn unban(&self, address: &IpNetwork) {
1385 self.network_state
1386 .peer_store
1387 .lock()
1388 .mut_ban_list()
1389 .unban_network(address);
1390 }
1391
1392 pub fn connected_peers(&self) -> Vec<(PeerIndex, Peer)> {
1394 self.network_state.with_peer_registry(|reg| {
1395 reg.peers()
1396 .iter()
1397 .map(|(peer_index, peer)| (*peer_index, peer.clone()))
1398 .collect::<Vec<_>>()
1399 })
1400 }
1401
1402 pub fn ban_peer(&self, peer_index: PeerIndex, duration: Duration, reason: String) {
1404 self.network_state
1405 .ban_session(&self.p2p_control, peer_index, duration, reason);
1406 }
1407
1408 fn disconnect_peers_in_ip_range(&self, address: IpNetwork, reason: &str) {
1410 self.network_state.with_peer_registry(|reg| {
1411 reg.peers().iter().for_each(|(peer_index, peer)| {
1412 if let Some(addr) = multiaddr_to_socketaddr(&peer.connected_addr) {
1413 if address.contains(addr.ip()) {
1414 let _ = disconnect_with_message(
1415 &self.p2p_control,
1416 *peer_index,
1417 &format!("Ban peer {}, reason: {}", addr.ip(), reason),
1418 );
1419 }
1420 }
1421 })
1422 });
1423 }
1424
1425 fn try_broadcast(
1426 &self,
1427 quick: bool,
1428 target: Option<SessionId>,
1429 proto_id: ProtocolId,
1430 data: Bytes,
1431 ) -> Result<(), SendErrorKind> {
1432 let now = Instant::now();
1433 loop {
1434 let target = target
1435 .map(TargetSession::Single)
1436 .unwrap_or(TargetSession::All);
1437 let result = if quick {
1438 self.p2p_control
1439 .quick_filter_broadcast(target, proto_id, data.clone())
1440 } else {
1441 self.p2p_control
1442 .filter_broadcast(target, proto_id, data.clone())
1443 };
1444 match result {
1445 Ok(()) => {
1446 return Ok(());
1447 }
1448 Err(SendErrorKind::WouldBlock) => {
1449 if Instant::now().saturating_duration_since(now) > P2P_SEND_TIMEOUT {
1450 warn!("Broadcast message to {} timeout", proto_id);
1451 return Err(SendErrorKind::WouldBlock);
1452 }
1453 thread::sleep(P2P_TRY_SEND_INTERVAL);
1454 }
1455 Err(err) => {
1456 warn!("Broadcast message to {} failed: {:?}", proto_id, err);
1457 return Err(err);
1458 }
1459 }
1460 }
1461 }
1462
1463 pub fn broadcast(&self, proto_id: ProtocolId, data: Bytes) -> Result<(), SendErrorKind> {
1465 self.try_broadcast(false, None, proto_id, data)
1466 }
1467
1468 pub fn quick_broadcast(&self, proto_id: ProtocolId, data: Bytes) -> Result<(), SendErrorKind> {
1470 self.try_broadcast(true, None, proto_id, data)
1471 }
1472
1473 pub fn send_message_to(
1475 &self,
1476 session_id: SessionId,
1477 proto_id: ProtocolId,
1478 data: Bytes,
1479 ) -> Result<(), SendErrorKind> {
1480 self.try_broadcast(false, Some(session_id), proto_id, data)
1481 }
1482
1483 pub fn is_active(&self) -> bool {
1485 self.network_state.is_active()
1486 }
1487
1488 pub fn set_active(&self, active: bool) {
1490 self.network_state.active.store(active, Ordering::Release);
1491 }
1492
1493 pub fn protocols(&self) -> Vec<(ProtocolId, String, Vec<String>)> {
1495 self.network_state.protocols.read().clone()
1496 }
1497
1498 pub fn ping_peers(&self) {
1500 if let Some(mut ping_controller) = self.ping_controller.clone() {
1501 let _ignore = ping_controller.try_send(());
1502 }
1503 }
1504}
1505
1506pub(crate) fn disconnect_with_message(
1508 control: &ServiceControl,
1509 peer_index: SessionId,
1510 message: &str,
1511) -> Result<(), SendErrorKind> {
1512 if !message.is_empty() {
1513 let data = Bytes::from(message.as_bytes().to_vec());
1514 control.quick_send_message_to(
1516 peer_index,
1517 SupportProtocols::DisconnectMessage.protocol_id(),
1518 data,
1519 )?;
1520 }
1521 control.disconnect(peer_index)
1522}
1523
1524pub(crate) async fn async_disconnect_with_message(
1525 control: &ServiceAsyncControl,
1526 peer_index: SessionId,
1527 message: &str,
1528) -> Result<(), SendErrorKind> {
1529 if !message.is_empty() {
1530 let data = Bytes::from(message.as_bytes().to_vec());
1531 control
1533 .quick_send_message_to(
1534 peer_index,
1535 SupportProtocols::DisconnectMessage.protocol_id(),
1536 data,
1537 )
1538 .await?;
1539 }
1540 control.disconnect(peer_index).await
1541}
1542
1543#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
1545pub enum TransportType {
1546 Tcp,
1548 Ws,
1550 Wss,
1552}
1553
1554#[allow(dead_code)]
1555pub(crate) fn find_type(addr: &Multiaddr) -> TransportType {
1556 let mut iter = addr.iter();
1557
1558 iter.find_map(|proto| match proto {
1559 Protocol::Ws => Some(TransportType::Ws),
1560 Protocol::Wss => Some(TransportType::Wss),
1561 _ => None,
1562 })
1563 .unwrap_or(TransportType::Tcp)
1564}