chiark / gitweb /
wip resolve
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 23 Jul 2021 23:33:45 +0000 (00:33 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 23 Jul 2021 23:33:45 +0000 (00:33 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
README.config
src/config.rs
src/prelude.rs

index 37142b8f2b769a68df7d263c025b0757a46c5dae..4afc45ae1960747111c661eec29b35d6cf5d3030 100644 (file)
@@ -3,18 +3,20 @@
 Sections
 
   [<servername> <client>]
-  [<servername> LIMIT]
   [<client>]
   [<servername>]      often [SERVER]
-  [LIMIT]
   [COMMON]
-  [DEFAULT]
 
 Keys are looked up in that order, unless otherwise specified.
 <client> is the client's virtual address.
 <servername> must be a valid lowercase DNS hostname and not look like 
 an address, or be COMMON, DEFAULT or SERVER.
 
+There are also:
+
+  [<servername> LIMIT]
+  [LIMIT]
+
 Things not in a section are an error.
 
 
index 63665f96f15071be3f81fef558da536984388d18..60c090b7ec8fc1f1200618ae0eda66c862225e86 100644 (file)
@@ -26,16 +26,16 @@ pub struct CidrString(pub String);
 pub struct InstanceConfig {
   // Exceptional settings
   pub server:                       String,
-  pub secret:                       String,
+  pub secret:                       String, // make a newytpe
   pub ipif:                         String,
 
   // Capped settings:
   pub max_batch_down:               u32,
   pub max_queue_time:               Duration,
   pub http_timeout:                 Duration,
+  pub target_requests_outstanding:  u32,
 
   // Ordinary settings:
-  pub target_requests_outstanding:  u32,
   pub addrs:                        Vec<IpAddr>,
   pub vnetwork:                     Vec<CidrString>,
   pub vaddr:                        Vec<IpAddr>,
@@ -59,7 +59,7 @@ pub struct InstanceConfig {
 
 #[derive(Debug,Clone,Hash,Eq,PartialEq)]
 pub enum SectionName {
-  Link { server: ServerName, client: ClientName },
+  Link(LinkName),
   Client(ClientName),
   Server(ServerName), // includes SERVER, which is slightly special
   ServerLimit(ServerName),
@@ -69,6 +69,12 @@ pub enum SectionName {
 }
 pub use SectionName as SN;
 
+#[derive(Debug,Clone,Hash,Eq,PartialEq)]
+struct LinkName {
+  server: ServerName,
+  client: ClientName,
+}
+
 #[derive(Debug,Clone)]
 struct RawVal { val: Option<String>, loc: Arc<PathBuf> }
 type SectionMap = HashMap<String, RawVal>;
@@ -116,7 +122,7 @@ impl FromStr for SectionName {
     let server = server.parse().context("server name in link section name")?;
     if client == "LIMIT" { return SN::ServerLimit(server) }
     let client = client.parse().context("client name in link section name")?;
-    SN::Link { server, client }
+    SN::Link(LinkName { server, client })
   }
 }
 
@@ -252,6 +258,102 @@ impl Aggregate {
   }
 }
 
+enum LinkEnd { Server, Client }
+
+struct ResolveContext<'c> {
+  agg: &'c Aggregate,
+  link: &'c LinkName,
+  end: LinkEnd,
+}
+
+impl<'c> ResolveContext<'c> {
+  fn first_of_raw(&self, key: &str,
+                  sections: &[ &dyn Fn() -> SectionName ])
+                  -> Option<&'c RawVal> {
+    for section in sections {
+      if let Some(raw) = self.agg.sections
+        .get(&section())
+        .and_then(|vars: &SectionMap| vars.get(key))
+      {
+        return Some(raw)
+      }
+    }
+    None
+  }
+
+  #[throws(AE)]
+  fn first_of<T>(&self, key: &str,
+                 sections: &[ &dyn Fn() -> SectionName ])
+                 -> Option<T>
+  where T: FromStr
+  {
+    match self.first_of_raw(key, sections) {
+      None => None,
+      Some(raw) => Some({
+        raw.val.parse()
+          .context(key)
+          .context(r#"in section "{}""#, &raw.section)
+          .dcontext(&raw.loc)?
+      }),
+    }
+  }
+
+  pub fn ordinary<T>(&self, key: &str) -> T where T: FromStr + Default {
+    self.first_of(key, &[
+      || SN::Link(self.link.clone()),
+      || SN::Client(self.link.client.clone()),
+      || SN::Server(self.link.server.clone()),
+      || SN::Common,
+    ])?
+      .unwrap_or_default()
+  }
+
+  pub fn limited<T>(&self, key: &str) -> T
+  where T: FromStr + Default + PartialOrd
+  {
+    let val = self.ordinary(key);
+    if let Some(limit) = self.first_of(key, &[
+      || SN::LimitServer(self.link.server.clone()),
+      || SN::LimitGlobal,
+    ])? {
+      val = min(val, limit)
+    }
+    val
+  }
+
+  pub fn client<T>(&self, key: &str) -> T where T: FromStr + Default {
+    match self.end {
+      LinkEnd::Client => self.ordinary(key)?,
+      LinkEnd::Server => default(),
+    }
+  }
+  pub fn server<T>(&self, key: &str) -> T where T: FromStr + Default {
+    match self.end {
+      LinkEnd::Server => self.ordinary(key)?,
+      LinkEnd::Client => default(),
+    }
+  }
+
+  pub fn special_ipif<T>(&self, key: &str) -> T where T: FromStr + Default {
+    match self.end {
+      LinkEnd::Client => self.ordinary(key)?,
+      LinkEnd::Server => {
+        self.first_of(key, &[
+          || SN::Common,
+          || SN::Server(self.link.server.clone()),
+        ])?
+      },
+    }
+  }
+}
+
+/*
+fn resolve_instance_config() {
+  InstanceConfig {
+    max_batch_down: resolve::limited(&agg, "max_batch_down")
+  }
+}
+*/
 
 #[throws(AE)]
 pub fn read() {
index bac8d9de3e3f98386479d5d43b62a9a19bebbe49..29336ff716ff235631c1fb4339bab7694ee9e7aa 100644 (file)
@@ -3,6 +3,7 @@
 // There is NO WARRANTY.
 
 pub use std::collections::HashMap;
+pub use std::cmp::{min, max};
 pub use std::fs;
 pub use std::fmt::Debug;
 pub use std::io::{self, ErrorKind, Read as _};
@@ -28,3 +29,5 @@ pub use crate::types::*;
 
 pub use anyhow::Error as AE;
 pub use ErrorKind as EK;
+
+pub fn default<T:Default>() -> T { Default::default() }