rustpbx 0.4.4

A SIP PBX implementation in Rust
Documentation
use crate::call::SipUser;
use rsipstack::transaction::key::TransactionKey;
use std::{
    sync::{Arc, RwLock},
    time::Duration,
};

#[derive(Default)]
pub enum SpamResult {
    #[default]
    Nice,
    Spam,
    IpBlacklist,
    UaBlacklist,
}

impl SpamResult {
    fn is_spam(&self) -> bool {
        !matches!(self, SpamResult::Nice)
    }
}

#[derive(Default)]
struct TransactionCookieInner {
    user: Option<SipUser>,
    spam_result: SpamResult,
    max_duration: Option<Duration>,
    extensions: http::Extensions,
}
#[derive(Clone, Default)]
pub struct TransactionCookie {
    inner: Arc<RwLock<TransactionCookieInner>>,
}

impl From<&TransactionKey> for TransactionCookie {
    fn from(_key: &TransactionKey) -> Self {
        Self {
            inner: Arc::new(RwLock::new(TransactionCookieInner {
                user: None,
                spam_result: SpamResult::Nice,
                max_duration: None,
                extensions: http::Extensions::new(),
            })),
        }
    }
}

impl TransactionCookie {
    pub fn set_user(&self, user: SipUser) {
        if let Ok(mut inner) = self.inner.write() {
            inner.user = Some(user);
        }
    }
    pub fn get_user(&self) -> Option<SipUser> {
        self.inner
            .read()
            .map(|inner| inner.user.clone())
            .ok()
            .flatten()
    }

    pub fn mark_as_spam(&self, r: SpamResult) {
        self.inner
            .try_write()
            .map(|mut inner| {
                inner.spam_result = r;
            })
            .ok();
    }

    pub fn is_spam(&self) -> bool {
        self.inner
            .try_read()
            .map(|inner| inner.spam_result.is_spam())
            .ok()
            .unwrap_or_default()
    }

    pub fn set_max_duration(&self, duration: Duration) {
        self.inner
            .try_write()
            .map(|mut inner| {
                inner.max_duration = Some(duration);
            })
            .ok();
    }

    pub fn get_max_duration(&self) -> Option<Duration> {
        self.inner
            .try_read()
            .map(|inner| inner.max_duration)
            .ok()
            .flatten()
    }

    pub fn with_extensions<F, R>(&self, f: F) -> Option<R>
    where
        F: FnOnce(&http::Extensions) -> R,
    {
        self.inner.read().ok().map(|inner| f(&inner.extensions))
    }

    pub fn with_extensions_mut<F, R>(&self, f: F) -> Option<R>
    where
        F: FnOnce(&mut http::Extensions) -> R,
    {
        self.inner
            .write()
            .ok()
            .map(|mut inner| f(&mut inner.extensions))
    }

    pub fn insert_extension<T: Clone + Send + Sync + 'static>(&self, val: T) {
        self.with_extensions_mut(|ext| ext.insert(val));
    }

    pub fn get_extension<T: Clone + Send + Sync + 'static>(&self) -> Option<T> {
        self.with_extensions(|ext| ext.get::<T>().cloned())
            .flatten()
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CalleeDisplayName(pub String);

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CalleeOfflineMarker;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TenantId(pub i64);

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TrunkContext {
    pub id: Option<i64>,
    pub name: String,
    pub tenant_id: Option<i64>,
    pub did_numbers: Vec<String>,
}