connector.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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::{env, time::Duration};
  19. use async_std::sync::Arc;
  20. use log::error;
  21. use url::Url;
  22. use super::{
  23. transport::{TcpTransport, TorTransport, Transport, TransportName},
  24. Channel, ChannelPtr, SessionWeakPtr, SettingsPtr,
  25. };
  26. use crate::{Error, Result};
  27. /// Create outbound socket connections.
  28. pub struct Connector {
  29. settings: SettingsPtr,
  30. pub session: SessionWeakPtr,
  31. }
  32. impl Connector {
  33. /// Create a new connector with default network settings.
  34. pub fn new(settings: SettingsPtr, session: SessionWeakPtr) -> Self {
  35. Self { settings, session }
  36. }
  37. /// Establish an outbound connection.
  38. pub async fn connect(&self, connect_url: Url) -> Result<ChannelPtr> {
  39. let transport_name = TransportName::try_from(connect_url.clone())?;
  40. self.connect_channel(
  41. connect_url,
  42. transport_name,
  43. Duration::from_secs(self.settings.connect_timeout_seconds.into()),
  44. )
  45. .await
  46. }
  47. async fn connect_channel(
  48. &self,
  49. connect_url: Url,
  50. transport_name: TransportName,
  51. timeout: Duration,
  52. ) -> Result<Arc<Channel>> {
  53. macro_rules! connect {
  54. ($stream:expr, $transport:expr, $upgrade:expr) => {{
  55. if let Err(err) = $stream {
  56. error!(target: "net::connector", "Setup for {} failed: {}", connect_url, err);
  57. return Err(Error::ConnectFailed)
  58. }
  59. let stream = $stream?.await;
  60. if let Err(err) = stream {
  61. error!(target: "net::connector", "Connection to {} failed: {}", connect_url, err);
  62. return Err(Error::ConnectFailed)
  63. }
  64. let channel = match $upgrade {
  65. // session
  66. None => {
  67. Channel::new(Box::new(stream?), connect_url.clone(), self.session.clone())
  68. .await
  69. }
  70. Some(u) if u == "tls" => {
  71. let stream = $transport.upgrade_dialer(stream?)?.await;
  72. Channel::new(Box::new(stream?), connect_url, self.session.clone()).await
  73. }
  74. Some(u) => return Err(Error::UnsupportedTransportUpgrade(u)),
  75. };
  76. Ok(channel)
  77. }};
  78. }
  79. match transport_name {
  80. TransportName::Tcp(upgrade) => {
  81. let transport = TcpTransport::new(None, 1024);
  82. let stream = transport.dial(connect_url.clone(), Some(timeout));
  83. connect!(stream, transport, upgrade)
  84. }
  85. TransportName::Tor(upgrade) => {
  86. let socks5_url = Url::parse(
  87. &env::var("DARKFI_TOR_SOCKS5_URL")
  88. .unwrap_or_else(|_| "socks5://127.0.0.1:9050".to_string()),
  89. )?;
  90. let transport = TorTransport::new(socks5_url, None)?;
  91. let stream = transport.clone().dial(connect_url.clone(), None);
  92. connect!(stream, transport, upgrade)
  93. }
  94. _ => unimplemented!(),
  95. }
  96. }
  97. }