mod.rs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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::{
  19. sync::{Arc, Weak},
  20. time::UNIX_EPOCH,
  21. };
  22. use async_trait::async_trait;
  23. use log::{debug, error};
  24. use smol::Executor;
  25. use super::{channel::ChannelPtr, p2p::P2pPtr, protocol::ProtocolVersion};
  26. use crate::Result;
  27. pub mod inbound_session;
  28. pub use inbound_session::{InboundSession, InboundSessionPtr};
  29. pub mod manual_session;
  30. pub use manual_session::{ManualSession, ManualSessionPtr};
  31. pub mod outbound_session;
  32. pub use outbound_session::{OutboundSession, OutboundSessionPtr};
  33. pub mod seedsync_session;
  34. pub use seedsync_session::{SeedSyncSession, SeedSyncSessionPtr};
  35. /// Bitwise selectors for the `protocol_registry`
  36. pub type SessionBitFlag = u32;
  37. pub const SESSION_INBOUND: SessionBitFlag = 0b0001;
  38. pub const SESSION_OUTBOUND: SessionBitFlag = 0b0010;
  39. pub const SESSION_MANUAL: SessionBitFlag = 0b0100;
  40. pub const SESSION_SEED: SessionBitFlag = 0b1000;
  41. pub const SESSION_ALL: SessionBitFlag = 0b1111;
  42. pub type SessionWeakPtr = Weak<dyn Session + Send + Sync + 'static>;
  43. /// Removes channel from the list of connected channels when a stop signal
  44. /// is received.
  45. pub async fn remove_sub_on_stop(p2p: P2pPtr, channel: ChannelPtr, type_id: SessionBitFlag) {
  46. debug!(target: "net::session::remove_sub_on_stop()", "[START]");
  47. // Subscribe to stop events
  48. let stop_sub = channel.clone().subscribe_stop().await;
  49. if let Ok(stop_sub) = stop_sub {
  50. // Wait for a stop event
  51. stop_sub.receive().await;
  52. }
  53. debug!(
  54. target: "net::session::remove_sub_on_stop()",
  55. "Received stop event. Removing channel {}", channel.address(),
  56. );
  57. if type_id != SESSION_INBOUND {
  58. match p2p.hosts().get_anchorlist_index_at_addr(channel.address()).await {
  59. Ok(index) => p2p.hosts().anchorlist_remove(channel.address(), index).await,
  60. Err(e) => {
  61. error!(target: "net::session::remove_sub_on_stop()",
  62. "Can't remove anchor connection {}", e)
  63. }
  64. }
  65. }
  66. // Remove channel from p2p
  67. p2p.remove(channel).await;
  68. debug!(target: "net::session::remove_sub_on_stop()", "[END]");
  69. }
  70. /// Session trait. Defines methods that are used across sessions.
  71. /// Implements registering the channel and initializing the channel by
  72. /// performing a network handshake.
  73. #[async_trait]
  74. pub trait Session: Sync {
  75. /// Registers a new channel with the session.
  76. /// Performs a network handshake and starts the channel.
  77. /// If we need to pass `Self` as an `Arc` we can do so like this:
  78. /// ```
  79. /// pub trait MyTrait: Send + Sync {
  80. /// async fn foo(&self, self_: Arc<dyn MyTrait>) {}
  81. /// }
  82. /// ```
  83. async fn register_channel(
  84. &self,
  85. channel: ChannelPtr,
  86. executor: Arc<Executor<'_>>,
  87. ) -> Result<()> {
  88. debug!(target: "net::session::register_channel()", "[START]");
  89. // Protocols should all be initialized but not started.
  90. // We do this so that the protocols can begin receiving and buffering
  91. // messages while the handshake protocol is ongoing. They are currently
  92. // in sleep mode.
  93. let p2p = self.p2p();
  94. let protocols =
  95. p2p.protocol_registry().attach(self.type_id(), channel.clone(), p2p.clone()).await;
  96. // Perform the handshake protocol
  97. let protocol_version = ProtocolVersion::new(channel.clone(), p2p.settings().clone()).await;
  98. debug!(target: "net::session::register_channel()", "register_channel {}", channel.clone().address());
  99. let handshake_task =
  100. self.perform_handshake_protocols(protocol_version, channel.clone(), executor.clone());
  101. // Switch on the channel
  102. channel.start(executor.clone());
  103. // Wait for handshake to finish.
  104. handshake_task.await?;
  105. // Now the channel is ready
  106. debug!(target: "net::session::register_channel()", "Session handshake complete");
  107. debug!(target: "net::session::register_channel()", "Activating remaining protocols");
  108. // Now start all the protocols. They are responsible for managing their own
  109. // lifetimes and correctly selfdestructing when the channel ends.
  110. for protocol in protocols {
  111. protocol.start(executor.clone()).await?;
  112. }
  113. debug!(target: "net::session::register_channel()", "[END]");
  114. Ok(())
  115. }
  116. /// Performs network handshake to initialize channel. Adds the channel to
  117. /// the list of connected channels, and prepares to remove the channel when
  118. /// a stop signal is received.
  119. async fn perform_handshake_protocols(
  120. &self,
  121. protocol_version: Arc<ProtocolVersion>,
  122. channel: ChannelPtr,
  123. executor: Arc<Executor<'_>>,
  124. ) -> Result<()> {
  125. // Perform handshake
  126. protocol_version.run(executor.clone()).await?;
  127. if self.type_id() != SESSION_INBOUND {
  128. // Channel is now initialized. Timestamp this.
  129. let last_seen = UNIX_EPOCH.elapsed().unwrap().as_secs();
  130. self.p2p()
  131. .hosts()
  132. .anchorlist_store_or_update(&[(channel.address().clone(), last_seen)])
  133. .await?;
  134. }
  135. // Add channel to p2p
  136. self.p2p().store(channel.clone()).await;
  137. // Subscribe to stop, so we can remove from p2p
  138. executor.spawn(remove_sub_on_stop(self.p2p(), channel, self.type_id())).detach();
  139. // Channel is ready for use
  140. Ok(())
  141. }
  142. /// Returns a pointer to the p2p network interface
  143. fn p2p(&self) -> P2pPtr;
  144. /// Return the session bit flag for the session type
  145. fn type_id(&self) -> SessionBitFlag;
  146. }