server.rs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 async_std::sync::Arc;
  19. use async_trait::async_trait;
  20. use log::{debug, error, info};
  21. use tinyjson::JsonValue;
  22. use url::Url;
  23. use super::{
  24. common::{read_from_stream, write_to_stream, INIT_BUF_SIZE},
  25. jsonrpc::*,
  26. };
  27. use crate::{
  28. net::transport::{Listener, PtListener, PtStream},
  29. Result,
  30. };
  31. /// Asynchronous trait implementing a handler for incoming JSON-RPC requests.
  32. #[async_trait]
  33. pub trait RequestHandler: Sync + Send {
  34. async fn handle_request(&self, req: JsonRequest) -> JsonResult;
  35. async fn pong(&self, id: u16, _params: JsonValue) -> JsonResult {
  36. JsonResponse::new(JsonValue::String("pong".to_string()), id).into()
  37. }
  38. }
  39. /// Accept function that should run inside a loop for accepting incoming
  40. /// JSON-RPC requests and passing them to the [`RequestHandler`].
  41. pub async fn accept(
  42. mut stream: Box<dyn PtStream>,
  43. addr: Url,
  44. rh: Arc<impl RequestHandler + 'static>,
  45. ) -> Result<()> {
  46. loop {
  47. let mut buf = Vec::with_capacity(INIT_BUF_SIZE);
  48. let _ = read_from_stream(&mut stream, &mut buf, false).await?;
  49. let val: JsonValue = String::from_utf8(buf)?.parse()?;
  50. let req = JsonRequest::try_from(&val)?;
  51. debug!(target: "rpc::server", "{} --> {}", addr, val.stringify()?);
  52. let rep = rh.handle_request(req).await;
  53. match rep {
  54. JsonResult::Subscriber(subscriber) => {
  55. // Subscribe to the inner method subscriber
  56. let subscription = subscriber.sub.subscribe().await;
  57. loop {
  58. // Listen for notifications
  59. let notification = subscription.receive().await;
  60. // Push notification
  61. debug!(target: "rpc::server", "{} <-- {}", addr, notification.stringify()?);
  62. let notification = JsonResult::Notification(notification);
  63. if let Err(e) = write_to_stream(&mut stream, &notification).await {
  64. subscription.unsubscribe().await;
  65. return Err(e)
  66. }
  67. }
  68. }
  69. JsonResult::Request(_) | JsonResult::Notification(_) => {
  70. unreachable!("Should never happen")
  71. }
  72. JsonResult::Response(ref v) => {
  73. debug!(target: "rpc::server", "{} <-- {}", addr, v.stringify()?);
  74. write_to_stream(&mut stream, &rep).await?;
  75. }
  76. JsonResult::Error(ref v) => {
  77. debug!(target: "rpc::server", "{} <-- {}", addr, v.stringify()?);
  78. write_to_stream(&mut stream, &rep).await?;
  79. }
  80. }
  81. }
  82. }
  83. /// Wrapper function around [`accept()`] to take the incoming connection and
  84. /// pass it forward.
  85. async fn run_accept_loop(
  86. listener: Box<dyn PtListener>,
  87. rh: Arc<impl RequestHandler + 'static>,
  88. ex: Arc<smol::Executor<'_>>,
  89. ) -> Result<()> {
  90. while let Ok((stream, peer_addr)) = listener.next().await {
  91. info!(target: "rpc::server", "[RPC] Server accepted conn from {}", peer_addr);
  92. // Detaching requests handling
  93. let rh_ = rh.clone();
  94. ex.spawn(async move {
  95. if let Err(e) = accept(stream, peer_addr.clone(), rh_).await {
  96. if e.to_string().as_str() == "Connection closed cleanly" {
  97. info!(
  98. target: "rpc::server",
  99. "[RPC] Closed connection from {}",
  100. peer_addr,
  101. );
  102. } else {
  103. error!(
  104. target: "rpc::server",
  105. "[RPC] Server error on handling request from {}: {}",
  106. peer_addr, e,
  107. );
  108. }
  109. }
  110. })
  111. .detach();
  112. }
  113. // NOTE: This is here now to catch some code path. Will be handled properly.
  114. panic!("RPC server listener stopped/crashed");
  115. }
  116. /// Start a JSON-RPC server bound to the given accept URL and use the
  117. /// given [`RequestHandler`] to handle incoming requests.
  118. pub async fn listen_and_serve(
  119. accept_url: Url,
  120. rh: Arc<impl RequestHandler + 'static>,
  121. ex: Arc<smol::Executor<'_>>,
  122. ) -> Result<()> {
  123. let listener = Listener::new(accept_url).await?.listen().await?;
  124. run_accept_loop(listener, rh, ex.clone()).await
  125. }