Преглед изворни кода

bin/ircd2: WIP add config file and settings struct & clean up

ghassmo пре 4 година
родитељ
комит
60b3be57ad
5 измењених фајлова са 215 додато и 62 уклоњено
  1. 3 2
      Cargo.lock
  2. 2 1
      bin/ircd2/Cargo.toml
  3. 36 0
      bin/ircd2/ircd_config.toml
  4. 40 59
      bin/ircd2/src/main.rs
  5. 134 0
      bin/ircd2/src/settings.rs

+ 3 - 2
Cargo.lock

@@ -2182,14 +2182,15 @@ dependencies = [
  "async-executor",
  "async-std",
  "async-trait",
- "clap 3.1.8",
+ "clap 3.1.12",
  "ctrlc-async",
  "darkfi",
  "easy-parallel",
  "futures",
  "fxhash",
  "log",
- "rand 0.8.5",
+ "rand",
+ "serde",
  "serde_json",
  "simplelog",
  "smol",

+ 2 - 1
bin/ircd2/Cargo.toml

@@ -27,7 +27,8 @@ clap = {version = "3.1.8", features = ["derive"]}
 log = "0.4.16"
 simplelog = "0.12.0-alpha1"
 fxhash = "0.2.1"
-ctrlc-async = {version= "3.2.2", features = ["termination"]}
+ctrlc-async = {version= "3.2.2", default-features = false, features = ["async-std", "termination"]}
 
 # Encoding and parsing
 serde_json = "1.0.79"
+serde = {version = "1.0.136", features = ["derive"]}

+ 36 - 0
bin/ircd2/ircd_config.toml

@@ -0,0 +1,36 @@
+## taud configuration file
+##
+## Please make sure you go through all the settings so you can configure
+## your daemon properly.
+
+# Path to the datastore
+datastore_raft = "~/.config/tau/tau.db"
+
+# Path to DER-formatted PKCS#12 archive. (used only with tls url)
+# This can be created using openssl:
+# openssl pkcs12 -export -out identity.pfx -inkey key.pem -in cert.pem -certfile chain_certs.pem
+tls_identity_path = ""
+
+### Number of outbound connections 
+#outbound_connections = 5
+
+# The address where taud should bind its RPC socket
+[rpc_listener_url]
+url="127.0.0.1:6667"
+password = "FOOBAR"
+
+# The address where taud should bind its RPC socket
+[irc_listener_url]
+url="127.0.0.1:8000"
+password = "FOOBAR"
+
+### The accept address 
+#[accept_address]
+#url="127.0.0.1:8822"
+#password = "FOOBAR"
+
+### Seed node addresses
+#[[seeds]]
+#url="127.0.0.1:8811"
+#password = "FOOBAR"
+

+ 40 - 59
bin/ircd2/src/main.rs

@@ -10,54 +10,27 @@ use log::{debug, error, info, warn};
 use simplelog::{ColorChoice, TermLogger, TerminalMode};
 
 use darkfi::{
-    cli_desc, net,
+    net,
     raft::Raft,
     rpc::rpcserver::{listen_and_serve, RpcServerConfig},
-    util::cli::log_config,
+    util::{
+        cli::{log_config, spawn_config, Config},
+        path::get_config_path,
+    },
     Error, Result,
 };
 
-pub(crate) mod privmsg;
-pub(crate) mod rpc;
-pub(crate) mod server;
+pub mod privmsg;
+pub mod rpc;
+pub mod server;
+pub mod settings;
 
-use crate::{privmsg::Privmsg, rpc::JsonRpcInterface, server::IrcServerConnection};
-
-#[derive(Parser)]
-#[clap(name = "ircd", about = cli_desc!(), version)]
-struct Args {
-    /// Accept address
-    #[clap(short, long)]
-    accept: Option<SocketAddr>,
-
-    /// Seed node (repeatable)
-    #[clap(short, long)]
-    seed: Vec<SocketAddr>,
-
-    /// Manual connection (repeatable)
-    #[clap(short, long)]
-    connect: Vec<SocketAddr>,
-
-    /// Connection slots
-    #[clap(long, default_value_t = 0)]
-    slots: u32,
-
-    /// External address
-    #[clap(short, long)]
-    external: Option<SocketAddr>,
-
-    /// IRC listen address
-    #[clap(short = 'r', long, default_value = "127.0.0.1:6667")]
-    irc: SocketAddr,
-
-    /// RPC listen address
-    #[clap(long, default_value = "127.0.0.1:8000")]
-    rpc: SocketAddr,
-
-    /// Verbosity level
-    #[clap(short, parse(from_occurrences))]
-    verbose: u8,
-}
+use crate::{
+    privmsg::Privmsg,
+    rpc::JsonRpcInterface,
+    server::IrcServerConnection,
+    settings::{CliArgs, IrcdConfig, Settings, CONFIG_FILE_CONTENTS},
+};
 
 async fn process_user_input(
     mut line: String,
@@ -100,7 +73,7 @@ async fn process(
         let mut line = String::new();
         futures::select! {
             privmsg = receiver.recv().fuse() => {
-                let msg = privmsg.expect("internal message queue error");
+                let msg = privmsg?;
                 debug!("ABOUT TO SEND: {:?}", msg);
                 let irc_msg = format!(":{}!anon@dark.fi PRIVMSG {} :{}\r\n",
                                       msg.nickname,
@@ -123,31 +96,32 @@ async fn process(
     }
 }
 
-async fn start(executor: Arc<Executor<'_>>, args: Args, net_settings: net::Settings) -> Result<()> {
-    let listener = TcpListener::bind(args.irc).await?;
+async fn start(executor: Arc<Executor<'_>>, settings: Settings) -> Result<()> {
+    let listener = TcpListener::bind(settings.irc_listener_url).await?;
     let local_addr = listener.local_addr()?;
     info!("Listening on {}", local_addr);
 
     //
     // Raft
     //
-    let mut raft = Raft::<Privmsg>::new(net_settings.inbound, std::path::PathBuf::from("msgs.db"))?;
+    let mut raft =
+        Raft::<Privmsg>::new(settings.accept_address, std::path::PathBuf::from("msgs.db"))?;
 
     let raft_sender = raft.get_broadcast();
     let commits = raft.get_commits();
 
     //
     // RPC interface
-
+    //
     let rpc_config = RpcServerConfig {
-        socket_addr: args.rpc,
+        socket_addr: settings.rpc_listener_url,
         // TODO: Use net/transport:
         use_tls: false,
         identity_path: Default::default(),
         identity_pass: Default::default(),
     };
     let executor_cloned = executor.clone();
-    let rpc_interface = Arc::new(JsonRpcInterface { addr: args.rpc });
+    let rpc_interface = Arc::new(JsonRpcInterface { addr: settings.rpc_listener_url });
     let rpc_task = executor.spawn(async move {
         listen_and_serve(rpc_config, rpc_interface, executor_cloned.clone()).await
     });
@@ -176,6 +150,15 @@ async fn start(executor: Arc<Executor<'_>>, args: Args, net_settings: net::Setti
 
     let stop_signal = async_channel::bounded::<()>(10);
 
+    let net_settings = net::Settings {
+        inbound: settings.accept_address,
+        outbound_connections: settings.outbound_connections,
+        external_addr: settings.accept_address,
+        peers: settings.connect.clone(),
+        seeds: settings.seeds.clone(),
+        ..Default::default()
+    };
+
     ctrlc_async::set_async_handler(async move {
         warn!(target: "ircd", "ircd start() Exit Signal");
         // cleaning up tasks running in the background
@@ -192,19 +175,17 @@ async fn start(executor: Arc<Executor<'_>>, args: Args, net_settings: net::Setti
 }
 
 fn main() -> Result<()> {
-    let args = Args::parse();
+    let args = CliArgs::parse();
 
     let (lvl, conf) = log_config(args.verbose.into())?;
     TermLogger::init(lvl, conf, TerminalMode::Mixed, ColorChoice::Auto)?;
 
-    let net_settings = net::Settings {
-        inbound: args.accept,
-        outbound_connections: args.slots,
-        external_addr: args.external,
-        peers: args.connect.clone(),
-        seeds: args.seed.clone(),
-        ..Default::default()
-    };
+    let config_path = get_config_path(args.config.clone(), "ircd_config.toml")?;
+    spawn_config(&config_path, CONFIG_FILE_CONTENTS)?;
+
+    let config: IrcdConfig = Config::<IrcdConfig>::load(config_path)?;
+
+    let settings = Settings::load(args, config)?;
 
     let ex = Arc::new(Executor::new());
     let ex_clone = ex.clone();
@@ -214,7 +195,7 @@ fn main() -> Result<()> {
         // Run the main future on the current thread.
         .finish(|| {
             smol::future::block_on(async move {
-                start(ex_clone.clone(), args, net_settings).await?;
+                start(ex_clone.clone(), settings).await?;
                 drop(signal);
                 Ok::<(), darkfi::Error>(())
             })

+ 134 - 0
bin/ircd2/src/settings.rs

@@ -0,0 +1,134 @@
+use std::{net::SocketAddr, path::PathBuf};
+
+use clap::Parser;
+use serde::{Deserialize, Serialize};
+
+use darkfi::{
+    cli_desc,
+    util::{cli::UrlConfig, path::expand_path},
+    Error, Result,
+};
+
+pub const CONFIG_FILE_CONTENTS: &[u8] = include_bytes!("../ircd_config.toml");
+
+#[derive(Clone, Debug)]
+pub struct Settings {
+    pub datastore_raft: PathBuf,
+    pub rpc_listener_url: SocketAddr,
+    pub irc_listener_url: SocketAddr,
+    pub accept_address: Option<SocketAddr>,
+    pub outbound_connections: u32,
+    pub connect: Vec<SocketAddr>,
+    pub seeds: Vec<SocketAddr>,
+}
+
+impl Settings {
+    pub fn load(args: CliArgs, config: IrcdConfig) -> Result<Self> {
+        if config.datastore_raft.is_empty() {
+            return Err(Error::ParseFailed("Failed to parse datastore_raft path"))
+        }
+
+        let datastore_raft = expand_path(&config.datastore_raft)?;
+
+        let rpc_listener_url = if args.rpc.is_none() {
+            SocketAddr::try_from(config.rpc_listener_url)?
+        } else {
+            args.rpc.unwrap()
+        };
+
+        let irc_listener_url = if args.irc.is_none() {
+            SocketAddr::try_from(config.irc_listener_url)?
+        } else {
+            args.irc.unwrap()
+        };
+
+        let accept_address = if args.accept.is_none() {
+            match config.accept_address {
+                Some(addr) => {
+                    let socket_addr = SocketAddr::try_from(addr)?;
+                    Some(socket_addr)
+                }
+                None => None,
+            }
+        } else {
+            args.accept
+        };
+
+        let outbound_connections = if args.slots == 0 {
+            config.outbound_connections.unwrap_or_default()
+        } else {
+            args.slots
+        };
+
+        let connect = args.connect;
+
+        let config_seeds = config
+            .seeds
+            .map(|addrs| {
+                addrs.iter().filter_map(|addr| SocketAddr::try_from(addr.clone()).ok()).collect()
+            })
+            .unwrap_or_default();
+
+        let seeds = if args.seeds.is_empty() { config_seeds } else { args.seeds };
+
+        Ok(Settings {
+            datastore_raft,
+            rpc_listener_url,
+            irc_listener_url,
+            accept_address,
+            outbound_connections,
+            connect,
+            seeds,
+        })
+    }
+}
+
+#[derive(Parser)]
+#[clap(name = "ircd", about = cli_desc!(), version)]
+pub struct CliArgs {
+    /// Sets a custom config file
+    #[clap(long)]
+    pub config: Option<String>,
+    /// Accept address
+    #[clap(short, long)]
+    pub accept: Option<SocketAddr>,
+    /// Seed node (repeatable)
+    #[clap(short, long)]
+    pub seeds: Vec<SocketAddr>,
+    /// Manual connection (repeatable)
+    #[clap(short, long)]
+    pub connect: Vec<SocketAddr>,
+    /// Connection slots
+    #[clap(long, default_value = "0")]
+    pub slots: u32,
+    /// External address
+    #[clap(short, long)]
+    pub external: Option<SocketAddr>,
+    /// IRC listen address
+    #[clap(short = 'r', long)]
+    pub irc: Option<SocketAddr>,
+    /// RPC listen address
+    #[clap(long)]
+    pub rpc: Option<SocketAddr>,
+    /// Verbosity level
+    #[clap(short, parse(from_occurrences))]
+    pub verbose: u8,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct IrcdConfig {
+    /// path to datastore  for raft
+    pub datastore_raft: String,
+    /// Path to DER-formatted PKCS#12 archive. (used only with tls listener url)
+    pub tls_identity_path: String,
+    /// The address where taud should bind its RPC socket
+    pub rpc_listener_url: UrlConfig,
+    /// IRC listen address
+    pub irc_listener_url: UrlConfig,
+    /// Accept address for p2p network
+    pub accept_address: Option<UrlConfig>,
+    /// Number of outbound connections for p2p
+    pub outbound_connections: Option<u32>,
+    /// The seeds for receiving ip addresses from the p2p network
+    pub seeds: Option<Vec<UrlConfig>>,
+}