oxedyne/fe2o3/fe2o3_shield/src/srv/cfg.rs
12.5 KiB, 68 runs
created by r1870400018:858, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | use crate::{ |
| 2 | srv::constant, |
| 3 | //packet::PacketValidator, |
| 4 | //schemes::{ |
| 5 | // WireSchemes, |
| 6 | //}, |
| 7 | }; |
| 8 | |
| 9 | use oxedyne_fe2o3_core::{ |
| 10 | prelude::*, |
| 11 | path::NormPathBuf, |
| 12 | //alt::DefAlt, |
| 13 | }; |
| 14 | use oxedyne_fe2o3_crypto::sign::SignatureScheme; |
| 15 | //use oxedyne_fe2o3_iop_crypto::{ |
| 16 | // sign::{ |
| 17 | // Signer, |
| 18 | // SignerDefAlt, |
| 19 | // }, |
| 20 | // enc::Encrypter, |
| 21 | //}; |
| 22 | use oxedyne_fe2o3_jdat::{ |
| 23 | prelude::*, |
| 24 | cfg::Config, |
| 25 | chunk::{ |
| 26 | Chunker, |
| 27 | ChunkConfig, |
| 28 | }, |
| 29 | //file::JdatFile, |
| 30 | }; |
| 31 | use oxedyne_fe2o3_hash::{ |
| 32 | hash::{ |
| 33 | HashScheme, |
| 34 | //HasherDefAlt, |
| 35 | }, |
| 36 | //pow::ProofOfWork, |
| 37 | }; |
| 38 | //use oxedyne_fe2o3_iop_hash::{ |
| 39 | // api::Hasher, |
| 40 | // csum::Checksummer, |
| 41 | //}; |
| 42 | |
| 43 | use std::{ |
| 44 | collections::BTreeMap, |
| 45 | net::{ |
| 46 | IpAddr, |
| 47 | SocketAddr, |
| 48 | ToSocketAddrs, |
| 49 | }, |
| 50 | str::FromStr, |
| 51 | }; |
| 52 | |
| 53 | use local_ip_address::local_ip; |
| 54 | |
| 55 | |
| 56 | #[derive(Clone, Debug, Eq, PartialEq, FromDatMap, ToDatMap)] |
| 57 | pub struct ServerConfig { |
| 58 | // Schemes |
| 59 | pub schemes_db_path: String, |
| 60 | // Chunking |
| 61 | pub wire_chunk_threshold: u64, // applies only to values |
| 62 | pub wire_chunk_bytes: u64, |
| 63 | // Server |
| 64 | pub log_level: String, |
| 65 | pub server_address: String, |
| 66 | pub server_port_udp: u16, |
| 67 | pub server_rps_zbits_profile: u8, // 0 = linear, .. |
| 68 | pub server_pow_zbits_min: u16, // min zero bits for all packet pows |
| 69 | pub server_pow_zbits_max: u16, // when rps reaches max, the reqd pow zbit reaches this level |
| 70 | pub server_pow_time_horiz_secs: u64, // timestamp must be no older in seconds to now |
| 71 | pub server_rps_max: u16, // the requests per second corresponding to maximum pow zbits |
| 72 | //pub packet_pow_hash_scheme: String, |
| 73 | //pub packet_signature_scheme: String, |
| 74 | pub addr_guard_map_bins: u32, // Number of bins in shared map of incoming addresses. |
| 75 | pub user_guard_map_bins: u32, // Number of bins in shared map of users. |
| 76 | pub msg_assembler_map_bins: u32, // Number of bins in shared map of message pieces. |
| 77 | // Server policy |
| 78 | // An attacker can flood us with HReq1 messages with random uids and public keys. A reasonable |
| 79 | // defence is to set a relatively high difficulty for HReq1. |
| 80 | pub server_accept_unknown_users: bool, |
| 81 | pub trusted_seeds: Vec<String>, |
| 82 | } |
| 83 | |
| 84 | impl Config for ServerConfig { |
| 85 | |
| 86 | fn check_and_fix(&mut self) -> Outcome<()> { |
| 87 | // Checks that read only. |
| 88 | res!(self.check_wire_chunk_config(&self.chunk_config())); |
| 89 | Ok(()) |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | impl Default for ServerConfig { |
| 94 | fn default() -> Self { |
| 95 | Self { |
| 96 | // Schemes |
| 97 | schemes_db_path: fmt!("../oxedyne_fe2o3_namex/namex.jdat"), |
| 98 | // Chunking |
| 99 | wire_chunk_threshold: 1_500, |
| 100 | wire_chunk_bytes: 1_000, |
| 101 | // Server |
| 102 | log_level: fmt!("debug"), |
| 103 | server_address: fmt!("127.0.0.1"), |
| 104 | server_port_udp: 60000, // numeric keypad mapping for "o3db" |
| 105 | server_rps_zbits_profile: 0, // 0 = linear, .. |
| 106 | server_pow_zbits_min: 2, // all packets must have a proof of work with at least this many zero bits |
| 107 | server_pow_zbits_max: 15, // when rps reaches max, the reqd pow zbit reaches this level |
| 108 | server_pow_time_horiz_secs: 600, // timestamp must be no older in seconds to now |
| 109 | server_rps_max: 30_000, // the requests per second corresponding to maximum pow zbits |
| 110 | //packet_pow_hash_scheme: fmt!("Seahash"), |
| 111 | //packet_signature_scheme: fmt!("Ed25519"), // try SIKE |
| 112 | addr_guard_map_bins: 128, // arbitrary |
| 113 | user_guard_map_bins: 128, // arbitrary |
| 114 | msg_assembler_map_bins: 128, // arbitrary |
| 115 | // Server policy. |
| 116 | server_accept_unknown_users: false, |
| 117 | trusted_seeds: vec![], |
| 118 | } |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | impl ServerConfig { |
| 123 | |
| 124 | pub fn validate( |
| 125 | &self, |
| 126 | _root: &NormPathBuf, |
| 127 | ) |
| 128 | -> Outcome<()> |
| 129 | { |
| 130 | Ok(()) |
| 131 | } |
| 132 | |
| 133 | pub fn try_default() -> Outcome<Self> { |
| 134 | Ok(Self::default()) |
| 135 | } |
| 136 | |
| 137 | pub fn bind_ip(&self) -> Outcome<IpAddr> { |
| 138 | let raw = self.server_address.trim(); |
| 139 | if raw.is_empty() || raw.eq_ignore_ascii_case("local") { |
| 140 | return Ok(res!(local_ip(), IO, Network)); |
| 141 | } |
| 142 | match IpAddr::from_str(raw) { |
| 143 | Ok(ip) => Ok(ip), |
| 144 | Err(e) => Err(err!(e, |
| 145 | "ServerConfig: server_address '{}' is neither an IP address nor the \ |
| 146 | word 'local'.", self.server_address; |
| 147 | Invalid, Input, Network)), |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | //pub fn syntax_default() -> Outcome<SyntaxRef> { |
| 152 | // let syntax = SyntaxRef(Arc::new(res!(syntax::build()))); |
| 153 | // Ok(syntax) |
| 154 | //} |
| 155 | |
| 156 | /// Hard-wired default proof of work hash scheme. |
| 157 | pub fn default_packet_pow_hash_scheme() -> Option<HashScheme> { |
| 158 | Some(HashScheme::new_seahash()) |
| 159 | } |
| 160 | |
| 161 | /// Hard-wired default signature scheme. |
| 162 | pub fn default_packet_signature_scheme() -> Option<SignatureScheme> { |
| 163 | Some(SignatureScheme::empty_ed25519()) |
| 164 | } |
| 165 | |
| 166 | //// Data scheme updaters. |
| 167 | //pub fn update_packet_validator< |
| 168 | // WENC: Encrypter, |
| 169 | // WCS: Checksummer, |
| 170 | // POWH: Hasher, |
| 171 | // SGN: Signer, |
| 172 | // HS: Encrypter, |
| 173 | // //// Proof of work validation. |
| 174 | // //const N: usize, // Pristine + Nonce size. |
| 175 | // //const P0: usize, // Length of pristine prefix bytes (i.e. not included in artefact). |
| 176 | // //const P1: usize, // Length of pristine bytes (i.e. included in artefact). |
| 177 | // //PRIS: Pristine<P0, P1>, // Pristine supplied to hasher. |
| 178 | //>( |
| 179 | // &self, |
| 180 | // wschms: &WireSchemes<WENC, WCS, POWH, SGN, HS>, |
| 181 | //) |
| 182 | // -> Outcome<PacketValidator< |
| 183 | // HasherDefAlt<HashScheme, POWH>, |
| 184 | // SignerDefAlt<SignatureScheme, SGN>, |
| 185 | // >> |
| 186 | //{ |
| 187 | // let pow_def_alt = res!(Self::read_hash_scheme( |
| 188 | // &self.packet_pow_hash_scheme, |
| 189 | // &*wschms.powh, |
| 190 | // Self::default_packet_pow_hash_scheme, |
| 191 | // "packet_pow_hash_scheme", |
| 192 | // )); |
| 193 | // let sig_def_alt = res!(Self::read_signature_scheme( |
| 194 | // &self.packet_signature_scheme, |
| 195 | // &*wschms.sign, |
| 196 | // Self::default_packet_signature_scheme, |
| 197 | // "packet_signature_scheme", |
| 198 | // )); |
| 199 | // Ok(PacketValidator { |
| 200 | // pow: match pow_def_alt { |
| 201 | // DefAlt::Given(..) | DefAlt::Default(..) => |
| 202 | // Some(ProofOfWork::new(HasherDefAlt(pow_def_alt))), |
| 203 | // DefAlt::None => None, |
| 204 | // }, |
| 205 | // sig: match sig_def_alt { |
| 206 | // DefAlt::Given(..) | DefAlt::Default(..) => |
| 207 | // Some(SignerDefAlt(sig_def_alt)), |
| 208 | // DefAlt::None => None, |
| 209 | // }, |
| 210 | // }) |
| 211 | //} |
| 212 | |
| 213 | /// Return a rest chunk configuration from the database configuration. |
| 214 | pub fn chunk_config(&self) -> ChunkConfig { |
| 215 | ChunkConfig { |
| 216 | threshold_bytes: self.wire_chunk_threshold as usize, |
| 217 | chunk_size: self.wire_chunk_bytes as usize, |
| 218 | dat_wrap: false, |
| 219 | pad_last: true, |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | pub fn chunker(cfg: ChunkConfig) -> Chunker { |
| 224 | Chunker::default().set_config(cfg) |
| 225 | } |
| 226 | |
| 227 | pub fn wire_chunk_size(&self) -> usize { self.wire_chunk_bytes as usize } |
| 228 | pub fn wire_chunking_threshold(&self) -> usize { self.wire_chunk_threshold as usize } |
| 229 | |
| 230 | pub fn new_chunk_cfg( |
| 231 | threshold_bytes: usize, |
| 232 | chunk_size: usize, |
| 233 | dat_wrap: bool, |
| 234 | pad_last: bool, |
| 235 | ) |
| 236 | -> ChunkConfig |
| 237 | { |
| 238 | ChunkConfig { |
| 239 | threshold_bytes, |
| 240 | chunk_size, |
| 241 | dat_wrap, |
| 242 | pad_last, |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | pub fn chunker_default(&self) -> ChunkConfig { |
| 247 | ChunkConfig { |
| 248 | threshold_bytes: self.wire_chunk_threshold as usize, |
| 249 | chunk_size: self.wire_chunk_bytes as usize, |
| 250 | dat_wrap: false, |
| 251 | pad_last: true, |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | pub fn check_wire_chunk_config(&self, chunk_cfg: &ChunkConfig) -> Outcome<()> { |
| 256 | if chunk_cfg.chunk_size > u16::MAX as usize { |
| 257 | return Err(err!( |
| 258 | "Chunk size of {} is less than the current minimum of {}.", |
| 259 | chunk_cfg.chunk_size, constant::MIN_CHUNK_SIZE; |
| 260 | TooBig, Configuration)); |
| 261 | } |
| 262 | Ok(()) |
| 263 | } |
| 264 | |
| 265 | pub fn dump(self) -> Outcome<()> { |
| 266 | let dat = Self::to_datmap(self); |
| 267 | for line in dat.to_lines(" ", true) { |
| 268 | info!(async_log::stream(), "{}", line); |
| 269 | } |
| 270 | Ok(()) |
| 271 | } |
| 272 | |
| 273 | // Servers. |
| 274 | pub fn addr_guard_map_bins(&self) -> u32 { |
| 275 | self.addr_guard_map_bins |
| 276 | } |
| 277 | |
| 278 | pub fn user_guard_map_bins(&self) -> u32 { |
| 279 | self.user_guard_map_bins |
| 280 | } |
| 281 | |
| 282 | pub fn msg_assembler_map_bins(&self) -> u32 { |
| 283 | self.msg_assembler_map_bins |
| 284 | } |
| 285 | |
| 286 | ///// Build the `PacketValidator` |
| 287 | //pub fn packet_validator< |
| 288 | // // Proof of work validator. |
| 289 | // H: Hasher + Send + 'static, // Proof of work hasher. |
| 290 | // const N: usize, // Pristine + Nonce size. |
| 291 | // const P0: usize, // Length of pristine prefix bytes (i.e. not included in artefact). |
| 292 | // const P1: usize, // Length of pristine bytes (i.e. included in artefact). |
| 293 | // PRIS: Pristine<P0, P1>, // Pristine supplied to hasher. |
| 294 | // // Digital signature validation. |
| 295 | // S: Signer, |
| 296 | //>( |
| 297 | // &self, |
| 298 | // pow_opt: Option<(ProofOfWork<HasherDefAlt<HashScheme, POWH>>, PowParams<P0, P1, PRIS>)>, |
| 299 | // sigpk_opt: Option<Vec<u8>>, |
| 300 | //) |
| 301 | // -> Outcome<PacketValidator> |
| 302 | //{ |
| 303 | // Ok(PacketValidator { |
| 304 | // pow: match self.packet_pow_hash_schemevalidation { |
| 305 | // true => match pvars_opt { |
| 306 | // Some(pvars) => ( |
| 307 | // ProofOfWork::new(HashScheme::new_seahash()), |
| 308 | // PowParams { |
| 309 | // pvars, |
| 310 | // time_lim: constant::POW_CREATE_TIMEOUT, |
| 311 | // count_lim: constant::POW_CREATE_COUNT_LIM, |
| 312 | // }, |
| 313 | // ), |
| 314 | // None => return Err(err!( |
| 315 | // "The configuration currently requires a proof of work validator, \ |
| 316 | // but the PowVars supplied is None.", |
| 317 | // ), Bug, Configuration)), |
| 318 | // }, |
| 319 | // false => None, |
| 320 | // }, |
| 321 | // sig: match self.packet_sign_validation { |
| 322 | // true => match sigpk_opt { |
| 323 | // Some(sigpk) => ( |
| 324 | // ProofOfWork::new(HashScheme::new_seahash()), |
| 325 | // PowParams { |
| 326 | // pvars, |
| 327 | // time_lim: constant::POW_CREATE_TIMEOUT, |
| 328 | // count_lim: constant::POW_CREATE_COUNT_LIM, |
| 329 | // }, |
| 330 | // ), |
| 331 | // None => return Err(err!( |
| 332 | // "The configuration currently requires a proof of work validator, \ |
| 333 | // but the PowVars supplied is None.", |
| 334 | // ), Bug, Configuration)), |
| 335 | |
| 336 | // }, |
| 337 | // false => None, |
| 338 | // } |
| 339 | // }) |
| 340 | //} |
| 341 | |
| 342 | pub fn get_trusted_seeds(&self) -> Outcome<Vec<SocketAddr>> { |
| 343 | |
| 344 | if self.trusted_seeds.len() < constant::TRUSTED_SEEDS_MIN { |
| 345 | return Err(err!( |
| 346 | "ServerConfig: The number of trusted seeds must be at least {}.", |
| 347 | constant::TRUSTED_SEEDS_MIN; |
| 348 | Invalid, Input, TooSmall)); |
| 349 | } |
| 350 | |
| 351 | let mut result = Vec::new(); |
| 352 | for seed in &self.trusted_seeds { |
| 353 | match fmt!("{}:{}", seed, self.server_port_udp).to_socket_addrs() { |
| 354 | Ok(mut addrs) => match addrs.next() { |
| 355 | Some(addr) => result.push(addr), |
| 356 | None => return Err(err!( |
| 357 | "Could not resolve trusted seed '{}'.", seed; |
| 358 | Invalid, Input, Network)), |
| 359 | }, |
| 360 | Err(e) => return Err(err!(e, |
| 361 | "Could not resolve trusted seed '{}'.", seed; |
| 362 | Invalid, Input, Network)), |
| 363 | } |
| 364 | } |
| 365 | Ok(result) |
| 366 | } |
| 367 | } |