diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/config.rs | 8 | ||||
-rw-r--r-- | src/mail_uuid.rs | 76 | ||||
-rw-r--r-- | src/mailbox.rs | 6 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/uidindex.rs | 36 |
5 files changed, 89 insertions, 38 deletions
diff --git a/src/config.rs b/src/config.rs index a1de5ba..3fd0bd4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::io::Read; +use std::net::SocketAddr; use std::path::PathBuf; use anyhow::Result; @@ -13,6 +14,8 @@ pub struct Config { pub login_static: Option<LoginStaticConfig>, pub login_ldap: Option<LoginLdapConfig>, + + pub lmtp: Option<LmtpConfig>, } #[derive(Deserialize, Debug, Clone)] @@ -62,6 +65,11 @@ pub struct LoginLdapConfig { pub bucket_attr: Option<String>, } +#[derive(Deserialize, Debug, Clone)] +pub struct LmtpConfig { + pub bind_addr: SocketAddr, +} + pub fn read_config(config_file: PathBuf) -> Result<Config> { let mut file = std::fs::OpenOptions::new() .read(true) diff --git a/src/mail_uuid.rs b/src/mail_uuid.rs new file mode 100644 index 0000000..d0d582f --- /dev/null +++ b/src/mail_uuid.rs @@ -0,0 +1,76 @@ +use std::sync::atomic::{AtomicU64, Ordering}; + +use lazy_static::lazy_static; +use rand::prelude::*; +use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; + +use crate::time::now_msec; + +/// A Mail UUID is composed of two components: +/// - a process identifier, 128 bits, itself composed of: +/// - the timestamp of when the process started, 64 bits +/// - a 64-bit random number +/// - a sequence number, 64 bits +#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug)] +pub struct MailUuid(pub [u8; 24]); + +struct UuidGenerator { + pid: u128, + sn: AtomicU64, +} + +impl UuidGenerator { + fn new() -> Self { + let time = now_msec() as u128; + let rand = thread_rng().gen::<u64>() as u128; + Self { + pid: (time << 64) | rand, + sn: AtomicU64::new(0), + } + } + + fn gen(&self) -> MailUuid { + let sn = self.sn.fetch_add(1, Ordering::Relaxed); + let mut res = [0u8; 24]; + res[0..16].copy_from_slice(&u128::to_be_bytes(self.pid)); + res[16..24].copy_from_slice(&u64::to_be_bytes(sn)); + MailUuid(res) + } +} + +lazy_static! { + static ref GENERATOR: UuidGenerator = UuidGenerator::new(); +} + +pub fn gen_uuid() -> MailUuid { + GENERATOR.gen() +} + +// -- serde -- + +impl<'de> Deserialize<'de> for MailUuid { + fn deserialize<D>(d: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + let v = String::deserialize(d)?; + let bytes = hex::decode(v).map_err(|_| D::Error::custom("invalid hex"))?; + + if bytes.len() != 24 { + return Err(D::Error::custom("bad length")); + } + + let mut tmp = [0u8; 24]; + tmp[..].copy_from_slice(&bytes); + Ok(Self(tmp)) + } +} + +impl Serialize for MailUuid { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + serializer.serialize_str(&hex::encode(self.0)) + } +} diff --git a/src/mailbox.rs b/src/mailbox.rs index a20ca15..49d8e56 100644 --- a/src/mailbox.rs +++ b/src/mailbox.rs @@ -1,11 +1,11 @@ use anyhow::Result; use k2v_client::K2vClient; -use rand::prelude::*; use rusoto_s3::S3Client; use crate::bayou::Bayou; use crate::cryptoblob::Key; use crate::login::Credentials; +use crate::mail_uuid::*; use crate::uidindex::*; pub struct Mailbox { @@ -38,12 +38,10 @@ impl Mailbox { dump(&self.uid_index); - let mut rand_id = [0u8; 24]; - rand_id[..16].copy_from_slice(&u128::to_be_bytes(thread_rng().gen())); let add_mail_op = self .uid_index .state() - .op_mail_add(MailUuid(rand_id), vec!["\\Unseen".into()]); + .op_mail_add(gen_uuid(), vec!["\\Unseen".into()]); self.uid_index.push(add_mail_op).await?; dump(&self.uid_index); diff --git a/src/main.rs b/src/main.rs index ada94fc..b8231f1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod bayou; mod config; mod cryptoblob; mod login; +mod mail_uuid; mod mailbox; mod server; mod time; diff --git a/src/uidindex.rs b/src/uidindex.rs index 1e30190..ecd52ff 100644 --- a/src/uidindex.rs +++ b/src/uidindex.rs @@ -1,17 +1,12 @@ use im::OrdMap; -use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::bayou::*; +use crate::mail_uuid::MailUuid; type ImapUid = u32; type ImapUidvalidity = u32; -/// A Mail UUID is composed of two components: -/// - a process identifier, 128 bits -/// - a sequence number, 64 bits -#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug)] -pub struct MailUuid(pub [u8; 24]); - #[derive(Clone)] pub struct UidIndex { pub mail_uid: OrdMap<MailUuid, ImapUid>, @@ -176,30 +171,3 @@ impl Serialize for UidIndex { val.serialize(serializer) } } - -impl<'de> Deserialize<'de> for MailUuid { - fn deserialize<D>(d: D) -> Result<Self, D::Error> - where - D: Deserializer<'de>, - { - let v = String::deserialize(d)?; - let bytes = hex::decode(v).map_err(|_| D::Error::custom("invalid hex"))?; - - if bytes.len() != 24 { - return Err(D::Error::custom("bad length")); - } - - let mut tmp = [0u8; 24]; - tmp[..].copy_from_slice(&bytes); - Ok(Self(tmp)) - } -} - -impl Serialize for MailUuid { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - serializer.serialize_str(&hex::encode(self.0)) - } -} |