connector.rs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 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::time::Duration;
  19. use log::debug;
  20. use url::Url;
  21. use super::{
  22. channel::{Channel, ChannelPtr},
  23. session::SessionWeakPtr,
  24. settings::SettingsPtr,
  25. transport::Dialer,
  26. };
  27. use crate::{Error, Result};
  28. /// Create outbound socket connections
  29. pub struct Connector {
  30. /// P2P settings
  31. settings: SettingsPtr,
  32. /// Weak pointer to the session
  33. pub session: SessionWeakPtr,
  34. }
  35. impl Connector {
  36. /// Create a new connector with given network settings
  37. pub fn new(settings: SettingsPtr, session: SessionWeakPtr) -> Self {
  38. Self { settings, session }
  39. }
  40. /// Establish an outbound connection
  41. pub async fn connect(&self, url: &Url) -> Result<(Url, ChannelPtr)> {
  42. if self.session.upgrade().unwrap().p2p().hosts().is_rejected(url).await {
  43. debug!(target: "net::connector::connect", "Peer {} is rejected", url);
  44. return Err(Error::ConnectFailed)
  45. }
  46. let mut endpoint = url.clone();
  47. let transports = &self.settings.allowed_transports;
  48. let scheme = endpoint.scheme();
  49. if !transports.contains(&scheme.to_string()) && self.settings.transport_mixing {
  50. if transports.contains(&"tor".to_string()) && scheme == "tcp" {
  51. endpoint.set_scheme("tor")?;
  52. } else if transports.contains(&"tor+tls".to_string()) && scheme == "tcp+tls" {
  53. endpoint.set_scheme("tor+tls")?;
  54. } else if transports.contains(&"nym".to_string()) && scheme == "tcp" {
  55. endpoint.set_scheme("nym")?;
  56. } else if transports.contains(&"nym+tls".to_string()) && scheme == "tcp+tls" {
  57. endpoint.set_scheme("nym+tls")?;
  58. }
  59. }
  60. let dialer = Dialer::new(endpoint.clone()).await?;
  61. let timeout = Duration::from_secs(self.settings.outbound_connect_timeout);
  62. let ptstream = dialer.dial(Some(timeout)).await?;
  63. let channel = Channel::new(ptstream, endpoint.clone(), self.session.clone()).await;
  64. Ok((endpoint, channel))
  65. }
  66. }