main.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{collections::HashSet, sync::Arc};
  19. use darkfi::{
  20. async_daemonize, cli_desc,
  21. rpc::server::{listen_and_serve, RequestHandler},
  22. system::{StoppableTask, StoppableTaskPtr},
  23. util::path::expand_path,
  24. Error, Result,
  25. };
  26. use log::{error, info};
  27. use serde::Deserialize;
  28. use smol::{fs, lock::Mutex, stream::StreamExt, Executor};
  29. use structopt::StructOpt;
  30. use structopt_toml::StructOptToml;
  31. use url::Url;
  32. const CONFIG_FILE: &str = "swapd.toml";
  33. const CONFIG_FILE_CONTENTS: &str = include_str!("../swapd.toml");
  34. /// JSON-RPC server methods
  35. mod rpc;
  36. #[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
  37. #[serde(default)]
  38. #[structopt(name = "darkfi-mmproxy", about = cli_desc!())]
  39. struct Args {
  40. #[structopt(short, parse(from_occurrences))]
  41. /// Increase verbosity (-vvv supported)
  42. verbose: u8,
  43. #[structopt(short, long)]
  44. /// Configuration file to use
  45. config: Option<String>,
  46. #[structopt(long)]
  47. /// Set log file output
  48. log: Option<String>,
  49. #[structopt(flatten)]
  50. swapd: SwapdArgs,
  51. }
  52. #[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
  53. #[structopt()]
  54. struct SwapdArgs {
  55. #[structopt(long, default_value = "tcp://127.0.0.1:52821")]
  56. /// darkfi-swapd JSON-RPC listen URL
  57. swapd_rpc: Url,
  58. #[structopt(long, default_value = "~/.local/darkfi/swapd")]
  59. /// Path to swapd's filesystem database
  60. swapd_db: String,
  61. }
  62. /// Swapd daemon state
  63. struct Swapd {
  64. /// Main reference to the swapd filesystem databaase
  65. _sled_db: sled::Db,
  66. /// JSON-RPC connection tracker
  67. rpc_connections: Mutex<HashSet<StoppableTaskPtr>>,
  68. }
  69. impl Swapd {
  70. /// Instantiate `Swapd` state
  71. async fn new(_swapd_args: &SwapdArgs, sled_db: sled::Db) -> Result<Self> {
  72. Ok(Self { _sled_db: sled_db, rpc_connections: Mutex::new(HashSet::new()) })
  73. }
  74. }
  75. async_daemonize!(realmain);
  76. async fn realmain(args: Args, ex: Arc<Executor<'static>>) -> Result<()> {
  77. info!("Starting DarkFi Atomic Swap Daemon...");
  78. // Create datastore path if not there already.
  79. let datastore = expand_path(&args.swapd.swapd_db)?;
  80. fs::create_dir_all(&datastore).await?;
  81. let sled_db = sled::open(datastore)?;
  82. info!("Initializing daemon state");
  83. let swapd = Arc::new(Swapd::new(&args.swapd, sled_db.clone()).await?);
  84. info!("Starting JSON-RPC server on {}", args.swapd.swapd_rpc);
  85. let swapd_ = Arc::clone(&swapd);
  86. let rpc_task = StoppableTask::new();
  87. rpc_task.clone().start(
  88. listen_and_serve(args.swapd.swapd_rpc, swapd.clone(), None, ex.clone()),
  89. |res| async move {
  90. match res {
  91. Ok(()) | Err(Error::RpcServerStopped) => swapd_.stop_connections().await,
  92. Err(e) => error!("Failed stopping JSON-RPC server: {}", e),
  93. }
  94. },
  95. Error::RpcServerStopped,
  96. ex.clone(),
  97. );
  98. info!("Ready to operate");
  99. // Signal handling for graceful termination.
  100. let (signals_handler, signals_task) = SignalHandler::new(ex)?;
  101. signals_handler.wait_termination(signals_task).await?;
  102. info!("Caught termination signal, cleaning up and exiting");
  103. info!("Flushing sled database");
  104. sled_db.flush_async().await?;
  105. info!("Shut down successfully");
  106. Ok(())
  107. }