protocol_address.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::sync::Arc;
  19. use async_trait::async_trait;
  20. use log::{debug, warn};
  21. use smol::Executor;
  22. use super::{
  23. super::{
  24. channel::ChannelPtr,
  25. hosts::store::{HostColor, HostsPtr},
  26. message::{AddrsMessage, GetAddrsMessage},
  27. message_subscriber::MessageSubscription,
  28. p2p::P2pPtr,
  29. session::SESSION_OUTBOUND,
  30. settings::SettingsPtr,
  31. },
  32. protocol_base::{ProtocolBase, ProtocolBasePtr},
  33. protocol_jobs_manager::{ProtocolJobsManager, ProtocolJobsManagerPtr},
  34. };
  35. use crate::Result;
  36. /// Defines address and get-address messages. On receiving GetAddr, nodes
  37. /// reply an AddrMessage containing nodes from their hostlist. On receiving
  38. /// an AddrMessage, nodes enter the info into their greylists.
  39. ///
  40. /// The node selection logic for creating an AddrMessage is as follows:
  41. ///
  42. /// 1. First select nodes matching the requested transports from the
  43. /// anchorlist. These nodes have the highest guarantee of being reachable, so we
  44. /// prioritize them first.
  45. ///
  46. /// 2. Then select nodes matching the requested transports from the
  47. /// whitelist.
  48. ///
  49. /// 3. Next select whitelist nodes that don't match our transports. We do
  50. /// this so that nodes share and propagate nodes of different transports,
  51. /// even if they can't connect to them themselves.
  52. ///
  53. /// 4. Finally, if there's still space available, fill the remaining vector
  54. /// space with greylist entries. This is necessary in case this node does
  55. /// not support the transports of the requesting node (non-supported
  56. /// transports are stored on the greylist).
  57. pub struct ProtocolAddress {
  58. channel: ChannelPtr,
  59. addrs_sub: MessageSubscription<AddrsMessage>,
  60. get_addrs_sub: MessageSubscription<GetAddrsMessage>,
  61. hosts: HostsPtr,
  62. settings: SettingsPtr,
  63. jobsman: ProtocolJobsManagerPtr,
  64. p2p: P2pPtr,
  65. }
  66. const PROTO_NAME: &str = "ProtocolAddress";
  67. impl ProtocolAddress {
  68. /// Creates a new address protocol. Makes an address, an external address
  69. /// and a get-address subscription and adds them to the address protocol
  70. /// instance.
  71. pub async fn init(channel: ChannelPtr, p2p: P2pPtr) -> ProtocolBasePtr {
  72. let settings = p2p.settings();
  73. let hosts = p2p.hosts();
  74. // Creates a subscription to address message
  75. let addrs_sub =
  76. channel.subscribe_msg::<AddrsMessage>().await.expect("Missing addrs dispatcher!");
  77. // Creates a subscription to get-address message
  78. let get_addrs_sub =
  79. channel.subscribe_msg::<GetAddrsMessage>().await.expect("Missing getaddrs dispatcher!");
  80. Arc::new(Self {
  81. channel: channel.clone(),
  82. addrs_sub,
  83. get_addrs_sub,
  84. hosts,
  85. jobsman: ProtocolJobsManager::new(PROTO_NAME, channel),
  86. settings,
  87. p2p,
  88. })
  89. }
  90. /// Handles receiving the address message. Loops to continually receive
  91. /// address messages on the address subscription. Validates and adds the
  92. /// received addresses to the greylist.
  93. async fn handle_receive_addrs(self: Arc<Self>) -> Result<()> {
  94. debug!(
  95. target: "net::protocol_address::handle_receive_addrs()",
  96. "[START] address={}", self.channel.address(),
  97. );
  98. loop {
  99. let addrs_msg = self.addrs_sub.receive().await?;
  100. debug!(
  101. target: "net::protocol_address::handle_receive_addrs()",
  102. "Received {} addrs from {}", addrs_msg.addrs.len(), self.channel.address(),
  103. );
  104. debug!(
  105. target: "net::protocol_address::handle_receive_addrs()",
  106. "Appending to greylist...",
  107. );
  108. self.hosts.insert(HostColor::Grey, &addrs_msg.addrs).await;
  109. }
  110. }
  111. /// Handles receiving the get-address message. Continually receives
  112. /// get-address messages on the get-address subscription. Then replies
  113. /// with an address message.
  114. async fn handle_receive_get_addrs(self: Arc<Self>) -> Result<()> {
  115. debug!(
  116. target: "net::protocol_address::handle_receive_get_addrs()",
  117. "[START] address={}", self.channel.address(),
  118. );
  119. loop {
  120. let get_addrs_msg = self.get_addrs_sub.receive().await?;
  121. debug!(
  122. target: "net::protocol_address::handle_receive_get_addrs()",
  123. "Received GetAddrs({}) message from {}", get_addrs_msg.max, self.channel.address(),
  124. );
  125. // Validate transports length
  126. // TODO: Verify this limit. It should be the max number of all our allowed transports,
  127. // plus their mixing.
  128. if get_addrs_msg.transports.len() > 20 {
  129. warn!(target: "net::protocol_address::handle_receive_get_addrs()",
  130. "Sending empty Addrs message");
  131. // TODO: Should this error out, effectively ending the connection?
  132. let addrs_msg = AddrsMessage { addrs: vec![] };
  133. self.channel.send(&addrs_msg).await?;
  134. continue
  135. }
  136. // First we grab address with the requested transports from the gold list
  137. debug!(target: "net::protocol_address::handle_receive_get_addrs()",
  138. "Fetching gold entries with schemes");
  139. let mut addrs = self
  140. .hosts
  141. .container
  142. .fetch_n_random_with_schemes(
  143. HostColor::Gold,
  144. &get_addrs_msg.transports,
  145. get_addrs_msg.max,
  146. )
  147. .await;
  148. // Then we grab address with the requested transports from the whitelist
  149. debug!(target: "net::protocol_address::handle_receive_get_addrs()",
  150. "Fetching whitelist entries with schemes");
  151. addrs.append(
  152. &mut self
  153. .hosts
  154. .container
  155. .fetch_n_random_with_schemes(
  156. HostColor::White,
  157. &get_addrs_msg.transports,
  158. get_addrs_msg.max,
  159. )
  160. .await,
  161. );
  162. // Next we grab addresses without the requested transports
  163. // to fill a 2 * max length vector.
  164. // Then we grab address without the requested transports from the gold list
  165. debug!(target: "net::protocol_address::handle_receive_get_addrs()",
  166. "Fetching gold entries without schemes");
  167. let remain = 2 * get_addrs_msg.max - addrs.len() as u32;
  168. addrs.append(
  169. &mut self
  170. .hosts
  171. .container
  172. .fetch_n_random_excluding_schemes(
  173. HostColor::Gold,
  174. &get_addrs_msg.transports,
  175. remain,
  176. )
  177. .await,
  178. );
  179. // Then we grab address without the requested transports from the white list
  180. debug!(target: "net::protocol_address::handle_receive_get_addrs()",
  181. "Fetching white entries without schemes");
  182. let remain = 2 * get_addrs_msg.max - addrs.len() as u32;
  183. addrs.append(
  184. &mut self
  185. .hosts
  186. .container
  187. .fetch_n_random_excluding_schemes(
  188. HostColor::White,
  189. &get_addrs_msg.transports,
  190. remain,
  191. )
  192. .await,
  193. );
  194. // If there's still space available, take from the Dark list.
  195. /* NOTE: We share peers from our Dark list because to ensure
  196. that non-compatiable transports are shared with other nodes
  197. so that they propagate on the network even if they're not
  198. popular transports. */
  199. debug!(target: "net::protocol_address::handle_receive_get_addrs()",
  200. "Fetching dark entries");
  201. let remain = 2 * get_addrs_msg.max - addrs.len() as u32;
  202. addrs.append(&mut self.hosts.container.fetch_n_random(HostColor::Dark, remain).await);
  203. debug!(
  204. target: "net::protocol_address::handle_receive_get_addrs()",
  205. "Sending {} addresses to {}", addrs.len(), self.channel.address(),
  206. );
  207. let addrs_msg = AddrsMessage { addrs };
  208. self.channel.send(&addrs_msg).await?;
  209. }
  210. }
  211. /// Send our own external addresses over a channel. Get the latest
  212. /// last_seen field from InboundSession, and send it along with our
  213. /// external address.
  214. ///
  215. /// If our external address is misconfigured, send an empty vector.
  216. /// If we have reached our inbound connection limit, send our external
  217. /// address with a `last_seen` field that corresponds to the last time
  218. /// we could receive inbound connections.
  219. async fn send_my_addrs(self: Arc<Self>) -> Result<()> {
  220. debug!(
  221. target: "net::protocol_address::send_my_addrs()",
  222. "[START] channel address={}", self.channel.address(),
  223. );
  224. let type_id = self.channel.session_type_id();
  225. if type_id != SESSION_OUTBOUND {
  226. debug!(target: "net::protocol_address::send_my_addrs()",
  227. "Not an outbound session. Stopping");
  228. return Ok(())
  229. }
  230. if self.settings.external_addrs.is_empty() {
  231. debug!(target: "net::protocol_address::send_my_addrs()",
  232. "External addr not configured. Stopping");
  233. return Ok(())
  234. }
  235. let mut addrs = vec![];
  236. let inbound = self.p2p.session_inbound();
  237. for (addr, last_seen) in inbound.ping_self.addrs.lock().await.iter() {
  238. addrs.push((addr.clone(), *last_seen));
  239. }
  240. debug!(target: "net::protocol_address::send_my_addrs()",
  241. "Broadcasting {} addresses", addrs.len());
  242. let ext_addr_msg = AddrsMessage { addrs };
  243. self.channel.send(&ext_addr_msg).await?;
  244. debug!(target: "net::protocol_address::send_my_addrs()",
  245. "[END] channel address={}", self.channel.address());
  246. Ok(())
  247. }
  248. }
  249. #[async_trait]
  250. impl ProtocolBase for ProtocolAddress {
  251. /// Start the address protocol. If it's an outbound session and has an
  252. /// external address, send our external address. Run receive address
  253. /// and get address protocols on the protocol task manager. Then send
  254. /// get-address msg.
  255. async fn start(self: Arc<Self>, ex: Arc<Executor<'_>>) -> Result<()> {
  256. debug!(target: "net::protocol_address::start()",
  257. "START => address={}", self.channel.address());
  258. self.jobsman.clone().start(ex.clone());
  259. self.jobsman.clone().spawn(self.clone().send_my_addrs(), ex.clone()).await;
  260. self.jobsman.clone().spawn(self.clone().handle_receive_addrs(), ex.clone()).await;
  261. self.jobsman.spawn(self.clone().handle_receive_get_addrs(), ex).await;
  262. // Send get_address message.
  263. let get_addrs = GetAddrsMessage {
  264. max: self.settings.outbound_connections as u32,
  265. transports: self.settings.allowed_transports.clone(),
  266. };
  267. self.channel.send(&get_addrs).await?;
  268. debug!(target: "net::protocol_address::start()",
  269. "END => address={}", self.channel.address());
  270. Ok(())
  271. }
  272. fn name(&self) -> &'static str {
  273. PROTO_NAME
  274. }
  275. }