connector.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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, time::Duration};
  19. use futures::{
  20. future::{select, Either},
  21. pin_mut,
  22. };
  23. use log::warn;
  24. use url::Url;
  25. use super::{
  26. channel::{Channel, ChannelPtr},
  27. hosts::HostColor,
  28. session::SessionWeakPtr,
  29. settings::Settings,
  30. transport::Dialer,
  31. };
  32. use crate::{system::CondVar, Error, Result};
  33. /// Create outbound socket connections
  34. pub struct Connector {
  35. /// P2P settings
  36. settings: Arc<Settings>,
  37. /// Weak pointer to the session
  38. pub session: SessionWeakPtr,
  39. /// Stop signal that aborts the connector if received.
  40. stop_signal: CondVar,
  41. }
  42. impl Connector {
  43. /// Create a new connector with given network settings
  44. pub fn new(settings: Arc<Settings>, session: SessionWeakPtr) -> Self {
  45. Self { settings, session, stop_signal: CondVar::new() }
  46. }
  47. /// Establish an outbound connection
  48. pub async fn connect(&self, url: &Url) -> Result<(Url, ChannelPtr)> {
  49. let hosts = self.session.upgrade().unwrap().p2p().hosts();
  50. if hosts.container.contains(HostColor::Black as usize, url) ||
  51. hosts.block_all_ports(url.host_str().unwrap().to_string())
  52. {
  53. warn!(target: "net::connector::connect", "Peer {} is blacklisted", url);
  54. return Err(Error::ConnectFailed)
  55. }
  56. let mut endpoint = url.clone();
  57. let transports = &self.settings.allowed_transports;
  58. let scheme = endpoint.scheme();
  59. if !transports.contains(&scheme.to_string()) && self.settings.transport_mixing {
  60. if transports.contains(&"tor".to_string()) && scheme == "tcp" {
  61. endpoint.set_scheme("tor")?;
  62. } else if transports.contains(&"tor+tls".to_string()) && scheme == "tcp+tls" {
  63. endpoint.set_scheme("tor+tls")?;
  64. } else if transports.contains(&"nym".to_string()) && scheme == "tcp" {
  65. endpoint.set_scheme("nym")?;
  66. } else if transports.contains(&"nym+tls".to_string()) && scheme == "tcp+tls" {
  67. endpoint.set_scheme("nym+tls")?;
  68. }
  69. }
  70. let dialer = Dialer::new(endpoint.clone(), self.settings.datastore.clone()).await?;
  71. let timeout = Duration::from_secs(self.settings.outbound_connect_timeout);
  72. let stop_fut = async {
  73. self.stop_signal.wait().await;
  74. };
  75. let dial_fut = async { dialer.dial(Some(timeout)).await };
  76. pin_mut!(stop_fut);
  77. pin_mut!(dial_fut);
  78. match select(dial_fut, stop_fut).await {
  79. Either::Left((Ok(ptstream), _)) => {
  80. let channel = Channel::new(
  81. ptstream,
  82. Some(endpoint.clone()),
  83. url.clone(),
  84. self.session.clone(),
  85. )
  86. .await;
  87. Ok((endpoint, channel))
  88. }
  89. Either::Left((Err(e), _)) => {
  90. // If we get ENETUNREACH, we don't have IPv6 connectivity so note it down.
  91. if e.raw_os_error() == Some(libc::ENETUNREACH) {
  92. *self.session.upgrade().unwrap().p2p().hosts().ipv6_available.lock().unwrap() =
  93. false;
  94. }
  95. Err(e.into())
  96. }
  97. Either::Right((_, _)) => Err(Error::ConnectorStopped),
  98. }
  99. }
  100. pub(crate) fn stop(&self) {
  101. self.stop_signal.notify()
  102. }
  103. }