Răsfoiți Sursa

rpc/jsonrpc: handle errors properly inside send_request function

ghassmo 4 ani în urmă
părinte
comite
7067f6314c
2 a modificat fișierele cu 29 adăugiri și 16 ștergeri
  1. 11 0
      src/error.rs
  2. 18 16
      src/rpc/jsonrpc.rs

+ 11 - 0
src/error.rs

@@ -33,6 +33,10 @@ pub enum Error {
     #[error("Url parse error `{0}`")]
     UrlParseError(String),
 
+    #[cfg(any(feature = "rpc"))]
+    #[error("Socks error `{0}`")]
+    SocksError(String),
+
     #[error("No url found")]
     NoUrlFound,
 
@@ -275,6 +279,13 @@ impl From<Box<bincode::ErrorKind>> for Error {
     }
 }
 
+#[cfg(feature = "rpc")]
+impl From<fast_socks5::SocksError> for Error {
+    fn from(err: fast_socks5::SocksError) -> Error {
+        Error::SocksError(err.to_string())
+    }
+}
+
 impl From<std::convert::Infallible> for Error {
     fn from(err: std::convert::Infallible) -> Error {
         Error::InfallibleError(err.to_string())

+ 18 - 16
src/rpc/jsonrpc.rs

@@ -144,13 +144,13 @@ pub fn notification(m: Value, p: Value) -> JsonNotification {
 }
 
 pub async fn send_request(uri: &Url, data: Value, socks_url: Option<Url>) -> Result<JsonResult> {
-    let host = uri
-        .host()
-        .ok_or_else(|| Error::UrlParseError(format!("Missing host in {}", uri)))?
-        .to_string();
+    if uri.host().is_none() && uri.port().is_none() {
+        return Err(Error::UrlParseError(format!("Missing port in {}", uri)))
+    }
+
+    let host = uri.host().unwrap().to_string();
 
-    let port =
-        uri.port().ok_or_else(|| Error::UrlParseError(format!("Missing port in {}", uri)))?;
+    let port = uri.port().unwrap();
 
     let socket_addr = {
         let host = host.clone();
@@ -177,15 +177,19 @@ pub async fn send_request(uri: &Url, data: Value, socks_url: Option<Url>) -> Res
             let mut stream = Async::<UnixStream>::connect(uri.path()).await?;
             get_reply(&mut stream, data_str).await
         }
-        "tor" => {
+        "tor" | "nym" => {
             use fast_socks5::client::{Config, Socks5Stream};
 
             let mut stream;
 
+            if socks_url.is_none() {
+                return Err(Error::NoSocks5UrlFound)
+            }
+
             let socks_url = socks_url.unwrap();
             let config = Config::default();
 
-            if !socks_url.username().is_empty() && !socks_url.password().is_some() {
+            if !socks_url.username().is_empty() && socks_url.password().is_some() {
                 stream = Socks5Stream::connect_with_password(
                     socks_url.as_str(),
                     host,
@@ -194,28 +198,26 @@ pub async fn send_request(uri: &Url, data: Value, socks_url: Option<Url>) -> Res
                     socks_url.password().unwrap().to_string(),
                     config,
                 )
-                .await
-                .unwrap();
+                .await?;
             } else {
-                stream =
-                    Socks5Stream::connect(socks_url.as_str(), host, port, config).await.unwrap();
+                stream = Socks5Stream::connect(socks_url.as_str(), host, port, config).await?;
             }
 
             get_reply(&mut stream, data_str).await
         }
-        "nym" => unimplemented!(),
-        _ => unreachable!(),
+        _ => unimplemented!(),
     }
 }
+
 async fn get_reply<T: AsyncRead + AsyncWrite + Unpin>(
     stream: &mut T,
     data_str: String,
 ) -> Result<JsonResult> {
     // If we don't get a reply after 30 seconds, we'll fail.
-    let mut buf = [0; 2048];
-
     let read_timeout = Duration::from_secs(30);
 
+    let mut buf = [0; 2048];
+
     stream.write_all(data_str.as_bytes()).await?;
 
     let bytes_read = timeout(read_timeout, async { stream.read(&mut buf[..]).await }).await?;