mod.rs
1 /* This file is part of DarkFi (https://dark.fi) 2 * 3 * Copyright (C) 2020-2025 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 19 use sled_overlay::sled; 20 use std::{array::TryFromSliceError, string::FromUtf8Error, sync::Arc}; 21 22 pub mod darkirc; 23 #[cfg(feature = "enable-plugins")] 24 pub use darkirc::DarkIrc; 25 pub use darkirc::DarkIrcPtr; 26 27 use darkfi::net::Settings as NetSettings; 28 29 use crate::{ 30 prop::{Property, PropertyAtomicGuard, PropertySubType, PropertyType, PropertyValue, Role}, 31 scene::{SceneNode, SceneNodePtr, SceneNodeType}, 32 }; 33 34 pub struct PluginSettings { 35 pub setting_root: SceneNodePtr, 36 pub sled_tree: sled::Tree, 37 } 38 impl PluginSettings { 39 pub fn add_setting(&self, name: &str, default: PropertyValue) -> Option<SceneNodePtr> { 40 let atom = &mut PropertyAtomicGuard::none(); 41 let node = match default { 42 PropertyValue::Bool(b) => { 43 let mut node = SceneNode::new(name, SceneNodeType::Setting); 44 let prop = Property::new("value", PropertyType::Bool, PropertySubType::Null); 45 node.add_property(prop).unwrap(); 46 let prop = Property::new("default", PropertyType::Bool, PropertySubType::Null); 47 node.add_property(prop).unwrap(); 48 node.set_property_bool(atom, Role::User, "value", b.clone()).unwrap(); 49 node.set_property_bool(atom, Role::App, "default", b.clone()).unwrap(); 50 Some(node) 51 } 52 PropertyValue::Uint32(u) => { 53 let mut node = SceneNode::new(name, SceneNodeType::Setting); 54 let prop = Property::new("value", PropertyType::Uint32, PropertySubType::Null); 55 node.add_property(prop).unwrap(); 56 let prop = Property::new("default", PropertyType::Uint32, PropertySubType::Null); 57 node.add_property(prop).unwrap(); 58 node.set_property_u32(atom, Role::User, "value", u.clone()).unwrap(); 59 node.set_property_u32(atom, Role::App, "default", u.clone()).unwrap(); 60 Some(node) 61 } 62 PropertyValue::Float32(f) => { 63 let mut node = SceneNode::new(name, SceneNodeType::Setting); 64 let prop = Property::new("value", PropertyType::Float32, PropertySubType::Null); 65 node.add_property(prop).unwrap(); 66 let prop = Property::new("default", PropertyType::Float32, PropertySubType::Null); 67 node.add_property(prop).unwrap(); 68 node.set_property_f32(atom, Role::User, "value", f.clone()).unwrap(); 69 node.set_property_f32(atom, Role::App, "default", f.clone()).unwrap(); 70 Some(node) 71 } 72 PropertyValue::Str(s) => { 73 let mut node = SceneNode::new(name, SceneNodeType::Setting); 74 let prop = Property::new("value", PropertyType::Str, PropertySubType::Null); 75 node.add_property(prop).unwrap(); 76 let prop = Property::new("default", PropertyType::Str, PropertySubType::Null); 77 node.add_property(prop).unwrap(); 78 node.set_property_str(atom, Role::User, "value", s.clone()).unwrap(); 79 node.set_property_str(atom, Role::App, "default", s.clone()).unwrap(); 80 Some(node) 81 } 82 _ => None, 83 }; 84 85 match node { 86 Some(n) => { 87 let node_ptr = Arc::new(n); 88 self.setting_root.link(node_ptr.clone().into()); 89 Some(node_ptr) 90 } 91 None => None, 92 } 93 } 94 95 // For all settings, copy the value from sled into the setting node's value property 96 pub fn load_settings(&self) { 97 let atom = &mut PropertyAtomicGuard::none(); 98 for setting_node in self.setting_root.get_children().iter() { 99 if setting_node.typ != SceneNodeType::Setting { 100 continue 101 } 102 103 let value = setting_node.get_property("value").clone().unwrap(); 104 match value.typ { 105 PropertyType::Bool => { 106 let sled_result = self.sled_tree.get(setting_node.name.as_str()); 107 if let Ok(Some(sled_value)) = sled_result { 108 setting_node 109 .set_property_bool(atom, Role::User, "value", sled_value[0] != 0) 110 .unwrap(); 111 } 112 } 113 PropertyType::Uint32 => { 114 let sled_result = self.sled_tree.get(setting_node.name.as_str()); 115 if let Ok(Some(sled_value)) = sled_result { 116 if sled_value.len() == 4 { 117 let bytes: Result<[u8; 4], TryFromSliceError> = 118 sled_value.as_ref().try_into(); 119 if let Ok(b) = bytes { 120 setting_node 121 .set_property_u32( 122 atom, 123 Role::User, 124 "value", 125 u32::from_le_bytes(b), 126 ) 127 .unwrap(); 128 } 129 } 130 } 131 } 132 PropertyType::Float32 => { 133 let sled_result = self.sled_tree.get(setting_node.name.as_str()); 134 if let Ok(Some(sled_value)) = sled_result { 135 if sled_value.len() == 4 { 136 let bytes: Result<[u8; 4], TryFromSliceError> = 137 sled_value.as_ref().try_into(); 138 if let Ok(b) = bytes { 139 setting_node 140 .set_property_f32( 141 atom, 142 Role::User, 143 "value", 144 f32::from_le_bytes(b), 145 ) 146 .unwrap(); 147 } 148 } 149 } 150 } 151 PropertyType::Str => { 152 let sled_result = self.sled_tree.get(setting_node.name.as_str()); 153 if let Ok(Some(sled_value)) = sled_result { 154 let string: Result<String, FromUtf8Error> = 155 String::from_utf8(sled_value.to_vec()); 156 if let Ok(s) = string { 157 setting_node.set_property_str(atom, Role::User, "value", s).unwrap(); 158 } 159 } 160 } 161 _ => {} 162 } 163 } 164 } 165 166 // Save all settings to sled 167 pub fn save_settings(&self) { 168 for setting_node in self.setting_root.get_children().iter() { 169 if setting_node.typ != SceneNodeType::Setting { 170 continue 171 } 172 173 let value = setting_node.get_property("value").clone().unwrap(); 174 match value.typ { 175 PropertyType::Bool => { 176 let value_bytes = if value.get_bool(0).unwrap() { 1u8 } else { 0u8 }; 177 self.sled_tree 178 .insert(setting_node.name.as_str(), sled::IVec::from(vec![value_bytes])) 179 .unwrap(); 180 } 181 PropertyType::Uint32 => { 182 self.sled_tree 183 .insert( 184 setting_node.name.as_str(), 185 sled::IVec::from(value.get_u32(0).unwrap().to_le_bytes().as_ref()), 186 ) 187 .unwrap(); 188 } 189 PropertyType::Float32 => { 190 self.sled_tree 191 .insert( 192 setting_node.name.as_str(), 193 sled::IVec::from(value.get_f32(0).unwrap().to_le_bytes().as_ref()), 194 ) 195 .unwrap(); 196 } 197 PropertyType::Str => { 198 self.sled_tree 199 .insert( 200 setting_node.name.as_str(), 201 sled::IVec::from(value.get_str(0).unwrap().as_bytes()), 202 ) 203 .unwrap(); 204 } 205 _ => {} 206 } 207 } 208 } 209 210 pub fn get_setting(&self, name: &str) -> Option<SceneNodePtr> { 211 self.setting_root 212 .clone() 213 .get_children() 214 .iter() 215 .find(|node| node.typ == SceneNodeType::Setting && node.name == name) 216 .cloned() 217 } 218 219 pub fn add_p2p_settings(&self, p2p_settings: &NetSettings) { 220 self.add_setting( 221 "net.outbound_connections", 222 PropertyValue::Uint32(p2p_settings.outbound_connections as u32), 223 ); 224 self.add_setting( 225 "net.inbound_connections", 226 PropertyValue::Uint32(p2p_settings.inbound_connections as u32), 227 ); 228 self.add_setting( 229 "net.outbound_connect_timeout", 230 PropertyValue::Uint32(p2p_settings.outbound_connect_timeout as u32), 231 ); 232 self.add_setting( 233 "net.channel_handshake_timeout", 234 PropertyValue::Uint32(p2p_settings.channel_handshake_timeout as u32), 235 ); 236 self.add_setting( 237 "net.channel_heartbeat_interval", 238 PropertyValue::Uint32(p2p_settings.channel_heartbeat_interval as u32), 239 ); 240 self.add_setting( 241 "net.outbound_peer_discovery_cooloff_time", 242 PropertyValue::Uint32(p2p_settings.outbound_peer_discovery_cooloff_time as u32), 243 ); 244 self.add_setting("net.localnet", PropertyValue::Bool(p2p_settings.localnet)); 245 self.add_setting( 246 "net.greylist_refinery_interval", 247 PropertyValue::Uint32(p2p_settings.greylist_refinery_interval as u32), 248 ); 249 self.add_setting( 250 "net.white_connect_percent", 251 PropertyValue::Uint32(p2p_settings.white_connect_percent as u32), 252 ); 253 self.add_setting( 254 "net.gold_connect_count", 255 PropertyValue::Uint32(p2p_settings.gold_connect_count as u32), 256 ); 257 self.add_setting( 258 "net.slot_preference_strict", 259 PropertyValue::Bool(p2p_settings.slot_preference_strict), 260 ); 261 self.add_setting( 262 "net.time_with_no_connections", 263 PropertyValue::Uint32(p2p_settings.time_with_no_connections as u32), 264 ); 265 } 266 267 // Update a NetSettings from settings in the node tree 268 pub fn update_p2p_settings(&self, p2p_settings: &mut NetSettings) { 269 p2p_settings.outbound_connections = self 270 .get_setting("net.outbound_connections") 271 .unwrap() 272 .get_property_u32("value") 273 .unwrap() as usize; 274 p2p_settings.inbound_connections = 275 self.get_setting("net.inbound_connections").unwrap().get_property_u32("value").unwrap() 276 as usize; 277 p2p_settings.outbound_connect_timeout = self 278 .get_setting("net.outbound_connect_timeout") 279 .unwrap() 280 .get_property_u32("value") 281 .unwrap() as u64; 282 p2p_settings.channel_handshake_timeout = self 283 .get_setting("net.channel_handshake_timeout") 284 .unwrap() 285 .get_property_u32("value") 286 .unwrap() as u64; 287 p2p_settings.channel_heartbeat_interval = self 288 .get_setting("net.channel_heartbeat_interval") 289 .unwrap() 290 .get_property_u32("value") 291 .unwrap() as u64; 292 p2p_settings.outbound_peer_discovery_cooloff_time = self 293 .get_setting("net.outbound_peer_discovery_cooloff_time") 294 .unwrap() 295 .get_property_u32("value") 296 .unwrap() as u64; 297 p2p_settings.localnet = 298 self.get_setting("net.localnet").unwrap().get_property_bool("value").unwrap(); 299 p2p_settings.greylist_refinery_interval = self 300 .get_setting("net.greylist_refinery_interval") 301 .unwrap() 302 .get_property_u32("value") 303 .unwrap() as u64; 304 p2p_settings.white_connect_percent = self 305 .get_setting("net.white_connect_percent") 306 .unwrap() 307 .get_property_u32("value") 308 .unwrap() as usize; 309 p2p_settings.gold_connect_count = 310 self.get_setting("net.gold_connect_count").unwrap().get_property_u32("value").unwrap() 311 as usize; 312 p2p_settings.slot_preference_strict = self 313 .get_setting("net.slot_preference_strict") 314 .unwrap() 315 .get_property_bool("value") 316 .unwrap(); 317 p2p_settings.time_with_no_connections = self 318 .get_setting("net.time_with_no_connections") 319 .unwrap() 320 .get_property_u32("value") 321 .unwrap() as u64; 322 } 323 }