rpcclient.rs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. use async_std::sync::Arc;
  2. use async_executor::Executor;
  3. use log::{debug, error};
  4. use serde_json::{json, Value};
  5. use url::Url;
  6. use crate::{Error, Result};
  7. use super::jsonrpc::{self, ErrorCode, JsonRequest, JsonResult};
  8. pub struct RpcClient {
  9. sender: async_channel::Sender<Value>,
  10. receiver: async_channel::Receiver<JsonResult>,
  11. stop_signal: async_channel::Sender<()>,
  12. }
  13. impl RpcClient {
  14. pub async fn new(url: Url, executor: Arc<Executor<'_>>) -> Result<Self> {
  15. let (sender, receiver, stop_signal) = jsonrpc::open_channels(&url, executor).await?;
  16. Ok(Self { sender, receiver, stop_signal })
  17. }
  18. pub async fn request(&self, value: JsonRequest) -> Result<Value> {
  19. let req_id = value.id.clone().as_u64().unwrap_or(0);
  20. let value = json!(value);
  21. self.sender.send(value).await?;
  22. let reply = self.receiver.recv().await;
  23. // if the connection is closed the receiver will get an error
  24. // for waiting closed channel
  25. if reply.is_err() {
  26. error!("Unable to connect to the RPC server");
  27. return Err(Error::OperationFailed)
  28. }
  29. match reply? {
  30. JsonResult::Resp(r) => {
  31. // check if the ids match
  32. let resp_id = r.id.as_u64();
  33. if resp_id.is_none() {
  34. let error = jsonrpc::error(ErrorCode::InvalidId, None, r.id);
  35. self.stop_signal.send(()).await?;
  36. return Err(Error::JsonRpcError(error.error.message.to_string()))
  37. }
  38. if resp_id.unwrap() != req_id {
  39. let error = jsonrpc::error(
  40. ErrorCode::InvalidId,
  41. Some("Ids doesn't match".into()),
  42. r.id,
  43. );
  44. self.stop_signal.send(()).await?;
  45. return Err(Error::JsonRpcError(error.error.message.to_string()))
  46. }
  47. debug!(target: "RPC", "<-- {}", serde_json::to_string(&r)?);
  48. Ok(r.result)
  49. }
  50. JsonResult::Err(e) => {
  51. debug!(target: "RPC", "<-- {}", serde_json::to_string(&e)?);
  52. // close the server connection
  53. self.stop_signal.send(()).await?;
  54. Err(Error::JsonRpcError(e.error.message.to_string()))
  55. }
  56. JsonResult::Notif(n) => {
  57. debug!(target: "RPC", "<-- {}", serde_json::to_string(&n)?);
  58. Err(Error::JsonRpcError("Unexpected reply".to_string()))
  59. }
  60. }
  61. }
  62. }