manual_session.rs 6.3 KB

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