aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2022-05-31 15:49:10 +0200
committerAlex Auvolat <alex@adnab.me>2022-05-31 15:49:10 +0200
commit01d82c14ca61e7c4de1e72c5f94456610464c064 (patch)
tree20ada5789d449182e18c3a18751ffd0473486614 /src
parentd53cf1d220ef08c0b9368cfe91bee7660b7f5a3b (diff)
downloadaerogramme-01d82c14ca61e7c4de1e72c5f94456610464c064.tar.gz
aerogramme-01d82c14ca61e7c4de1e72c5f94456610464c064.zip
UUID generator; import kannader smtp server
Diffstat (limited to 'src')
-rw-r--r--src/config.rs8
-rw-r--r--src/mail_uuid.rs76
-rw-r--r--src/mailbox.rs6
-rw-r--r--src/main.rs1
-rw-r--r--src/uidindex.rs36
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))
- }
-}