jsonrpc.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. use std::{env, str, time::Duration};
  2. use async_std::io::timeout;
  3. use futures::{select, AsyncReadExt, AsyncWriteExt, FutureExt};
  4. use log::error;
  5. use rand::Rng;
  6. use serde::{Deserialize, Serialize};
  7. use serde_json::{json, Value};
  8. use url::Url;
  9. use crate::{
  10. net::{TcpTransport, TorTransport, Transport, TransportName, TransportStream, UnixTransport},
  11. Error, Result,
  12. };
  13. #[derive(Debug, Clone)]
  14. pub enum ErrorCode {
  15. ParseError,
  16. InvalidRequest,
  17. MethodNotFound,
  18. InvalidParams,
  19. InternalError,
  20. KeyGenError,
  21. GetAddressesError,
  22. ImportAndExportFile,
  23. SetDefaultAddress,
  24. InvalidAmountParam,
  25. InvalidNetworkParam,
  26. InvalidTokenIdParam,
  27. InvalidAddressParam,
  28. InvalidSymbolParam,
  29. InvalidId,
  30. ServerError(i64),
  31. }
  32. impl ErrorCode {
  33. pub fn code(&self) -> i64 {
  34. match *self {
  35. ErrorCode::ParseError => -32700,
  36. ErrorCode::InvalidRequest => -32600,
  37. ErrorCode::MethodNotFound => -32601,
  38. ErrorCode::InvalidParams => -32602,
  39. ErrorCode::InternalError => -32603,
  40. ErrorCode::KeyGenError => -32002,
  41. ErrorCode::GetAddressesError => -32003,
  42. ErrorCode::ImportAndExportFile => -32004,
  43. ErrorCode::SetDefaultAddress => -32005,
  44. ErrorCode::InvalidAmountParam => -32010,
  45. ErrorCode::InvalidNetworkParam => -32011,
  46. ErrorCode::InvalidTokenIdParam => -32012,
  47. ErrorCode::InvalidAddressParam => -32013,
  48. ErrorCode::InvalidSymbolParam => -32014,
  49. ErrorCode::InvalidId => -32030,
  50. ErrorCode::ServerError(c) => c,
  51. }
  52. }
  53. pub fn description(&self) -> String {
  54. let desc = match *self {
  55. ErrorCode::ParseError => "Parse error",
  56. ErrorCode::InvalidRequest => "Invalid request",
  57. ErrorCode::MethodNotFound => "Method not found",
  58. ErrorCode::InvalidParams => "Invalid params",
  59. ErrorCode::InternalError => "Internal error",
  60. ErrorCode::KeyGenError => "Key gen error",
  61. ErrorCode::GetAddressesError => "get addresses error",
  62. ErrorCode::ImportAndExportFile => "error import/export a file",
  63. ErrorCode::SetDefaultAddress => "error set default address",
  64. ErrorCode::InvalidAmountParam => "Invalid amount param",
  65. ErrorCode::InvalidNetworkParam => "Invalid network param",
  66. ErrorCode::InvalidTokenIdParam => "Invalid token id param",
  67. ErrorCode::InvalidAddressParam => "Invalid address param",
  68. ErrorCode::InvalidSymbolParam => "Invalid symbol param",
  69. ErrorCode::InvalidId => "Invalid Id",
  70. ErrorCode::ServerError(_) => "Server error",
  71. };
  72. desc.to_string()
  73. }
  74. }
  75. #[derive(Serialize, Deserialize, Clone, Debug)]
  76. #[serde(untagged)]
  77. pub enum JsonResult {
  78. Resp(JsonResponse),
  79. Err(JsonError),
  80. Notif(JsonNotification),
  81. }
  82. impl From<JsonResponse> for JsonResult {
  83. fn from(resp: JsonResponse) -> Self {
  84. Self::Resp(resp)
  85. }
  86. }
  87. impl From<JsonError> for JsonResult {
  88. fn from(err: JsonError) -> Self {
  89. Self::Err(err)
  90. }
  91. }
  92. impl From<JsonNotification> for JsonResult {
  93. fn from(notif: JsonNotification) -> Self {
  94. Self::Notif(notif)
  95. }
  96. }
  97. #[derive(Serialize, Deserialize, Clone, Debug)]
  98. pub struct JsonRequest {
  99. pub jsonrpc: Value,
  100. pub method: Value,
  101. pub params: Value,
  102. pub id: Value,
  103. }
  104. #[derive(Serialize, Deserialize, Clone, Debug)]
  105. pub struct JsonErrorVal {
  106. pub code: Value,
  107. pub message: Value,
  108. }
  109. #[derive(Serialize, Deserialize, Clone, Debug)]
  110. pub struct JsonError {
  111. pub jsonrpc: Value,
  112. pub error: JsonErrorVal,
  113. pub id: Value,
  114. }
  115. #[derive(Serialize, Deserialize, Clone, Debug)]
  116. pub struct JsonResponse {
  117. pub jsonrpc: Value,
  118. pub result: Value,
  119. pub id: Value,
  120. }
  121. #[derive(Serialize, Deserialize, Clone, Debug)]
  122. pub struct JsonNotification {
  123. pub jsonrpc: Value,
  124. pub method: Value,
  125. pub params: Value,
  126. }
  127. pub fn request(m: Value, p: Value) -> JsonRequest {
  128. let mut rng = rand::thread_rng();
  129. JsonRequest { jsonrpc: json!("2.0"), method: m, params: p, id: json!(rng.gen::<u32>()) }
  130. }
  131. pub fn response(r: Value, i: Value) -> JsonResponse {
  132. JsonResponse { jsonrpc: json!("2.0"), result: r, id: i }
  133. }
  134. pub fn error(c: ErrorCode, m: Option<String>, i: Value) -> JsonError {
  135. let ev = JsonErrorVal {
  136. code: json!(c.code()),
  137. message: if m.is_none() { json!(c.description()) } else { json!(Some(m)) },
  138. };
  139. JsonError { jsonrpc: json!("2.0"), error: ev, id: i }
  140. }
  141. pub fn notification(m: Value, p: Value) -> JsonNotification {
  142. JsonNotification { jsonrpc: json!("2.0"), method: m, params: p }
  143. }
  144. async fn reqrep_loop<T: TransportStream>(
  145. mut stream: T,
  146. result_sender: async_channel::Sender<JsonResult>,
  147. data_receiver: async_channel::Receiver<Value>,
  148. stop_receiver: async_channel::Receiver<()>,
  149. ) -> Result<()> {
  150. // If we don't get a reply after 30 seconds, we'll fail.
  151. let read_timeout = Duration::from_secs(30);
  152. loop {
  153. let mut buf = [0; 8192];
  154. select! {
  155. data = data_receiver.recv().fuse() => {
  156. let data_str = serde_json::to_string(&data?)?;
  157. stream.write_all(data_str.as_bytes()).await?;
  158. let bytes_read = timeout(read_timeout, async { stream.read(&mut buf[..]).await }).await?;
  159. let reply: JsonResult = serde_json::from_slice(&buf[0..bytes_read])?;
  160. result_sender.send(reply).await?;
  161. }
  162. _ = stop_receiver.recv().fuse() => break
  163. }
  164. }
  165. Ok(())
  166. }
  167. pub async fn open_channels(
  168. uri: &Url,
  169. ) -> Result<(
  170. async_channel::Sender<Value>,
  171. async_channel::Receiver<JsonResult>,
  172. async_channel::Sender<()>,
  173. )> {
  174. let (data_sender, data_receiver) = async_channel::unbounded();
  175. let (result_sender, result_receiver) = async_channel::unbounded();
  176. let (stop_sender, stop_receiver) = async_channel::unbounded();
  177. let transport_name = TransportName::try_from(uri.clone())?;
  178. macro_rules! reqrep {
  179. ($stream:expr, $transport:expr, $upgrade:expr) => {{
  180. if let Err(err) = $stream {
  181. error!("RPC Setup for {} failed: {}", uri, err);
  182. return Err(Error::ConnectFailed)
  183. }
  184. let stream = $stream?.await;
  185. if let Err(err) = stream {
  186. error!("RPC Connection to {} failed: {}", uri, err);
  187. return Err(Error::ConnectFailed)
  188. }
  189. let stream = stream?;
  190. match $upgrade {
  191. None => {
  192. smol::spawn(reqrep_loop(stream, result_sender, data_receiver, stop_receiver))
  193. .detach();
  194. }
  195. Some(u) if u == "tls" => {
  196. let stream = $transport.upgrade_dialer(stream)?.await?;
  197. smol::spawn(reqrep_loop(stream, result_sender, data_receiver, stop_receiver))
  198. .detach();
  199. }
  200. Some(u) => return Err(Error::UnsupportedTransportUpgrade(u)),
  201. }
  202. }};
  203. }
  204. match transport_name {
  205. TransportName::Tcp(upgrade) => {
  206. let transport = TcpTransport::new(None, 1024);
  207. let stream = transport.dial(uri.clone());
  208. reqrep!(stream, transport, upgrade);
  209. }
  210. TransportName::Tor(upgrade) => {
  211. let socks5_url = Url::parse(
  212. &env::var("DARKFI_TOR_SOCKS5_URL")
  213. .unwrap_or_else(|_| "socks5://127.0.0.1:9050".to_string()),
  214. )?;
  215. let transport = TorTransport::new(socks5_url, None)?;
  216. let stream = transport.clone().dial(uri.clone());
  217. reqrep!(stream, transport, upgrade);
  218. }
  219. TransportName::Unix => {
  220. let transport = UnixTransport::new();
  221. let stream = transport.dial(uri.clone()).await;
  222. if let Err(err) = stream {
  223. error!("RPC Connection to {} failed: {}", uri, err);
  224. return Err(Error::ConnectFailed)
  225. }
  226. smol::spawn(reqrep_loop(stream?, result_sender, data_receiver, stop_receiver)).detach();
  227. }
  228. _ => unimplemented!(),
  229. }
  230. Ok((data_sender, result_receiver, stop_sender))
  231. }
  232. pub async fn send_request(uri: &Url, data: Value) -> Result<JsonResult> {
  233. let data_str = serde_json::to_string(&data)?;
  234. let transport_name = TransportName::try_from(uri.clone())?;
  235. macro_rules! reply {
  236. ($stream:expr, $transport:expr, $upgrade:expr) => {{
  237. if let Err(err) = $stream {
  238. error!("RPC Setup for {} failed: {}", uri, err);
  239. return Err(Error::ConnectFailed)
  240. }
  241. let stream = $stream?.await;
  242. if let Err(err) = stream {
  243. error!("RPC Connection to {} failed: {}", uri, err);
  244. return Err(Error::ConnectFailed)
  245. }
  246. let stream = stream?;
  247. match $upgrade {
  248. None => get_reply(stream, data_str).await,
  249. Some(u) if u == "tls" => {
  250. let stream = $transport.upgrade_dialer(stream)?.await?;
  251. get_reply(stream, data_str).await
  252. }
  253. Some(u) => Err(Error::UnsupportedTransportUpgrade(u)),
  254. }
  255. }};
  256. }
  257. match transport_name {
  258. TransportName::Tcp(upgrade) => {
  259. let transport = TcpTransport::new(None, 1024);
  260. let stream = transport.dial(uri.clone());
  261. reply!(stream, transport, upgrade)
  262. }
  263. TransportName::Tor(upgrade) => {
  264. let socks5_url = Url::parse(
  265. &env::var("DARKFI_TOR_SOCKS5_URL")
  266. .unwrap_or_else(|_| "socks5://127.0.0.1:9050".to_string()),
  267. )?;
  268. let transport = TorTransport::new(socks5_url, None)?;
  269. let stream = transport.clone().dial(uri.clone());
  270. reply!(stream, transport, upgrade)
  271. }
  272. TransportName::Unix => {
  273. let transport = UnixTransport::new();
  274. let stream = transport.dial(uri.clone()).await;
  275. if let Err(err) = stream {
  276. error!("RPC Connection to {} failed: {}", uri, err);
  277. return Err(Error::ConnectFailed)
  278. }
  279. get_reply(stream?, data_str).await
  280. }
  281. _ => unimplemented!(),
  282. }
  283. }
  284. async fn get_reply<T: TransportStream>(mut stream: T, data_str: String) -> Result<JsonResult> {
  285. // If we don't get a reply after 30 seconds, we'll fail.
  286. let read_timeout = Duration::from_secs(30);
  287. let mut buf = [0; 8192];
  288. stream.write_all(data_str.as_bytes()).await?;
  289. let bytes_read = timeout(read_timeout, async { stream.read(&mut buf[..]).await }).await?;
  290. let reply: JsonResult = serde_json::from_slice(&buf[0..bytes_read])?;
  291. Ok(reply)
  292. }
  293. // Utils to quickly handle errors
  294. pub type ValueResult<Value> = std::result::Result<Value, ErrorCode>;
  295. pub fn from_result(res: ValueResult<Value>, id: Value) -> JsonResult {
  296. match res {
  297. Ok(v) => JsonResult::Resp(response(v, id)),
  298. Err(e) => error(e, None, id).into(),
  299. }
  300. }