manual_session.rs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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 async_std::sync::{Arc, Mutex, Weak};
  19. use async_trait::async_trait;
  20. use log::{info, warn};
  21. use serde_json::json;
  22. use smol::Executor;
  23. use url::Url;
  24. use crate::{
  25. net::transport::TransportName,
  26. system::{StoppableTask, StoppableTaskPtr, Subscriber, SubscriberPtr, Subscription},
  27. util::async_util::sleep,
  28. Error, Result,
  29. };
  30. use super::{
  31. super::{ChannelPtr, Connector, P2p},
  32. Session, SessionBitflag, SESSION_MANUAL,
  33. };
  34. pub struct ManualSession {
  35. p2p: Weak<P2p>,
  36. connect_slots: Mutex<Vec<StoppableTaskPtr>>,
  37. /// Subscriber used to signal channels processing
  38. channel_subscriber: SubscriberPtr<Result<ChannelPtr>>,
  39. /// Flag to toggle channel_subscriber notifications
  40. notify: Mutex<bool>,
  41. }
  42. impl ManualSession {
  43. /// Create a new inbound session.
  44. pub fn new(p2p: Weak<P2p>) -> Arc<Self> {
  45. Arc::new(Self {
  46. p2p,
  47. connect_slots: Mutex::new(Vec::new()),
  48. channel_subscriber: Subscriber::new(),
  49. notify: Mutex::new(false),
  50. })
  51. }
  52. /// Stop the outbound session.
  53. pub async fn stop(&self) {
  54. let connect_slots = &*self.connect_slots.lock().await;
  55. for slot in connect_slots {
  56. slot.stop().await;
  57. }
  58. }
  59. pub async fn connect(self: Arc<Self>, addr: &Url, executor: Arc<Executor<'_>>) {
  60. let task = StoppableTask::new();
  61. task.clone().start(
  62. self.clone().channel_connect_loop(addr.clone(), executor.clone()),
  63. // Ignore stop handler
  64. |_| async {},
  65. Error::NetworkServiceStopped,
  66. executor.clone(),
  67. );
  68. self.connect_slots.lock().await.push(task);
  69. }
  70. pub async fn channel_connect_loop(
  71. self: Arc<Self>,
  72. addr: Url,
  73. executor: Arc<Executor<'_>>,
  74. ) -> Result<()> {
  75. let parent = Arc::downgrade(&self);
  76. let settings = self.p2p().settings();
  77. let connector = Connector::new(settings.clone(), Arc::new(parent));
  78. let attempts = settings.manual_attempt_limit;
  79. let mut remaining = attempts;
  80. // Retrieve preferent outbound transports
  81. let outbound_transports = &settings.outbound_transports;
  82. // Check that addr transport is in configured outbound transport
  83. let addr_transport = TransportName::try_from(addr.clone())?;
  84. let transports = if outbound_transports.contains(&addr_transport) {
  85. vec![addr_transport]
  86. } else {
  87. warn!(target: "net::manual_session", "Manual outbound address {} transport is not in accepted outbound transports, will try with: {:?}", addr, outbound_transports);
  88. outbound_transports.clone()
  89. };
  90. loop {
  91. // Loop forever if attempts is 0
  92. // Otherwise loop attempts number of times
  93. remaining = if attempts == 0 { 1 } else { remaining - 1 };
  94. if remaining == 0 {
  95. break
  96. }
  97. self.p2p().add_pending(addr.clone()).await;
  98. for transport in &transports {
  99. // Replace addr transport
  100. let mut transport_addr = addr.clone();
  101. transport_addr.set_scheme(&transport.to_scheme())?;
  102. info!(target: "net::manual_session", "Connecting to manual outbound [{}]", transport_addr);
  103. match connector.connect(transport_addr.clone()).await {
  104. Ok(channel) => {
  105. // Blacklist goes here
  106. info!(target: "net::manual_session", "Connected to manual outbound [{}]", transport_addr);
  107. let stop_sub = channel.subscribe_stop().await;
  108. if stop_sub.is_err() {
  109. continue
  110. }
  111. self.clone().register_channel(channel.clone(), executor.clone()).await?;
  112. // Channel is now connected but not yet setup
  113. // Remove pending lock since register_channel will add the channel to p2p
  114. self.p2p().remove_pending(&addr).await;
  115. //self.clone().attach_protocols(channel, executor.clone()).await?;
  116. // Notify that channel processing has been finished
  117. if *self.notify.lock().await {
  118. self.channel_subscriber.notify(Ok(channel)).await;
  119. }
  120. // Wait for channel to close
  121. stop_sub.unwrap().receive().await;
  122. }
  123. Err(err) => {
  124. info!(target: "net::manual_session", "Unable to connect to manual outbound [{}]: {}", addr, err);
  125. }
  126. }
  127. }
  128. // Notify that channel processing has been finished (failed)
  129. if *self.notify.lock().await {
  130. self.channel_subscriber.notify(Err(Error::ConnectFailed)).await;
  131. }
  132. sleep(settings.connect_timeout_seconds.into()).await;
  133. }
  134. warn!(
  135. target: "net::manual_session",
  136. "Suspending manual connection to [{}] after {} failed attempts.",
  137. &addr,
  138. attempts
  139. );
  140. Ok(())
  141. }
  142. /// Subscribe to a channel.
  143. pub async fn subscribe_channel(&self) -> Subscription<Result<ChannelPtr>> {
  144. self.channel_subscriber.clone().subscribe().await
  145. }
  146. /// Enable channel_subscriber notifications.
  147. pub async fn enable_notify(self: Arc<Self>) {
  148. *self.notify.lock().await = true;
  149. }
  150. /// Disable channel_subscriber notifications.
  151. pub async fn disable_notify(self: Arc<Self>) {
  152. *self.notify.lock().await = false;
  153. }
  154. // Starts sending keep-alive and address messages across the channels.
  155. /*async fn attach_protocols(
  156. self: Arc<Self>,
  157. channel: ChannelPtr,
  158. executor: Arc<Executor<'_>>,
  159. ) -> Result<()> {
  160. let hosts = self.p2p().hosts();
  161. let protocol_ping = ProtocolPing::new(channel.clone(), self.p2p());
  162. let protocol_addr = ProtocolAddress::new(channel, hosts).await;
  163. protocol_ping.start(executor.clone()).await;
  164. protocol_addr.start(executor).await;
  165. Ok(())
  166. }*/
  167. }
  168. #[async_trait]
  169. impl Session for ManualSession {
  170. async fn get_info(&self) -> serde_json::Value {
  171. json!({
  172. "key": 110
  173. })
  174. }
  175. fn p2p(&self) -> Arc<P2p> {
  176. self.p2p.upgrade().unwrap()
  177. }
  178. fn type_id(&self) -> SessionBitflag {
  179. SESSION_MANUAL
  180. }
  181. }