/*
* Copyright (c) 2023 Stalwart Labs Ltd.
*
* This file is part of Stalwart Mail Server.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* in the LICENSE file at the top-level directory of this distribution.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* You can be released from the requirements of the AGPLv3 license by
* purchasing a commercial license. Please contact licensing@stalw.art
* for more details.
*/
use std::{collections::HashMap, sync::Arc};
use config::Config;
pub mod acme;
pub mod codec;
pub mod config;
pub mod expr;
pub mod ipc;
pub mod listener;
pub mod map;
pub mod snowflake;
pub mod suffixlist;
use opentelemetry::KeyValue;
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::{
trace::{self, Sampler},
Resource,
};
use opentelemetry_semantic_conventions::resource::{SERVICE_NAME, SERVICE_VERSION};
use rustls::{
client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
ClientConfig, RootCertStore, SignatureScheme,
};
use rustls_pki_types::TrustAnchor;
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::{prelude::__tracing_subscriber_SubscriberExt, EnvFilter};
pub const BLOB_HASH_LEN: usize = 32;
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct BlobHash([u8; BLOB_HASH_LEN]);
impl BlobHash {
pub fn new_max() -> Self {
BlobHash([u8::MAX; BLOB_HASH_LEN])
}
pub fn try_from_hash_slice(value: &[u8]) -> Result {
value.try_into().map(BlobHash)
}
pub fn as_slice(&self) -> &[u8] {
self.0.as_ref()
}
}
impl From<&[u8]> for BlobHash {
fn from(value: &[u8]) -> Self {
BlobHash(blake3::hash(value).into())
}
}
impl From> for BlobHash {
fn from(value: Vec) -> Self {
value.as_slice().into()
}
}
impl From<&Vec> for BlobHash {
fn from(value: &Vec) -> Self {
value.as_slice().into()
}
}
impl AsRef for BlobHash {
fn as_ref(&self) -> &BlobHash {
self
}
}
impl From for Vec {
fn from(value: BlobHash) -> Self {
value.0.to_vec()
}
}
impl AsRef<[u8]> for BlobHash {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl AsMut<[u8]> for BlobHash {
fn as_mut(&mut self) -> &mut [u8] {
self.0.as_mut()
}
}
pub trait UnwrapFailure {
fn failed(self, action: &str) -> T;
}
impl UnwrapFailure for Option {
fn failed(self, message: &str) -> T {
match self {
Some(result) => result,
None => {
tracing::error!("{message}");
eprintln!("{message}");
std::process::exit(1);
}
}
}
}
impl UnwrapFailure for Result {
fn failed(self, message: &str) -> T {
match self {
Ok(result) => result,
Err(err) => {
tracing::error!("{message}: {err}");
#[cfg(feature = "test_mode")]
panic!("{message}: {err}");
#[cfg(not(feature = "test_mode"))]
{
eprintln!("{message}: {err}");
std::process::exit(1);
}
}
}
}
}
pub fn failed(message: &str) -> ! {
tracing::error!("{message}");
eprintln!("{message}");
std::process::exit(1);
}
pub fn enable_tracing(config: &Config, message: &str) -> config::Result