protocol_ping.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. use log::*;
  2. use rand::Rng;
  3. use smol::Executor;
  4. use std::{sync::Arc, time::Instant};
  5. use crate::{
  6. error::{Error, Result},
  7. net::{
  8. messages,
  9. protocols::{ProtocolJobsManager, ProtocolJobsManagerPtr},
  10. ChannelPtr, SettingsPtr,
  11. },
  12. util::sleep,
  13. };
  14. /// Defines ping and pong messages.
  15. pub struct ProtocolPing {
  16. channel: ChannelPtr,
  17. settings: SettingsPtr,
  18. jobsman: ProtocolJobsManagerPtr,
  19. }
  20. impl ProtocolPing {
  21. /// Create a new ping-pong protocol.
  22. pub fn new(channel: ChannelPtr, settings: SettingsPtr) -> Arc<Self> {
  23. Arc::new(Self {
  24. channel: channel.clone(),
  25. settings,
  26. jobsman: ProtocolJobsManager::new("ProtocolPing", channel),
  27. })
  28. }
  29. /// Starts ping-pong keep-alive messages exchange. Runs ping-pong in the
  30. /// protocol task manager, then queues the reply. Sends out a ping and
  31. /// waits for pong reply. Waits for ping and replies with a pong.
  32. pub async fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) {
  33. debug!(target: "net", "ProtocolPing::start() [START]");
  34. self.jobsman.clone().start(executor.clone());
  35. self.jobsman.clone().spawn(self.clone().run_ping_pong(), executor.clone()).await;
  36. self.jobsman.clone().spawn(self.reply_to_ping(), executor).await;
  37. debug!(target: "net", "ProtocolPing::start() [END]");
  38. }
  39. /// Runs ping-pong protocol. Creates a subscription to pong, then starts a
  40. /// loop. Loop sleeps for the duration of the channel heartbeat, then
  41. /// sends a ping message with a random nonce. Loop starts a timer, waits
  42. /// for the pong reply and insures the nonce is the same.
  43. async fn run_ping_pong(self: Arc<Self>) -> Result<()> {
  44. debug!(target: "net", "ProtocolPing::run_ping_pong() [START]");
  45. // Creates a subscription to pong message.
  46. let pong_sub = self
  47. .channel
  48. .clone()
  49. .subscribe_msg::<messages::PongMessage>()
  50. .await
  51. .expect("Missing pong dispatcher!");
  52. loop {
  53. // Wait channel_heartbeat amount of time.
  54. sleep(self.settings.channel_heartbeat_seconds).await;
  55. // Create a random nonce.
  56. let nonce = Self::random_nonce();
  57. // Send ping message.
  58. let ping = messages::PingMessage { nonce };
  59. self.channel.clone().send(ping).await?;
  60. debug!(target: "net", "ProtocolPing::run_ping_pong() send Ping message");
  61. // Start the timer for ping timer.
  62. let start = Instant::now();
  63. // Wait for pong, check nonce matches.
  64. let pong_msg = pong_sub.receive().await?;
  65. if pong_msg.nonce != nonce {
  66. error!("Wrong nonce for ping reply. Disconnecting from channel.");
  67. self.channel.stop().await;
  68. return Err(Error::ChannelStopped)
  69. }
  70. let duration = start.elapsed().as_millis();
  71. debug!(target: "net", "Received Pong message {}ms from [{:?}]", duration, self.channel.address());
  72. }
  73. }
  74. /// Waits for ping, then replies with pong. Copies ping's nonce into the
  75. /// pong reply.
  76. async fn reply_to_ping(self: Arc<Self>) -> Result<()> {
  77. debug!(target: "net", "ProtocolPing::reply_to_ping() [START]");
  78. // Creates a subscription to ping message.
  79. let ping_sub = self
  80. .channel
  81. .clone()
  82. .subscribe_msg::<messages::PingMessage>()
  83. .await
  84. .expect("Missing ping dispatcher!");
  85. loop {
  86. // Wait for ping, reply with pong that has a matching nonce.
  87. let ping = ping_sub.receive().await?;
  88. debug!(target: "net", "ProtocolPing::reply_to_ping() received Ping message");
  89. // Send pong message.
  90. let pong = messages::PongMessage { nonce: ping.nonce };
  91. self.channel.clone().send(pong).await?;
  92. debug!(target: "net", "ProtocolPing::reply_to_ping() sent Pong reply");
  93. }
  94. }
  95. fn random_nonce() -> u32 {
  96. let mut rng = rand::thread_rng();
  97. rng.gen()
  98. }
  99. }