From 967b0e0f31291006289a68f97f3d6991f7cb55ed Mon Sep 17 00:00:00 2001 From: parazyd Date: Thu, 23 Sep 2021 20:04:56 +0200 Subject: [PATCH] rpc/jsonrpc: Support TLS in send_request. This implies all URLs passed to the function should have a schema. tcp:// or tls:// are supported. --- Cargo.lock | 1 + Cargo.toml | 1 + src/error.rs | 8 ++++++++ src/rpc/jsonrpc.rs | 43 +++++++++++++++++++++++++++++++++++-------- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e2aa38003..44103cb71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1208,6 +1208,7 @@ dependencies = [ "spl-token", "tokio-tungstenite", "toml", + "url", "zcash_primitives", "zcash_proofs", "zeromq", diff --git a/Cargo.toml b/Cargo.toml index 9749e9a7a..8316d5810 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ log = "0.4.14" clap = "2.33.3" toml = "0.5.8" dirs = "4.0.0" +url = "2.2.2" serde = { version = "1.0.126", features = ["derive"]} serde_json = "1.0.61" bytes = "1.0.1" diff --git a/src/error.rs b/src/error.rs index cb05046c2..38094053d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -16,6 +16,7 @@ pub enum Error { ParseFailed(&'static str), ParseIntError, ParseFloatError, + UrlParseError, AsyncChannelSenderError, AsyncChannelReceiverError, AsyncNativeTlsError, @@ -75,6 +76,7 @@ impl fmt::Display for Error { Error::ParseFailed(ref err) => write!(f, "parse failed: {}", err), Error::ParseIntError => f.write_str("Parse int error"), Error::ParseFloatError => f.write_str("Parse float error"), + Error::UrlParseError => f.write_str("Failed to parse URL"), Error::AsyncChannelSenderError => f.write_str("Async_channel sender error"), Error::AsyncChannelReceiverError => f.write_str("Async_channel receiver error"), Error::AsyncNativeTlsError => f.write_str("Async_Native_TLS error"), @@ -195,6 +197,12 @@ impl From for Error { } } +impl From for Error { + fn from(_err: url::ParseError) -> Error { + Error::UrlParseError + } +} + impl From for Error { fn from(_err: std::num::ParseIntError) -> Error { Error::ParseIntError diff --git a/src/rpc/jsonrpc.rs b/src/rpc/jsonrpc.rs index 813e268ec..ff15d81da 100644 --- a/src/rpc/jsonrpc.rs +++ b/src/rpc/jsonrpc.rs @@ -1,12 +1,11 @@ +use std::net::{TcpStream, ToSocketAddrs}; use std::str; -use async_std::{ - io::{ReadExt, WriteExt}, - net::TcpStream, -}; +use async_std::io::{ReadExt, WriteExt}; use rand::Rng; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; +use smol::Async; use crate::Error; @@ -133,13 +132,41 @@ pub fn notification(m: Value, p: Value) -> JsonNotification { } pub async fn send_request(url: &str, data: Value) -> Result { - // TODO: TLS + let use_tls: bool; + let parsed_url = url::Url::parse(url)?; + + match parsed_url.scheme() { + "tcp" => use_tls = false, + "tls" => use_tls = true, + _ => return Err(Error::UrlParseError), + } + + // TODO: Error handling + let host = parsed_url.host().unwrap().to_string(); + let port = parsed_url.port().unwrap(); + + let socket_addr = { + let host = host.clone(); + smol::unblock(move || (host.as_str(), port).to_socket_addrs()) + .await? + .next() + .ok_or_else(|| Error::UrlParseError)? + }; + let mut buf = [0; 2048]; - let mut stream = TcpStream::connect(url).await?; + let bytes_read: usize; let data_str = serde_json::to_string(&data)?; - stream.write_all(&data_str.as_bytes()).await?; - let bytes_read = stream.read(&mut buf[..]).await?; + let mut stream = Async::::connect(socket_addr).await?; + + if use_tls { + let mut stream = async_native_tls::connect(&host, stream).await?; + stream.write_all(&data_str.as_bytes()).await?; + bytes_read = stream.read(&mut buf[..]).await?; + } else { + stream.write_all(&data_str.as_bytes()).await?; + bytes_read = stream.read(&mut buf[..]).await?; + } let reply: JsonResult = serde_json::from_slice(&buf[0..bytes_read])?; Ok(reply)