Просмотр исходного кода

rpc/jsonrpc: Support TLS in send_request.

This implies all URLs passed to the function should have a schema.

tcp:// or tls:// are supported.
parazyd 4 лет назад
Родитель
Сommit
967b0e0f31
4 измененных файлов с 45 добавлено и 8 удалено
  1. 1 0
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 8 0
      src/error.rs
  4. 35 8
      src/rpc/jsonrpc.rs

+ 1 - 0
Cargo.lock

@@ -1208,6 +1208,7 @@ dependencies = [
  "spl-token",
  "spl-token",
  "tokio-tungstenite",
  "tokio-tungstenite",
  "toml",
  "toml",
+ "url",
  "zcash_primitives",
  "zcash_primitives",
  "zcash_proofs",
  "zcash_proofs",
  "zeromq",
  "zeromq",

+ 1 - 0
Cargo.toml

@@ -49,6 +49,7 @@ log = "0.4.14"
 clap = "2.33.3"
 clap = "2.33.3"
 toml = "0.5.8"
 toml = "0.5.8"
 dirs = "4.0.0"
 dirs = "4.0.0"
+url = "2.2.2"
 serde = { version = "1.0.126", features = ["derive"]}
 serde = { version = "1.0.126", features = ["derive"]}
 serde_json = "1.0.61"
 serde_json = "1.0.61"
 bytes = "1.0.1"
 bytes = "1.0.1"

+ 8 - 0
src/error.rs

@@ -16,6 +16,7 @@ pub enum Error {
     ParseFailed(&'static str),
     ParseFailed(&'static str),
     ParseIntError,
     ParseIntError,
     ParseFloatError,
     ParseFloatError,
+    UrlParseError,
     AsyncChannelSenderError,
     AsyncChannelSenderError,
     AsyncChannelReceiverError,
     AsyncChannelReceiverError,
     AsyncNativeTlsError,
     AsyncNativeTlsError,
@@ -75,6 +76,7 @@ impl fmt::Display for Error {
             Error::ParseFailed(ref err) => write!(f, "parse failed: {}", err),
             Error::ParseFailed(ref err) => write!(f, "parse failed: {}", err),
             Error::ParseIntError => f.write_str("Parse int error"),
             Error::ParseIntError => f.write_str("Parse int error"),
             Error::ParseFloatError => f.write_str("Parse float 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::AsyncChannelSenderError => f.write_str("Async_channel sender error"),
             Error::AsyncChannelReceiverError => f.write_str("Async_channel receiver error"),
             Error::AsyncChannelReceiverError => f.write_str("Async_channel receiver error"),
             Error::AsyncNativeTlsError => f.write_str("Async_Native_TLS error"),
             Error::AsyncNativeTlsError => f.write_str("Async_Native_TLS error"),
@@ -195,6 +197,12 @@ impl From<std::net::AddrParseError> for Error {
     }
     }
 }
 }
 
 
+impl From<url::ParseError> for Error {
+    fn from(_err: url::ParseError) -> Error {
+        Error::UrlParseError
+    }
+}
+
 impl From<std::num::ParseIntError> for Error {
 impl From<std::num::ParseIntError> for Error {
     fn from(_err: std::num::ParseIntError) -> Error {
     fn from(_err: std::num::ParseIntError) -> Error {
         Error::ParseIntError
         Error::ParseIntError

+ 35 - 8
src/rpc/jsonrpc.rs

@@ -1,12 +1,11 @@
+use std::net::{TcpStream, ToSocketAddrs};
 use std::str;
 use std::str;
 
 
-use async_std::{
-    io::{ReadExt, WriteExt},
-    net::TcpStream,
-};
+use async_std::io::{ReadExt, WriteExt};
 use rand::Rng;
 use rand::Rng;
 use serde::{Deserialize, Serialize};
 use serde::{Deserialize, Serialize};
 use serde_json::{json, Value};
 use serde_json::{json, Value};
+use smol::Async;
 
 
 use crate::Error;
 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<JsonResult, Error> {
 pub async fn send_request(url: &str, data: Value) -> Result<JsonResult, Error> {
-    // 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 buf = [0; 2048];
-    let mut stream = TcpStream::connect(url).await?;
+    let bytes_read: usize;
     let data_str = serde_json::to_string(&data)?;
     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::<TcpStream>::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])?;
     let reply: JsonResult = serde_json::from_slice(&buf[0..bytes_read])?;
     Ok(reply)
     Ok(reply)