client.rs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2022 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. //! JSON-RPC client-side implementation.
  19. use std::time::Duration;
  20. use async_std::io::timeout;
  21. use futures::{select, AsyncReadExt, AsyncWriteExt, FutureExt};
  22. use log::{debug, error};
  23. use serde_json::{json, Value};
  24. use url::Url;
  25. use super::jsonrpc::{ErrorCode, JsonError, JsonRequest, JsonResult};
  26. use crate::{
  27. net::transport::{
  28. TcpTransport, TorTransport, Transport, TransportName, TransportStream, UnixTransport,
  29. },
  30. Error, Result,
  31. };
  32. /// JSON-RPC client implementation using asynchronous channels.
  33. pub struct RpcClient {
  34. send: smol::channel::Sender<Value>,
  35. recv: smol::channel::Receiver<JsonResult>,
  36. stop_signal: smol::channel::Sender<()>,
  37. url: Url,
  38. }
  39. impl RpcClient {
  40. /// Instantiate a new JSON-RPC client that will connect to the given URL.
  41. pub async fn new(url: Url) -> Result<Self> {
  42. let (send, recv, stop_signal) = Self::open_channels(&url).await?;
  43. Ok(Self { send, recv, stop_signal, url })
  44. }
  45. /// Close the channels of an instantiated [`RpcClient`].
  46. pub async fn close(&self) -> Result<()> {
  47. self.stop_signal.send(()).await?;
  48. Ok(())
  49. }
  50. /// Send a given JSON-RPC request over the instantiated client.
  51. pub async fn request(&self, value: JsonRequest) -> Result<Value> {
  52. let req_id = value.id.clone().as_u64().unwrap();
  53. debug!(target: "jsonrpc-client", "--> {}", serde_json::to_string(&value)?);
  54. // If the connection is closed, the sender will get an error for
  55. // sending to a closed channel.
  56. if let Err(e) = self.send.send(json!(value)).await {
  57. error!("JSON-RPC client unable to send to {} (channels closed): {}", self.url, e);
  58. return Err(Error::NetworkOperationFailed)
  59. }
  60. // If the connection is closed, the receiver will get an error for
  61. // waiting on a closed channel.
  62. let reply = self.recv.recv().await;
  63. if reply.is_err() {
  64. error!("JSON-RPC client unable to recv from {} (channels closed)", self.url);
  65. return Err(Error::NetworkOperationFailed)
  66. }
  67. match reply? {
  68. JsonResult::Response(r) => {
  69. // Check if the IDs match
  70. let resp_id = r.id.as_u64();
  71. if resp_id.is_none() {
  72. let e = JsonError::new(ErrorCode::InvalidId, None, r.id);
  73. //self.stop_signal.send(()).await?;
  74. return Err(Error::JsonRpcError(e.error.message.to_string()))
  75. }
  76. if resp_id.unwrap() != req_id {
  77. let e = JsonError::new(ErrorCode::InvalidId, None, r.id);
  78. //self.stop_signal.send(()).await?;
  79. return Err(Error::JsonRpcError(e.error.message.to_string()))
  80. }
  81. debug!(target: "jsonrpc-client", "<-- {}", serde_json::to_string(&r)?);
  82. Ok(r.result)
  83. }
  84. JsonResult::Error(e) => {
  85. debug!(target: "jsonrpc-client", "<-- {}", serde_json::to_string(&e)?);
  86. // Close the server connection
  87. //self.stop_signal.send(()).await?;
  88. Err(Error::JsonRpcError(e.error.message.to_string()))
  89. }
  90. JsonResult::Notification(n) => {
  91. debug!(target: "jsonrpc-client", "<-- {}", serde_json::to_string(&n)?);
  92. // Close the server connection
  93. //self.stop_signal.send(()).await?;
  94. Err(Error::JsonRpcError("Unexpected reply".to_string()))
  95. }
  96. }
  97. }
  98. /// Oneshot send a given JSON-RPC request over the instantiated client
  99. /// and close the channels on reply.
  100. pub async fn oneshot_request(&self, value: JsonRequest) -> Result<Value> {
  101. let rep = self.request(value).await?;
  102. self.stop_signal.send(()).await?;
  103. Ok(rep)
  104. }
  105. /// Instantiate channels for a new [`RpcClient`].
  106. async fn open_channels(
  107. uri: &Url,
  108. ) -> Result<(
  109. smol::channel::Sender<Value>,
  110. smol::channel::Receiver<JsonResult>,
  111. smol::channel::Sender<()>,
  112. )> {
  113. let (data_send, data_recv) = smol::channel::unbounded();
  114. let (result_send, result_recv) = smol::channel::unbounded();
  115. let (stop_send, stop_recv) = smol::channel::unbounded();
  116. let transport_name = TransportName::try_from(uri.clone())?;
  117. macro_rules! reqrep {
  118. ($stream:expr, $transport:expr, $upgrade:expr) => {{
  119. if let Err(err) = $stream {
  120. error!("JSON-RPC client setup for {} failed: {}", uri, err);
  121. return Err(Error::ConnectFailed)
  122. }
  123. let stream = $stream?.await;
  124. if let Err(err) = stream {
  125. error!("JSON-RPC client connection to {} failed: {}", uri, err);
  126. return Err(Error::ConnectFailed)
  127. }
  128. let stream = stream?;
  129. match $upgrade {
  130. None => {
  131. smol::spawn(Self::reqrep_loop(stream, result_send, data_recv, stop_recv))
  132. .detach();
  133. }
  134. Some(u) if u == "tls" => {
  135. let stream = $transport.upgrade_dialer(stream)?.await?;
  136. smol::spawn(Self::reqrep_loop(stream, result_send, data_recv, stop_recv))
  137. .detach();
  138. }
  139. Some(u) => return Err(Error::UnsupportedTransportUpgrade(u)),
  140. }
  141. }};
  142. }
  143. match transport_name {
  144. TransportName::Tcp(upgrade) => {
  145. let transport = TcpTransport::new(None, 1024);
  146. let stream = transport.dial(uri.clone(), None);
  147. reqrep!(stream, transport, upgrade);
  148. }
  149. TransportName::Tor(upgrade) => {
  150. let socks5_url = TorTransport::get_dialer_env()?;
  151. let transport = TorTransport::new(socks5_url, None)?;
  152. let stream = transport.clone().dial(uri.clone(), None);
  153. reqrep!(stream, transport, upgrade);
  154. }
  155. TransportName::Unix => {
  156. let transport = UnixTransport::new();
  157. let stream = transport.dial(uri.clone()).await;
  158. if let Err(err) = stream {
  159. error!("JSON-RPC client connection to {} failed: {}", uri, err);
  160. return Err(Error::ConnectFailed)
  161. }
  162. smol::spawn(Self::reqrep_loop(stream?, result_send, data_recv, stop_recv)).detach();
  163. }
  164. _ => unimplemented!(),
  165. }
  166. Ok((data_send, result_recv, stop_send))
  167. }
  168. /// Internal function that loops on a given stream and multiplexes the data.
  169. async fn reqrep_loop<T: TransportStream>(
  170. mut stream: T,
  171. result_send: smol::channel::Sender<JsonResult>,
  172. data_recv: smol::channel::Receiver<Value>,
  173. stop_recv: smol::channel::Receiver<()>,
  174. ) -> Result<()> {
  175. // If we don't get a reply within 30 seconds, we'll fail.
  176. let read_timeout = Duration::from_secs(30);
  177. loop {
  178. // FIXME: Nasty size. 8M
  179. let mut buf = vec![0; 1024 * 8192];
  180. select! {
  181. data = data_recv.recv().fuse() => {
  182. let data_bytes = serde_json::to_vec(&data?)?;
  183. stream.write_all(&data_bytes).await?;
  184. let n = timeout(read_timeout, async { stream.read(&mut buf[..]).await }).await?;
  185. let reply: JsonResult = serde_json::from_slice(&buf[0..n])?;
  186. result_send.send(reply).await?;
  187. }
  188. _ = stop_recv.recv().fuse() => break
  189. }
  190. }
  191. Ok(())
  192. }
  193. }