outbound_session.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. use async_executor::Executor;
  2. use async_std::sync::Mutex;
  3. use log::*;
  4. use std::net::SocketAddr;
  5. use std::sync::{Arc, Weak};
  6. use crate::net::error::{NetError, NetResult};
  7. use crate::net::protocols::{ProtocolAddress, ProtocolPing};
  8. use crate::net::sessions::Session;
  9. use crate::net::{ChannelPtr, Connector, P2p};
  10. use crate::system::{StoppableTask, StoppableTaskPtr};
  11. pub struct OutboundSession {
  12. p2p: Weak<P2p>,
  13. connect_slots: Mutex<Vec<StoppableTaskPtr>>,
  14. }
  15. impl OutboundSession {
  16. pub fn new(p2p: Weak<P2p>) -> Arc<Self> {
  17. Arc::new(Self {
  18. p2p,
  19. connect_slots: Mutex::new(Vec::new()),
  20. })
  21. }
  22. pub async fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) -> NetResult<()> {
  23. let slots_count = self.p2p().settings().outbound_connections;
  24. info!("Starting {} outbound connection slots.", slots_count);
  25. let mut connect_slots = self.connect_slots.lock().await;
  26. for i in 0..slots_count {
  27. let task = StoppableTask::new();
  28. task.clone().start(
  29. self.clone().channel_connect_loop(i, executor.clone()),
  30. // Ignore stop handler
  31. |_| async {},
  32. NetError::ServiceStopped,
  33. executor.clone(),
  34. );
  35. connect_slots.push(task);
  36. }
  37. Ok(())
  38. }
  39. pub async fn stop(&self) {
  40. let connect_slots = &*self.connect_slots.lock().await;
  41. for slot in connect_slots {
  42. slot.stop().await;
  43. }
  44. }
  45. pub async fn channel_connect_loop(
  46. self: Arc<Self>,
  47. slot_number: u32,
  48. executor: Arc<Executor<'_>>,
  49. ) -> NetResult<()> {
  50. let connector = Connector::new(self.p2p().settings().clone());
  51. loop {
  52. let addr = self.load_address(slot_number).await?;
  53. info!("#{} connecting to outbound [{}]", slot_number, addr);
  54. match connector.connect(addr).await {
  55. Ok(channel) => {
  56. // Blacklist goes here
  57. info!("#{} connected to outbound [{}]", slot_number, addr);
  58. let stop_sub = channel.subscribe_stop().await;
  59. self.clone()
  60. .register_channel(channel.clone(), executor.clone())
  61. .await?;
  62. self.clone()
  63. .attach_protocols(channel, executor.clone())
  64. .await?;
  65. // Wait for channel to close
  66. stop_sub.receive().await;
  67. }
  68. Err(err) => {
  69. info!("Unable to connect to outbound [{}]: {}", addr, err);
  70. }
  71. }
  72. }
  73. }
  74. async fn load_address(&self, slot_number: u32) -> NetResult<SocketAddr> {
  75. let hosts = self.p2p().hosts();
  76. let inbound_addr = self.p2p().settings().inbound;
  77. loop {
  78. match hosts.load_single().await {
  79. Some(addr) => match inbound_addr {
  80. Some(inbound_addr) => {
  81. if inbound_addr != addr {
  82. return Ok(addr);
  83. }
  84. }
  85. None => {
  86. return Ok(addr);
  87. }
  88. },
  89. None => {
  90. error!(
  91. "Hosts address pool is empty. Closing connect slot #{}",
  92. slot_number
  93. );
  94. return Err(NetError::ServiceStopped);
  95. }
  96. }
  97. }
  98. }
  99. async fn attach_protocols(
  100. self: Arc<Self>,
  101. channel: ChannelPtr,
  102. executor: Arc<Executor<'_>>,
  103. ) -> NetResult<()> {
  104. let settings = self.p2p().settings().clone();
  105. let hosts = self.p2p().hosts().clone();
  106. let protocol_ping = ProtocolPing::new(channel.clone(), settings.clone());
  107. let protocol_addr = ProtocolAddress::new(channel, hosts, settings).await;
  108. protocol_ping.start(executor.clone()).await;
  109. protocol_addr.start(executor).await;
  110. Ok(())
  111. }
  112. }
  113. impl Session for OutboundSession {
  114. fn p2p(&self) -> Arc<P2p> {
  115. self.p2p.upgrade().unwrap()
  116. }
  117. }