1use std::{
4 fmt,
5 fs::{self, File},
6 io::{self, BufRead, BufReader, BufWriter, Write},
7 path::{Path, PathBuf},
8};
9
10use koibumi_node::Config;
11
12use crate::{
13 constant::{BOOTSTRAPS, LOCAL_SERVER, ONION_SEED, TOR_SOCKS},
14 param::Params,
15};
16
17#[derive(Debug)]
19pub enum Error {
20 IoError(io::Error),
23 DeError(toml::de::Error),
26 SerError(toml::ser::Error),
29}
30
31impl fmt::Display for Error {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 match self {
34 Self::IoError(err) => err.fmt(f),
35 Self::DeError(err) => err.fmt(f),
36 Self::SerError(err) => err.fmt(f),
37 }
38 }
39}
40
41impl std::error::Error for Error {}
42
43impl From<io::Error> for Error {
44 fn from(err: io::Error) -> Self {
45 Self::IoError(err)
46 }
47}
48
49impl From<toml::de::Error> for Error {
50 fn from(err: toml::de::Error) -> Self {
51 Self::DeError(err)
52 }
53}
54
55impl From<toml::ser::Error> for Error {
56 fn from(err: toml::ser::Error) -> Self {
57 Self::SerError(err)
58 }
59}
60
61fn load_config_string(path: &Path) -> Result<String, Error> {
62 let f = File::open(path)?;
63 let reader = BufReader::new(f);
64 let lines = reader.lines().collect::<io::Result<Vec<String>>>()?;
65 Ok(lines.join("\n"))
66}
67
68fn default_config() -> Config {
69 Config::builder()
70 .server(Some(LOCAL_SERVER.parse().unwrap()))
71 .socks(Some(TOR_SOCKS.parse().unwrap()))
72 .connect_to_onion(true)
73 .connect_to_ip(true)
74 .seeds(vec![ONION_SEED.parse().unwrap()])
75 .bootstraps(vec![
76 BOOTSTRAPS[0].parse().unwrap(),
77 BOOTSTRAPS[1].parse().unwrap(),
78 ])
79 .build()
80}
81
82pub fn load(params: &Params) -> Result<Config, Error> {
84 let mut path = params.data_dir().to_path_buf();
85 path.push("node.toml");
86 if !path.exists() {
87 return Ok(default_config());
88 }
89 let string = load_config_string(&path)?;
90 Ok(toml::from_str(&string)?)
91}
92
93pub(crate) fn create_data_dir(params: &Params) -> Result<PathBuf, io::Error> {
94 let path = params.data_dir();
95 if !path.exists() {
96 fs::create_dir_all(&path)?;
97 }
98 Ok(path.to_path_buf())
99}
100
101pub fn save(params: &Params, config: &Config) -> Result<(), Error> {
103 let string = toml::to_string(&config)?;
104
105 let path = params.data_dir();
106 if !path.exists() {
107 fs::create_dir_all(&path)?;
108 }
109
110 let mut new_path = path.to_path_buf();
111 new_path.push("node-new.toml");
112 let f = File::create(new_path.clone())?;
113 let mut writer = BufWriter::new(f);
114 writer.write_all(string.as_bytes())?;
115 writer.flush()?;
116
117 let mut to_path = path.to_path_buf();
118 to_path.push("node.toml");
119 fs::rename(new_path, to_path)?;
120 Ok(())
121}