darkfi/net/protocol/
protocol_seed.rs1use async_trait::async_trait;
20use smol::{lock::RwLock as AsyncRwLock, Executor};
21use std::{sync::Arc, time::UNIX_EPOCH};
22use tracing::debug;
23
24use super::{
25 super::{
26 channel::ChannelPtr,
27 hosts::{HostColor, HostsPtr},
28 message::{AddrsMessage, GetAddrsMessage},
29 message_publisher::MessageSubscription,
30 p2p::P2pPtr,
31 settings::Settings,
32 },
33 protocol_base::{ProtocolBase, ProtocolBasePtr},
34};
35use crate::Result;
36
37pub struct ProtocolSeed {
39 channel: ChannelPtr,
40 hosts: HostsPtr,
41 settings: Arc<AsyncRwLock<Settings>>,
42 addr_sub: MessageSubscription<AddrsMessage>,
43}
44
45const PROTO_NAME: &str = "ProtocolSeed";
46
47impl ProtocolSeed {
48 pub async fn init(channel: ChannelPtr, p2p: P2pPtr) -> ProtocolBasePtr {
50 let addr_sub =
52 channel.subscribe_msg::<AddrsMessage>().await.expect("Missing addr dispatcher!");
53
54 Arc::new(Self { channel, hosts: p2p.hosts(), settings: p2p.settings(), addr_sub })
55 }
56
57 pub async fn send_my_addrs(&self) -> Result<()> {
60 debug!(
61 target: "net::protocol_seed::send_my_addrs",
62 "[START] channel address={}", self.channel.display_address(),
63 );
64
65 let external_addrs = self.channel.hosts().external_addrs().await;
66
67 if external_addrs.is_empty() {
68 debug!(
69 target: "net::protocol_seed::send_my_addrs",
70 "External address is not configured. Stopping",
71 );
72 return Ok(())
73 }
74
75 let mut addrs = vec![];
76
77 for addr in external_addrs {
78 let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
79 addrs.push((addr, last_seen));
80 }
81
82 debug!(
83 target: "net::protocol_seed::send_my_addrs",
84 "Broadcasting {} addresses", addrs.len(),
85 );
86
87 let ext_addr_msg = AddrsMessage { addrs };
88 self.channel.send(&ext_addr_msg).await?;
89
90 debug!(
91 target: "net::protocol_seed::send_my_addrs",
92 "[END] channel address={}", self.channel.display_address(),
93 );
94
95 Ok(())
96 }
97}
98
99#[async_trait]
100impl ProtocolBase for ProtocolSeed {
101 async fn start(self: Arc<Self>, _ex: Arc<Executor<'_>>) -> Result<()> {
106 debug!(target: "net::protocol_seed::start", "START => address={}", self.channel.display_address());
107
108 self.send_my_addrs().await?;
110
111 let settings = self.settings.read().await;
112 let outbound_connections = settings.outbound_connections;
113 let getaddrs_max = settings.getaddrs_max;
114 let active_profiles = settings.active_profiles.clone();
115 drop(settings);
116
117 let get_addr = GetAddrsMessage {
120 max: getaddrs_max.unwrap_or(outbound_connections.min(u32::MAX as usize) as u32),
121 transports: active_profiles,
122 };
123 self.channel.send(&get_addr).await?;
124
125 let addrs_msg = self.addr_sub.receive().await?;
127 debug!(
128 target: "net::protocol_seed::start",
129 "Received {} addrs from {}", addrs_msg.addrs.len(), self.channel.display_address(),
130 );
131
132 if !addrs_msg.addrs.is_empty() {
133 debug!(
134 target: "net::protocol_seed::start",
135 "Appending to greylist...",
136 );
137 self.hosts.insert(HostColor::Grey, &addrs_msg.addrs).await;
138 }
139
140 debug!(target: "net::protocol_seed::start", "END => address={}", self.channel.display_address());
141 Ok(())
142 }
143
144 fn name(&self) -> &'static str {
145 PROTO_NAME
146 }
147}