Bläddra i källkod

fud/settings: parse management_rpc separately to fix cli args parsing

epiphany 2 veckor sedan
förälder
incheckning
59e30d224b
5 ändrade filer med 67 tillägg och 26 borttagningar
  1. 1 0
      Cargo.lock
  2. 1 0
      bin/app/Cargo.lock
  3. 1 0
      bin/fud/fud/Cargo.toml
  4. 30 21
      bin/fud/fud/src/main.rs
  5. 34 5
      bin/fud/fud/src/settings.rs

+ 1 - 0
Cargo.lock

@@ -3465,6 +3465,7 @@ dependencies = [
  "structopt",
  "structopt-toml",
  "tinyjson",
+ "toml 0.9.12+spec-1.1.0",
  "tracing",
  "tracing-appender",
  "tracing-subscriber",

+ 1 - 0
bin/app/Cargo.lock

@@ -3137,6 +3137,7 @@ dependencies = [
  "structopt",
  "structopt-toml",
  "tinyjson",
+ "toml 0.9.12+spec-1.1.0",
  "tracing",
  "tracing-appender",
  "tracing-subscriber",

+ 1 - 0
bin/fud/fud/Cargo.toml

@@ -54,6 +54,7 @@ sled-overlay = "0.1.20"
 serde = {version = "1.0.228", features = ["derive"]}
 structopt = "0.3.26"
 structopt-toml = "0.5.1"
+toml = "0.9.8"
 
 [lints]
 workspace = true

+ 30 - 21
bin/fud/fud/src/main.rs

@@ -34,13 +34,13 @@ use darkfi::{
         settings::RpcSettings,
     },
     system::{Publisher, StoppableTask},
-    util::path::expand_path,
+    util::path::{expand_path, get_config_path},
     Error, Result,
 };
 use fud::{
     proto::ProtocolFud,
     rpc::{management::ManagementRpcInterface, DefaultRpcInterface},
-    settings::{Args, CONFIG_FILE, CONFIG_FILE_CONTENTS},
+    settings::{parse_management_rpc, Args, CONFIG_FILE, CONFIG_FILE_CONTENTS},
     Fud,
 };
 
@@ -133,24 +133,31 @@ async fn realmain(args: Args, ex: Arc<Executor<'static>>) -> Result<()> {
         ex.clone(),
     );
 
-    let management_rpc_settings: RpcSettings = args.management_rpc.into();
-    info!(target: "fud", "Starting management JSON-RPC server on {}", management_rpc_settings.listen);
-    let management_rpc_interface = Arc::new(ManagementRpcInterface::new(fud.clone(), dnet_sub));
-    let management_rpc_task = StoppableTask::new();
-    let management_rpc_interface_ = management_rpc_interface.clone();
-    management_rpc_task.clone().start(
-        listen_and_serve(management_rpc_settings, management_rpc_interface, None, ex.clone()),
-        |res| async move {
-            match res {
-                Ok(()) | Err(Error::RpcServerStopped) => {
-                    management_rpc_interface_.stop_connections().await
+    let mut management_rpc_task = None;
+    let management_rpc_settings =
+        parse_management_rpc(&get_config_path(args.config.clone(), CONFIG_FILE)?)?;
+    if let Some(management_rpc_settings) = management_rpc_settings {
+        let management_rpc_settings: RpcSettings = management_rpc_settings.into();
+        info!(target: "fud", "Starting management JSON-RPC server on {}", management_rpc_settings.listen);
+        let management_rpc_interface = Arc::new(ManagementRpcInterface::new(fud.clone(), dnet_sub));
+        management_rpc_task = Some(StoppableTask::new());
+        let management_rpc_interface_ = management_rpc_interface.clone();
+        management_rpc_task.as_ref().unwrap().clone().start(
+            listen_and_serve(management_rpc_settings, management_rpc_interface, None, ex.clone()),
+            |res| async move {
+                match res {
+                    Ok(()) | Err(Error::RpcServerStopped) => {
+                        management_rpc_interface_.stop_connections().await
+                    }
+                    Err(e) => {
+                        error!(target: "fud", "Failed starting management JSON-RPC server: {e}")
+                    }
                 }
-                Err(e) => error!(target: "fud", "Failed starting management JSON-RPC server: {e}"),
-            }
-        },
-        Error::RpcServerStopped,
-        ex.clone(),
-    );
+            },
+            Error::RpcServerStopped,
+            ex.clone(),
+        );
+    }
 
     if let Err(e) = fud.start().await {
         panic!("Error while starting fud: {e}");
@@ -186,8 +193,10 @@ async fn realmain(args: Args, ex: Arc<Executor<'static>>) -> Result<()> {
     info!(target: "fud", "Stopping main JSON-RPC server...");
     rpc_task.stop().await;
 
-    info!(target: "fud", "Stopping management JSON-RPC server...");
-    management_rpc_task.stop().await;
+    if let Some(management_rpc_task) = management_rpc_task {
+        info!(target: "fud", "Stopping management JSON-RPC server...");
+        management_rpc_task.stop().await;
+    }
 
     info!(target: "fud", "Stopping P2P network...");
     p2p.stop().await;

+ 34 - 5
bin/fud/fud/src/settings.rs

@@ -16,11 +16,15 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use std::{fs::read_to_string, path::PathBuf};
+
 use structopt::StructOpt;
 use structopt_toml::{serde::Deserialize, StructOptToml};
+use tracing::error;
 
 use darkfi::{
     cli_desc, dht::DhtSettingsOpt, net::settings::SettingsOpt, rpc::settings::RpcSettingsOpt,
+    Error, Result,
 };
 
 use crate::pow::PowSettingsOpt;
@@ -60,14 +64,10 @@ pub struct Args {
     /// Network settings
     pub net: SettingsOpt,
 
-    #[structopt(skip)]
+    #[structopt(flatten)]
     /// Main JSON-RPC settings
     pub rpc: RpcSettingsOpt,
 
-    #[structopt(skip)]
-    /// Management JSON-RPC settings
-    pub management_rpc: RpcSettingsOpt,
-
     #[structopt(flatten)]
     /// DHT settings
     pub dht: DhtSettingsOpt,
@@ -76,3 +76,32 @@ pub struct Args {
     /// PoW settings
     pub pow: PowSettingsOpt,
 }
+
+/// Helper function to parse management RPC settings from config file.
+/// structopt-toml doesn't support multiple fields with same names (even if
+/// nested) so we can't just have `rpc` and `management_rpc` (both
+/// `RpcSettingsOpt`) in `Args`. This issue causes all CLI arguments to stop
+/// working.
+///
+/// For now `management_rpc` is not in `Args` and parsed separately to prevent
+/// this.
+///
+/// TODO: replace structopt-toml to fix this issue.
+pub fn parse_management_rpc(config_path: &PathBuf) -> Result<Option<RpcSettingsOpt>> {
+    let contents = read_to_string(config_path)?;
+
+    #[derive(Deserialize)]
+    struct Config {
+        management_rpc: Option<RpcSettingsOpt>,
+    }
+
+    let config: Config = match toml::from_str(&contents) {
+        Ok(v) => v,
+        Err(e) => {
+            error!(target: "fud", "Failed parsing TOML config: {e}");
+            return Err(Error::ParseFailed("Failed parsing TOML config"))
+        }
+    };
+
+    Ok(config.management_rpc)
+}