protocol_foo.rs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2025 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::sync::Arc;
  19. use async_trait::async_trait;
  20. use tinyjson::JsonValue;
  21. use tracing::{debug, error, info};
  22. use darkfi::{
  23. impl_p2p_message,
  24. net::{
  25. metering::MeteringConfiguration,
  26. protocol::protocol_generic::{
  27. ProtocolGenericAction, ProtocolGenericHandler, ProtocolGenericHandlerPtr,
  28. },
  29. session::SESSION_DEFAULT,
  30. Message, P2pPtr,
  31. },
  32. rpc::jsonrpc::JsonSubscriber,
  33. system::ExecutorPtr,
  34. util::time::NanoTimestamp,
  35. Error, Result,
  36. };
  37. use darkfi_serial::{SerialDecodable, SerialEncodable};
  38. /// Structure represening a foo request.
  39. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  40. pub struct FooRequest {
  41. /// Request message
  42. pub message: String,
  43. }
  44. impl_p2p_message!(
  45. FooRequest,
  46. "foorequest",
  47. 0,
  48. 0,
  49. MeteringConfiguration { threshold: 0, sleep_step: 0, expiry_time: NanoTimestamp::from_secs(0) }
  50. );
  51. /// Structure representing the response to `FooRequest`.
  52. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  53. pub struct FooResponse {
  54. /// Response code
  55. pub code: u8,
  56. }
  57. impl_p2p_message!(
  58. FooResponse,
  59. "fooresponse",
  60. 0,
  61. 0,
  62. MeteringConfiguration { threshold: 0, sleep_step: 0, expiry_time: NanoTimestamp::from_secs(0) }
  63. );
  64. /// Atomic pointer to the `ProtocolFoo` handler.
  65. pub type ProtocolFooHandlerPtr = Arc<ProtocolFooHandler>;
  66. /// Handler managing all `ProtocolFoo` messages, over generic P2P protocols.
  67. pub struct ProtocolFooHandler {
  68. /// The generic handler for `FooRequest` messages.
  69. handler: ProtocolGenericHandlerPtr<FooRequest, FooResponse>,
  70. }
  71. impl ProtocolFooHandler {
  72. /// Initialize the generic prototocol handlers for all `ProtocolFoo` messages
  73. /// and register them to the provided P2P network, using the default session flag.
  74. pub async fn init(p2p: &P2pPtr) -> ProtocolFooHandlerPtr {
  75. debug!(
  76. target: "damd::proto::protocol_foo::init",
  77. "Adding all foo protocols to the protocol registry"
  78. );
  79. let handler = ProtocolGenericHandler::new(p2p, "ProtocolFoo", SESSION_DEFAULT).await;
  80. Arc::new(Self { handler })
  81. }
  82. /// Start all `ProtocolFoo` background tasks.
  83. pub async fn start(&self, executor: &ExecutorPtr, subscriber: JsonSubscriber) -> Result<()> {
  84. debug!(
  85. target: "damd::proto::protocol_foo::start",
  86. "Starting foo protocols handlers tasks..."
  87. );
  88. self.handler.task.clone().start(
  89. handle_receive_foo_request(self.handler.clone(), subscriber),
  90. |res| async move {
  91. match res {
  92. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  93. Err(e) => error!(target: "damd::proto::protocol_foo::start", "Failed starting ProtocolFoo handler task: {e}"),
  94. }
  95. },
  96. Error::DetachedTaskStopped,
  97. executor.clone(),
  98. );
  99. debug!(
  100. target: "damd::proto::protocol_foo::start",
  101. "Foo protocols handlers tasks started!"
  102. );
  103. Ok(())
  104. }
  105. /// Stop all `ProtocolSync` background tasks.
  106. pub async fn stop(&self) {
  107. debug!(target: "damd::proto::protocol_foo::stop", "Terminating foo protocols handlers tasks...");
  108. self.handler.task.stop().await;
  109. debug!(target: "damd::proto::protocol_foo::stop", "Foo protocols handlers tasks terminated!");
  110. }
  111. }
  112. /// Background handler function for ProtocolFoo.
  113. async fn handle_receive_foo_request(
  114. handler: ProtocolGenericHandlerPtr<FooRequest, FooResponse>,
  115. subscriber: JsonSubscriber,
  116. ) -> Result<()> {
  117. debug!(target: "damd::proto::protocol_foo::handle_receive_foo_request", "START");
  118. loop {
  119. // Wait for a new foo request message
  120. let (channel, request) = match handler.receiver.recv().await {
  121. Ok(r) => r,
  122. Err(e) => {
  123. debug!(
  124. target: "damd::proto::protocol_foo::handle_receive_foo_request",
  125. "recv fail: {e}"
  126. );
  127. continue
  128. }
  129. };
  130. let notification = format!("Received foo request from {channel}: {}", request.message);
  131. info!(target: "damd::proto::protocol_foo::handle_receive_foo_request", "{notification}");
  132. // Notify subscriber
  133. subscriber.notify(vec![JsonValue::String(notification)].into()).await;
  134. // Send response
  135. handler
  136. .send_action(channel, ProtocolGenericAction::Response(FooResponse { code: 42 }))
  137. .await;
  138. }
  139. }