chiark / gitweb /
support: Move config
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 14 May 2022 19:18:55 +0000 (20:18 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 14 May 2022 19:32:42 +0000 (20:32 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
25 files changed:
Cargo.lock
Cargo.toml
apitest/apitest.rs
cli/otter.rs
src/accounts.rs
src/bin/otterlib.rs
src/bundles.rs
src/commands.rs
src/crates.rs
src/error.rs
src/global.rs
src/imports.rs
src/lib.rs
src/shapelib.rs
src/utils.rs
support/Cargo.toml
support/authproofs.rs [moved from src/authproofs.rs with 100% similarity]
support/config.rs [moved from src/config.rs with 94% similarity]
support/crates.rs
support/fake-rng.rs [moved from src/fake-rng.rs with 90% similarity]
support/fake-time.rs [moved from src/fake-time.rs with 91% similarity]
support/imports.rs
support/lib.rs
support/support.rs
support/toml-de.rs [moved from src/toml-de.rs with 99% similarity]

index dd68c43ddf2aff70ec5766e42810c980edd1d7a0..735bead6d1e454a79d127c86856f92e4370b3a93 100644 (file)
@@ -2690,8 +2690,6 @@ dependencies = [
  "enum_dispatch",
  "env_logger 0.9.0",
  "fehler",
- "flexi_logger",
- "fs2",
  "glob",
  "humantime-serde",
  "image",
@@ -2699,7 +2697,6 @@ dependencies = [
  "inventory",
  "lazy-init",
  "lazy-regex",
- "lazy_static",
  "libc",
  "mio 0.8.2",
  "num",
@@ -2708,10 +2705,7 @@ dependencies = [
  "openssh-keys",
  "ordered-float",
  "otter-support",
- "paste",
  "percent-encoding",
- "pwd",
- "rand 0.8.5",
  "regex",
  "serde",
  "serde_with",
@@ -2723,7 +2717,6 @@ dependencies = [
  "tempfile",
  "tera",
  "thiserror",
- "toml",
  "typetag",
  "uds",
  "unicase",
@@ -2830,17 +2823,24 @@ dependencies = [
  "console",
  "derive-into-owned",
  "fehler",
+ "flexi_logger",
+ "fs2",
+ "lazy_static",
  "log",
  "nix 0.23.1",
  "num-derive",
  "num-traits",
  "otter-base",
  "parking_lot",
+ "paste",
+ "pwd",
+ "rand 0.8.5",
  "rmp",
  "rmp-serde",
  "serde",
  "serde_with",
  "strum",
+ "toml",
  "unicode-width",
 ]
 
index de459ba56b0194d3ed6df1e980cc73a009a57b5f..0a04a8245fe02b4e203320c8c44562f0f200383b 100644 (file)
@@ -44,29 +44,23 @@ educe="0.4"
 either="1"
 enum_dispatch="0.3.5"
 env_logger="0.9"
-fs2="0.4"
 glob="0.3"
 humantime-serde="1"
 inventory="0.2"
 lazy-init="0.5"
 lazy-regex="2"
-lazy_static="1"
 libc="0.2"
 num="0.4"
 once_cell="1"
 openssh-keys="0.5"
 ordered-float="2"
-paste="1"
 percent-encoding="2"
-pwd="1"
-rand="0.8"
 regex="1"
 structopt="0.3"
 sha2="0.10"
 subtle="2.4"
 tempfile="3"
 tera="1.10"
-toml="0.5"
 typetag="0.1.6"
 uds="0.2"
 unicase="2"
@@ -80,7 +74,6 @@ ambassador = "0.3.1"
 async-condvar-fair = { version="0.2", features=["parking_lot_0_12"] }
 const-default = { version="1",    features=["derive"      ] }
 enum-map     = { version="2"    , features=["serde"       ] }
-flexi_logger = { version="0.22" , features=["specfile"    ] }
 image = { version = "0.24", default-features=false, features=["jpeg","png"] }
 index_vec    = { version="0.1.1", features=["serde"       ] }
 mio          = { version="0.8",   features=["os-ext", "os-poll" ] }
index 3a1979c014ca3192e5c65adc2f1ba6cb5b3d87db..91145c53678d0c946a74b395bbd6af2b8e9da8c9 100644 (file)
@@ -34,7 +34,7 @@ pub type MC = MgmtCommand;
 
 // -------------------- private crates ----------
 
-use otter::config::DAEMON_STARTUP_REPORT;
+use otter_support::config::DAEMON_STARTUP_REPORT;
 
 // ==================== public constants ====================
 
index c8dae276aca9dfa1d0dde721c22be6c09a15daf3..91d99dd6fdf8fbf9add4ad9f81760a7f99f2fc35 100644 (file)
@@ -267,7 +267,7 @@ fn main() {
             });
           ServerConfig::read(Some(&config_filename), default())
             .context("read config file")?;
-          Ok::<_,AE>((otter::config::config(), config_filename))
+          Ok::<_,AE>((otter_support::config::config(), config_filename))
         })().map_err(|e| ArgumentParseError(
           format!("failed to find/load config: {}", &e)
         ))
index fb3c6fe7cb8504e8361702e3030f93a6be42503a..cd0fd83788ce0f37d582d3127957ca85e1dc8276 100644 (file)
@@ -6,8 +6,6 @@ use crate::prelude::*;
 
 use parking_lot::{Mutex, const_mutex, MutexGuard};
 
-use authproofs::*;
-
 #[path="sshkeys.rs"]
 pub mod sshkeys;
 
@@ -490,7 +488,6 @@ pub fn load_accounts() {
 
 pub mod loaded_acl {
   use crate::prelude::*;
-  use authproofs::*;
 
   pub trait Perm: FromPrimitive + ToPrimitive +
     Copy + Eq + Hash + Debug + Sync + Send + 'static
index fb05bb40815c782098de8c479e8fc27705dc79e7..4d618c085f2e61e5edd4d09eb6197dedee03941c 100644 (file)
@@ -239,7 +239,7 @@ fn main() {
   const SPLIT: &[char] = &[',', ' '];
 
   for libs in opts.libs.split(SPLIT) {
-    let tlibs = Config1::PathGlob(libs.to_owned());
+    let tlibs = ShapelibConfig1::PathGlob(libs.to_owned());
     load_global_libs(&[tlibs.clone()])?;
   }
   let mut items: Vec<ItemForOutput> = default();
index ca6afe66c6ef234788d8705fd02a0c177bfc9e1d..40b70f271450462c7decd44d0b2e5ba4b2af6466 100644 (file)
@@ -295,8 +295,9 @@ impl Id {
 
 //---------- displaing/presenting/authorising ----------
 
+#[ext(pub)]
 impl Authorisation<InstanceName> {
-  pub fn bundles(self) -> Authorisation<Id> { self.so_promise() }
+  fn bundles(self) -> Authorisation<Id> { self.so_promise() }
 }
 
 impl Display for State {
index 5a9db84a68a853bcc44045ceb6977c99fa845f63..ec44b62fec23b10eb4353edc1902a4c17e952148 100644 (file)
@@ -264,8 +264,8 @@ pub enum MgmtError {
   #[error("{0}")] CoordinateOverflow  (#[from] CoordinateOverflow),
   #[error("TOML syntax error: {0}")]                 TomlSyntaxError(String),
   #[error("TOML structure error: {0}")]              TomlStructureError(String),
-  #[error("RNG is real, command not supported")]     RngIsReal,
-  #[error("Time is real, command not supported")]    TimeIsReal,
+  #[error("{0}, command not supported")] RngIsReal(#[from] RngIsReal),
+  #[error("{0}, command not supported")] TimeIsReal(#[from] TimeIsReal),
   #[error("upload truncated")]                       UploadTruncated,
   #[error("upload corrupted")]                       UploadCorrupted,
   #[error("too many bundles")]                       TooManyBundles,
index 4f30987daff29e266493c771d08792e5266ed52a..e670f638f47376985b9090c9c032718f40e7269e 100644 (file)
@@ -15,23 +15,18 @@ pub use digest;
 pub use educe;
 pub use either;
 pub use env_logger;
-pub use flexi_logger;
-pub use fs2;
 pub use glob;
 pub use humantime_serde::{self, re::humantime};
 pub use index_vec;
 pub use lazy_init;
-pub use lazy_static;
 pub use inventory;
 pub use libc;
 pub use once_cell;
 pub use ordered_float;
-pub use pwd;
 pub use regex;
 pub use sha2;
 pub use slotmap;
 pub use tera;
-pub use toml;
 pub use uds;
 pub use vecdeque_stableix;
 pub use zip as zipfile;
index 47cec919252280902cf9da115db15f68e3c98d19..3b9554eaaa9456a3fbfcf0af393ba2f0a94160f2 100644 (file)
@@ -188,8 +188,6 @@ pub enum Inapplicable {
                                             BadPieceStateForOperation,
 }
 
-pub type StartupError = anyhow::Error;
-
 pub use Fatal::{NoClient,NoPlayer};
 
 pub enum AggregatedIE {
index 50a148128313b37f4f20bd49bdc4c9d16de7a348..115345f872f95703ff09bfe3e0fdab9d71d2a67d 100644 (file)
@@ -217,8 +217,6 @@ pub struct Global {
   // (in order of lock acquisition (L first), so also in order of criticality
   // (perf impact); outermost first, innermost last)
 
-  // slow global locks:
-  pub save_area_lock: Mutex<Option<File>>,
   // <- accounts::accounts ->
   games_table: RwLock<GamesTable>,
 
@@ -226,7 +224,6 @@ pub struct Global {
   // <- InstanceContainer ->
   // inner locks which the game needs:
   dirty: Mutex<VecDeque<InstanceRef>>,
-  pub config: RwLock<WholeServerConfig>,
 
   // fast global lookups
   players: RwLock<TokenTable<PlayerId>>,
@@ -324,14 +321,15 @@ impl InstanceWeakRef {
   }
 }
 
+#[ext(pub)]
 impl<A> Unauthorised<InstanceRef, A> {
   #[throws(GameBeingDestroyed)]
-  pub fn lock<'r>(&'r self) -> Unauthorised<InstanceGuard<'r>, A> {
+  fn lock<'r>(&'r self) -> Unauthorised<InstanceGuard<'r>, A> {
     let must_not_escape = self.by_ref(Authorisation::promise_any());
     Unauthorised::of(must_not_escape.lock()?)
   }
 
-  pub fn lock_even_destroying<'r>(&'r self) -> Unauthorised<InstanceGuard<'r>, A> {
+  fn lock_even_destroying<'r>(&'r self) -> Unauthorised<InstanceGuard<'r>, A> {
     let must_not_escape = self.by_ref(Authorisation::promise_any());
     Unauthorised::of(InstanceGuard {
       c: must_not_escape.lock_even_destroying(),
@@ -339,7 +337,7 @@ impl<A> Unauthorised<InstanceRef, A> {
     })
   }
 
-  pub fn lock_bundles<'r>(&'r self) -> Unauthorised<BundlesGuard<'_>, A> {
+  fn lock_bundles<'r>(&'r self) -> Unauthorised<BundlesGuard<'_>, A> {
     let must_not_escape = self.by_ref(Authorisation::promise_any());
     Unauthorised::of(must_not_escape.lock_bundles())
   }
index 53b659c47d425331058c2f898186f0c15d68afa9..bf7b81be33bc943112814ab2fde1c1faa7678497 100644 (file)
@@ -20,9 +20,7 @@ pub use std::fmt::{self, Debug, Display};
 pub use std::hash::Hash;
 pub use std::iter;
 pub use std::iter::{repeat_with};
-pub use std::marker::PhantomData;
 pub use std::num::{NonZeroUsize, TryFromIntError, Wrapping};
-pub use std::net::{IpAddr, SocketAddr, ToSocketAddrs, Ipv6Addr, Ipv4Addr};
 pub use std::path::PathBuf;
 pub use std::str;
 pub use std::str::FromStr;
@@ -30,7 +28,6 @@ pub use std::string::ParseError;
 pub use std::sync::atomic::AtomicBool;
 pub use std::sync::mpsc;
 pub use std::thread::{self, sleep};
-pub use std::time::{self, Duration, Instant};
 
 pub use async_condvar_fair::{Condvar, BatonExt as _};
 pub use boolinator::Boolinator as _;
@@ -44,21 +41,12 @@ pub use either::{Either, Left, Right};
 pub use enum_dispatch::enum_dispatch;
 pub use enum_map::{Enum, EnumMap};
 pub use fehler::{throw, throws};
-pub use flexi_logger::LogSpecification;
-pub use fs2::FileExt;
 pub use index_vec::{define_index_type, index_vec, IndexSlice, IndexVec};
 pub use lazy_regex::regex;
-pub use lazy_static::lazy_static;
-pub use log::{log, log_enabled};
 pub use ordered_float::OrderedFloat;
-pub use paste::paste;
 pub use percent_encoding::percent_decode_str;
 pub use percent_encoding::utf8_percent_encode;
 pub use percent_encoding::NON_ALPHANUMERIC;
-pub use rand::distributions::Alphanumeric;
-pub use rand::thread_rng;
-pub use rand::Rng;
-pub use rand::prelude::SliceRandom;
 pub use regex::Regex;
 pub use sha2::{Sha512, Sha512_256};
 pub use slotmap::{dense::DenseSlotMap, SparseSecondaryMap, Key as _};
@@ -88,14 +76,11 @@ pub use crate::{deref_to_field, deref_to_field_mut};
 pub use crate::ensure_eq;
 pub use crate::format_by_fmt_hex;
 pub use crate::impl_via_ambassador;
-pub use crate::trace_dbg;
 pub use crate::{want, wantok, wants, want_let, want_failed_internal};
 pub use crate::serde_with_compat;
 
 pub use crate::accounts::loaded_acl::{self, EffectiveACL, LoadedAcl, PermSet};
 pub use crate::accounts::*;
-pub use crate::authproofs::{self, Authorisation, Unauthorised};
-pub use crate::authproofs::AuthorisationSuperuser;
 pub use crate::asseturl::*;
 pub use crate::bundles::{self, InstanceBundles, MgmtBundleListExt};
 pub use crate::commands::{AccessTokenInfo, AccessTokenReport, MgmtError};
@@ -103,12 +88,9 @@ pub use crate::commands::{MgmtCommand, MgmtResponse};
 pub use crate::commands::{MgmtGameInstruction, MgmtGameResponse};
 pub use crate::commands::{MgmtBundleList, MgmtGameUpdateMode};
 pub use crate::commands::{ProgressUpdateMode};
-pub use crate::config::*;
 pub use crate::debugreader::DebugReader;
 pub use crate::digestrw::{self, *};
 pub use crate::error::*;
-pub use crate::fake_rng::*;
-pub use crate::fake_time::*;
 pub use crate::fastsplit::*;
 pub use crate::gamestate::*;
 pub use crate::global::*;
@@ -129,7 +111,6 @@ pub use crate::shapelib::{LibraryLoadError};
 pub use crate::slotmap_slot_idx::*;
 pub use crate::spec::*;
 pub use crate::spec::piece_specs::{FaceColourSpecs, SimpleCommon};
-pub use crate::toml_de;
 pub use crate::timedfd::*;
 pub use crate::updates::*;
 pub use crate::utils::*;
@@ -142,8 +123,6 @@ pub type SecondarySlotMap<K,V> = slotmap::secondary::SecondaryMap<K,V>;
 pub type SvgData = Vec<u8>;
 pub type Colour = Html;
 
-pub const MS: time::Duration = time::Duration::from_millis(1);
-
 // ---------- type abbreviations ----------
 
 // accounts.rs
index 2a3762bc1a01da1e2eb653b9250faf37803eef2a..d9dcc27da3f00d02348ccd6d9efa68a44bbae61b 100644 (file)
@@ -24,11 +24,9 @@ pub mod prelude;
 
 pub mod accounts;
 pub mod asseturl;
-pub mod authproofs;
 pub mod bundles;
 pub mod clock;
 pub mod commands;
-pub mod config;
 pub mod currency;
 pub mod deck;
 pub mod dice;
@@ -55,9 +53,6 @@ pub mod updates;
 pub mod ui;
 pub mod utils;
 
-#[path = "fake-rng.rs"]           pub mod fake_rng;
-#[path = "fake-time.rs"]          pub mod fake_time;
 #[path = "materials-format.rs"]   pub mod materials_format;
 #[path = "shapelib-toml.rs"]      pub mod shapelib_toml;
 #[path = "slotmap-slot-idx.rs"]   pub mod slotmap_slot_idx;
-#[path = "toml-de.rs"]            pub mod toml_de;
index 475819f217d070363686e74a132d686d6ff5315c..988fd604442f51d57272a86cd8422b7a1134da6f 100644 (file)
@@ -10,6 +10,9 @@ pub use crate::prelude::GoodItemName; // not sure why this is needed
 use parking_lot::{const_rwlock, RwLock};
 use parking_lot::RwLockReadGuard;
 
+use ShapelibConfig1 as Config1;
+use ShapelibExplicit1 as Explicit1;
+
 //==================== structs and definitions ====================
 
 // Naming convention:
@@ -1504,20 +1507,6 @@ impl<'ig> AllRegistries<'ig> {
 
 //==================== configu and loading global libs ====================
 
-#[derive(Deserialize,Debug,Clone)]
-#[serde(untagged)]
-pub enum Config1 {
-  PathGlob(String),
-  Explicit(Explicit1),
-}
-
-#[derive(Deserialize,Debug,Clone)]
-pub struct Explicit1 {
-  pub name: String,
-  pub catalogue: String,
-  pub dirname: String,
-}
-
 #[throws(LibraryLoadError)]
 pub fn load_1_global_library(l: &Explicit1) {
   let toml_path = &l.catalogue;
@@ -1542,7 +1531,8 @@ pub fn load_1_global_library(l: &Explicit1) {
         count, &l.name, &l.catalogue, &l.dirname);
 }
 
-impl Config1 {
+#[ext(pub)]
+impl ShapelibConfig1 {
   fn resolve(&self) -> Result<Box<dyn ExactSizeIterator<Item=Explicit1>>, LibraryLoadError> {
     use Config1::*;
     Ok(match self {
index 6aa057444f2fef5a9c7d8f410e68e9e0903c8c07..f653cb8c1ffef5476e047d974f8a4446c2ec7969 100644 (file)
@@ -125,23 +125,6 @@ pub mod timespec_serde {
   }
 }
 
-//---------- IpAddress ----------
-
-pub trait IpAddress: Debug {
-  fn with_port(&self, port: u16) -> SocketAddr;
-}
-
-impl<A> IpAddress for A where A: Into<IpAddr> + Debug + Clone {
-  fn with_port(&self, port: u16) -> SocketAddr {
-    match (self.clone().into(), port)
-      .to_socket_addrs()
-      .map(|i| i.at_most_one()) {
-        Ok(Ok(Some(addr))) => addr,
-        x => panic!("{:?},{} gave {:?}", self, port, x),
-      }
-  }
-}
-
 //---------- get_or_extend_with ----------
 
 
@@ -333,74 +316,6 @@ impl<Y: Sync, E: Sync, F: Sync + FnOnce() -> Result<Y,E>>
 
 // todo: DerefMut
 
-//========== toml ====================
-
-#[derive(Debug,Copy,Clone,Eq,PartialEq,Ord,PartialOrd)]
-pub struct TomlQuote<'s>(pub &'s str);
-
-// We reimplement this because the toml crate doesn't expose it, and
-// looking at the github issues etc. for that crate isn't encuraging.
-impl<'s> Display for TomlQuote<'s> {
-  #[throws(fmt::Error)]
-  fn fmt(&self, f: &mut fmt::Formatter) {
-    for c in self.0.chars() {
-      match c {
-        '"' | '\\'=> write!(f, "\\{}", c)?,
-        c if (c < ' ' && c != '\t') || c == '\x7f' => {
-          write!(f, r#"\u{:04x}"#, c as u32).unwrap();
-          continue;
-        }
-        c => write!(f, "{}", c)?,
-      }
-    }
-  }
-}
-
-#[test]
-fn toml_quote_string_test(){
-  assert_eq!(TomlQuote(r#"w \ "        \a\7fƒ."#).to_string(),
-                       r#"w \\ \"      \u0007\u007fƒ."#);
-}
-
-pub fn toml_merge<'u,
-                  S: 'u + AsRef<str>,
-                  KV: IntoIterator<Item=(&'u S, &'u toml::Value)>
-                  >(
-  table: &mut toml::value::Table,
-  updates: KV,
-) {
-  use toml::value::{Table, Value};
-  type TME<'e> = toml::map::Entry<'e>;
-
-  let mut kv = updates.into_iter().map(|(k, v)| (k.as_ref(), v));
-  inner(table, &mut kv);
-
-  fn inner<'u>(
-    table: &mut Table,
-    updates: &'u mut dyn Iterator<Item=(&'u str, &'u Value)>
-  ) {
-    for (k, v) in updates {
-      let e = table.entry(k);
-      match e {
-        TME::Vacant(ve) => {
-          ve.insert(v.clone());
-        }
-        TME::Occupied(mut oe) => match (oe.get_mut(), v) {
-          (Value::Table(old), Value::Table(new)) => {
-            toml_merge(old, new);
-          }
-          (Value::Array(old), Value::Array(new)) => {
-            old.extend(new.iter().cloned());
-          }
-          (old, new) => {
-            *old = new.clone();
-          }
-        }
-      }
-    }
-  }
-}
-
 //========== .insert() and .remove() on various Entry ==========
 
 macro_rules! entry_define_insert_remove {
@@ -740,11 +655,6 @@ macro_rules! want_let {
 
 //========== miscellaneous macros ==========
 
-paste!{
-  #[cfg(debug_assertions)]
-  pub fn [<x x x>]<T>() -> T { panic!("todo item triggered") }
-}
-
 #[macro_export]
 macro_rules! impl_via_ambassador{
   { 
@@ -765,19 +675,6 @@ macro_rules! impl_via_ambassador{
   } )* }
 }
 
-#[macro_export]
-macro_rules! trace_dbg {
-  ($msg:expr $(,$val:expr)*) => {
-    if log_enabled!(log::Level::Trace) {
-      #[allow(unused_mut)]
-      let mut buf = format!("{}", &$msg);
-      $( write!(&mut buf, " {}={:?}", stringify!($val), &$val).unwrap(); )*
-      trace!("{}", buf);
-    }
-  }
-
-}
-
 #[macro_export]
 macro_rules! ensure_eq {
   ($v1:expr, $v2:expr) => {
index 16b036ceb0e3a54d94269ca40f15b41a58a99a90..70e7610ef1311f768fee4748d0db3b5ff6c802fc 100644 (file)
@@ -33,14 +33,22 @@ chrono-tz="0.6"
 console="0.15"
 derive-into-owned="0.2"
 fehler="1"
+fs2="0.4"
+lazy_static="1"
 log="0.4"
 nix="0.23"
 num-derive="0.3"
 parking_lot="0.12"
+paste="1"
+pwd="1"
+rand="0.8"
 rmp="0.8"
 rmp-serde="1"
+toml="0.5"
 unicode-width="0.1"
 
+flexi_logger = { version="0.22" , features=["specfile"    ] }
+
 # Repeated in other Cargo.toml's because importing does not work properly
 num-traits="0.2"
 serde_with="1"
similarity index 100%
rename from src/authproofs.rs
rename to support/authproofs.rs
similarity index 94%
rename from src/config.rs
rename to support/config.rs
index 9d24e7547834f2cb2b73341e178094a8506d224e..178405c7041acf3f4f425bcbb5069d137fb9cbd6 100644 (file)
@@ -38,7 +38,7 @@ pub struct ServerConfigSpec {
   pub wasm_dir: Option<String>,
   pub log: Option<toml::Value>,
   pub bundled_sources: Option<String>,
-  pub shapelibs: Option<Vec<shapelib::Config1>>,
+  pub shapelibs: Option<Vec<ShapelibConfig1>>,
   pub specs_dir: Option<String>,
   pub sendmail: Option<String>,
   /// for auth keys, split on spaces
@@ -54,6 +54,20 @@ pub struct ServerConfigSpec {
   pub check_bundled_sources: Option<bool>,
 }
 
+#[derive(Deserialize,Debug,Clone)]
+#[serde(untagged)]
+pub enum ShapelibConfig1 {
+  PathGlob(String),
+  Explicit(ShapelibExplicit1),
+}
+
+#[derive(Deserialize,Debug,Clone)]
+pub struct ShapelibExplicit1 {
+  pub name: String,
+  pub catalogue: String,
+  pub dirname: String,
+}
+
 #[derive(Debug,Clone)]
 pub struct WholeServerConfig {
   server: Arc<ServerConfig>,
@@ -74,7 +88,7 @@ pub struct ServerConfig {
   pub libexec_dir: String,
   pub usvg_bin: String,
   pub bundled_sources: String,
-  pub shapelibs: Vec<shapelib::Config1>,
+  pub shapelibs: Vec<ShapelibConfig1>,
   pub specs_dir: String,
   pub sendmail: String,
   pub ssh_proxy_bin: String,
@@ -213,7 +227,7 @@ impl ServerConfigSpec {
 
     let shapelibs = shapelibs.unwrap_or_else(||{
       let glob = defpath(None, DEFAULT_LIBRARY_GLOB);
-      vec![ shapelib::Config1::PathGlob(glob) ]
+      vec![ ShapelibConfig1::PathGlob(glob) ]
     });
 
     let sendmail = prctx.resolve(&sendmail.unwrap_or_else(
@@ -318,15 +332,21 @@ impl ServerConfigSpec {
   }
 }
 
+lazy_static! {
+  static ref SAVE_AREA_LOCK: Mutex<Option<File>> = default();
+
+  static ref CONFIG: RwLock<WholeServerConfig> = default();
+}
+
 pub fn config() -> Arc<ServerConfig> {
-  GLOBAL.config.read().server.clone()
+  CONFIG.read().server.clone()
 }
 pub fn log_config() -> LogSpecification {
-  GLOBAL.config.read().log.clone()
+  CONFIG.read().log.clone()
 }
 
 fn set_config(whole: WholeServerConfig) {
-  *GLOBAL.config.write() = whole;
+  *CONFIG.write() = whole;
 }
 
 impl ServerConfig {
@@ -346,7 +366,7 @@ impl ServerConfig {
 
   #[throws(AE)]
   pub fn lock_save_area(&self) {
-    let mut st = GLOBAL.save_area_lock.lock();
+    let mut st = SAVE_AREA_LOCK.lock();
     let st = &mut *st;
     if st.is_none() {
       let lockfile = format!("{}/lock", config().save_dir);
@@ -359,7 +379,7 @@ impl ServerConfig {
   }
 
   pub fn save_dir(&self) -> &String {
-    let st = GLOBAL.save_area_lock.lock();
+    let st = SAVE_AREA_LOCK.lock();
     let mut _f: &File = st.as_ref().unwrap();
     &self.save_dir
   }
index 46f0e18ce2a0c90ba5cf9734e145417d4a63c83a..fc964f5ff50371e82b3bbd9fd22ac66dbe2984fe 100644 (file)
@@ -9,8 +9,14 @@ pub use otter_base;
 pub use anyhow;
 pub use chrono;
 pub use chrono_tz;
+pub use flexi_logger;
+pub use fs2;
+pub use lazy_static;
 pub use log;
 pub use nix;
 pub use parking_lot;
+pub use pwd;
+pub use rand;
 pub use rmp_serde;
+pub use toml;
 pub use unicode_width;
similarity index 90%
rename from src/fake-rng.rs
rename to support/fake-rng.rs
index 6522b3c7d2242a29277461f4fd15b6b722ad237c..c157fd8635cfe60f3d11b3521e62d6487ba7bc9d 100644 (file)
@@ -11,6 +11,10 @@ use rand::distributions::uniform::SampleUniform;
 #[serde(transparent)]
 pub struct FakeRngSpec(Option<Vec<String>>);
 
+#[derive(Serialize,Deserialize,Error,Debug,Clone)]
+#[error("RNG is real")]
+pub struct RngIsReal;
+
 impl FakeRngSpec {
   pub fn make_game_rng(self) -> RngWrap { RngWrap( match self.0 {
     None => None,
@@ -35,9 +39,9 @@ struct FakeRng {
 impl RngWrap {
   pub fn is_fake(&self) -> bool { self.0.is_some() }
 
-  #[throws(MgmtError)]
+  #[throws(RngIsReal)]
   pub fn set_fake(&self, v: Vec<String>, _: AuthorisationSuperuser) {
-    let mut fake = self.0.as_ref().ok_or(ME::RngIsReal)?.lock();
+    let mut fake = self.0.as_ref().ok_or(RngIsReal)?.lock();
     fake.i = 0;
     fake.ents = v;
   }
similarity index 91%
rename from src/fake-time.rs
rename to support/fake-time.rs
index 0ac9b770d7468de3507dc648cb2cd80d7d24e5b4..c9089731f414d5de00df08ba20a981cbe3a5ec79 100644 (file)
@@ -9,6 +9,10 @@ use parking_lot::Mutex;
 type Millis = u32;
 type Micros = u64;
 
+#[derive(Serialize,Deserialize,Error,Debug,Clone)]
+#[error("Time is real")]
+pub struct TimeIsReal;
+
 #[derive(Deserialize,Debug,Clone,Default)]
 #[serde(transparent)]
 pub struct FakeTimeConfig(pub Option<FakeTimeSpec>);
@@ -81,9 +85,9 @@ impl GlobalClock {
     fake.start + Duration::from_micros(fake.current)
   }
 
-  #[throws(MgmtError)]
+  #[throws(TimeIsReal)]
   pub fn set_fake(&self, fspec: FakeTimeSpec, _: AuthorisationSuperuser) {
-    let mut guard = self.fakeable.as_ref().ok_or(ME::TimeIsReal)?.lock();
+    let mut guard = self.fakeable.as_ref().ok_or(TimeIsReal)?.lock();
     *guard = FakeClock::from_spec(fspec)
   }
 
index c2c7c11a1587b301b6397a7d6835be4ca9bce5da..17df3a6358831f47b30e0be0d33720712dbc22e4 100644 (file)
@@ -16,6 +16,8 @@ pub use std::fs::File;
 pub use std::io;
 pub use std::io::ErrorKind;
 pub use std::io::{BufRead, BufReader, BufWriter, Read, Write};
+pub use std::marker::PhantomData;
+pub use std::net::{IpAddr, SocketAddr, ToSocketAddrs, Ipv6Addr, Ipv4Addr};
 pub use std::os::linux::fs::MetadataExt as _; // todo why linux for st_mode??
 pub use std::os::unix;
 pub use std::os::unix::ffi::OsStrExt;
@@ -25,16 +27,26 @@ pub use std::os::unix::net::UnixStream;
 pub use std::os::unix::process::{CommandExt, ExitStatusExt};
 pub use std::process::{exit, Child, Command, Stdio};
 pub use std::sync::Arc;
+pub use std::time::{self, Duration, Instant};
 
 pub use anyhow::{anyhow, ensure, Context};
 pub use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt};
 pub use derive_into_owned::IntoOwned;
+pub use flexi_logger::LogSpecification;
+pub use fs2::FileExt;
+pub use lazy_static::lazy_static;
 pub use log::{debug, error, info, trace, warn};
+pub use log::{log, log_enabled};
 pub use nix::unistd::{self, Uid};
 pub use nix::sys::time::TimeSpec;
 pub use nix::time::clock_gettime;
 pub use num_derive::{ToPrimitive, FromPrimitive};
 pub use num_traits::{Bounded, FromPrimitive, ToPrimitive};
+pub use paste::paste;
+pub use rand::distributions::Alphanumeric;
+pub use rand::thread_rng;
+pub use rand::Rng;
+pub use rand::prelude::SliceRandom;
 pub use serde::ser::SerializeTuple;
 pub use serde::{de::DeserializeOwned, Deserialize, Serialize};
 pub use serde::de::Error as _;
@@ -53,17 +65,28 @@ pub use parking_lot::{Mutex, MutexGuard};
 //pub use crate::debugmutex::{Mutex, MutexGuard};
 
 pub use crate::matches_doesnot;
+pub use crate::trace_dbg;
 
+pub use crate::authproofs::{self, Authorisation, Unauthorised};
+pub use crate::authproofs::AuthorisationSuperuser;
 pub use crate::childio;
+pub use crate::config::*;
 pub use crate::debugmutex::DebugIdentify;
+pub use crate::fake_rng::*;
+pub use crate::fake_time::*;
 pub use crate::packetframe::{FrameReader, FrameWriter, ReadFrame, WriteFrame};
 pub use crate::packetframe::{ReadExt, ResponseWriter};
 pub use crate::packetframe::{PacketFrameReadError, PacketFrameWriteError};
 pub use crate::progress::{self, ProgressInfo, OriginatorExt as _};
 pub use crate::support::*;
 pub use crate::termprogress;
+pub use crate::toml_de;
 pub use crate::tz::*;
 
+pub type StartupError = anyhow::Error;
+
+pub const MS: time::Duration = time::Duration::from_millis(1);
+
 // ---------- type abbreviations ----------
 
 pub type AE = anyhow::Error;
index 0307bc497cedbe8c96182d664f0e5afccf9cb965..17e2627bcc9d50d0129fd536db94a4d035c8c8da 100644 (file)
@@ -6,10 +6,16 @@ pub mod crates;
 pub mod imports;
 pub mod prelude;
 
+pub mod authproofs;
 pub mod childio;
+pub mod config;
 pub mod debugmutex;
 pub mod packetframe;
 pub mod progress;
 pub mod support;
 pub mod termprogress;
 pub mod tz;
+
+#[path = "fake-rng.rs"]           pub mod fake_rng;
+#[path = "fake-time.rs"]          pub mod fake_time;
+#[path = "toml-de.rs"]            pub mod toml_de;
index c5aa50031b02d5dca6369210fbe1f61ae1bae040..5f174bbb80db060d2bfc6a0a0ee41180d50e65a2 100644 (file)
@@ -4,6 +4,94 @@
 
 use crate::prelude::*;
 
+//========== miscellany ==========
+// (roughly in order of implementation length)
+
+//---------- IpAddress ----------
+
+pub trait IpAddress: Debug {
+  fn with_port(&self, port: u16) -> SocketAddr;
+}
+
+impl<A> IpAddress for A where A: Into<IpAddr> + Debug + Clone {
+  fn with_port(&self, port: u16) -> SocketAddr {
+    match (self.clone().into(), port)
+      .to_socket_addrs()
+      .map(|i| i.at_most_one()) {
+        Ok(Ok(Some(addr))) => addr,
+        x => panic!("{:?},{} gave {:?}", self, port, x),
+      }
+  }
+}
+
+//========== toml ====================
+
+#[derive(Debug,Copy,Clone,Eq,PartialEq,Ord,PartialOrd)]
+pub struct TomlQuote<'s>(pub &'s str);
+
+// We reimplement this because the toml crate doesn't expose it, and
+// looking at the github issues etc. for that crate isn't encuraging.
+impl<'s> Display for TomlQuote<'s> {
+  #[throws(fmt::Error)]
+  fn fmt(&self, f: &mut fmt::Formatter) {
+    for c in self.0.chars() {
+      match c {
+        '"' | '\\'=> write!(f, "\\{}", c)?,
+        c if (c < ' ' && c != '\t') || c == '\x7f' => {
+          write!(f, r#"\u{:04x}"#, c as u32).unwrap();
+          continue;
+        }
+        c => write!(f, "{}", c)?,
+      }
+    }
+  }
+}
+
+#[test]
+fn toml_quote_string_test(){
+  assert_eq!(TomlQuote(r#"w \ "        \a\7fƒ."#).to_string(),
+                       r#"w \\ \"      \u0007\u007fƒ."#);
+}
+
+pub fn toml_merge<'u,
+                  S: 'u + AsRef<str>,
+                  KV: IntoIterator<Item=(&'u S, &'u toml::Value)>
+                  >(
+  table: &mut toml::value::Table,
+  updates: KV,
+) {
+  use toml::value::{Table, Value};
+  type TME<'e> = toml::map::Entry<'e>;
+
+  let mut kv = updates.into_iter().map(|(k, v)| (k.as_ref(), v));
+  inner(table, &mut kv);
+
+  fn inner<'u>(
+    table: &mut Table,
+    updates: &'u mut dyn Iterator<Item=(&'u str, &'u Value)>
+  ) {
+    for (k, v) in updates {
+      let e = table.entry(k);
+      match e {
+        TME::Vacant(ve) => {
+          ve.insert(v.clone());
+        }
+        TME::Occupied(mut oe) => match (oe.get_mut(), v) {
+          (Value::Table(old), Value::Table(new)) => {
+            toml_merge(old, new);
+          }
+          (Value::Array(old), Value::Array(new)) => {
+            old.extend(new.iter().cloned());
+          }
+          (old, new) => {
+            *old = new.clone();
+          }
+        }
+      }
+    }
+  }
+}
+
 //========== Timestamp ==========
 
 #[derive(Copy,Clone,Debug,Serialize,Deserialize,Eq,Ord,PartialEq,PartialOrd)]
@@ -26,6 +114,26 @@ impl Timestamp {
   }
 }
 
+//========== miscellaneous macros ==========
+
+paste!{
+  #[cfg(debug_assertions)]
+  pub fn [<x x x>]<T>() -> T { panic!("todo item triggered") }
+}
+
+#[macro_export]
+macro_rules! trace_dbg {
+  ($msg:expr $(,$val:expr)*) => {
+    if log_enabled!(log::Level::Trace) {
+      #[allow(unused_mut)]
+      let mut buf = format!("{}", &$msg);
+      $( write!(&mut buf, " {}={:?}", stringify!($val), &$val).unwrap(); )*
+      trace!("{}", buf);
+    }
+  }
+
+}
+
 //========== matches_doesnot ==========
 
 #[macro_export] // <- otherwise bogus warning `unused_macros`
similarity index 99%
rename from src/toml-de.rs
rename to support/toml-de.rs
index e48a57a9aa26682caec7e5728d36d11bfe0dbd0e..c915dc8ba2ad885402cc25fdf8b85201dad2b131 100644 (file)
@@ -3,7 +3,6 @@
 // There is NO WARRANTY.
 
 use crate::crates::*;
-use otter_support::crates::*;
 use otter_base::crates::*;
 
 use std::fmt::{Debug, Display};