1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use crate::{auth::Credentials, pinky_swear::Pinky, Connection, ConnectionProperties, Result};
use parking_lot::Mutex;
use std::sync::Arc;

#[derive(Clone, Debug, Default)]
pub struct ConnectionStatus {
    inner: Arc<Mutex<Inner>>,
}

impl ConnectionStatus {
    pub fn state(&self) -> ConnectionState {
        self.inner.lock().state.clone()
    }

    pub(crate) fn set_state(&self, state: ConnectionState) {
        self.inner.lock().state = state
    }

    pub fn vhost(&self) -> String {
        self.inner.lock().vhost.clone()
    }

    pub(crate) fn set_vhost(&self, vhost: &str) {
        self.inner.lock().vhost = vhost.into();
    }

    pub fn username(&self) -> String {
        self.inner.lock().username.clone()
    }

    pub(crate) fn set_username(&self, username: &str) {
        self.inner.lock().username = username.into();
    }

    pub(crate) fn block(&self) {
        self.inner.lock().blocked = true;
    }

    pub(crate) fn unblock(&self) {
        self.inner.lock().blocked = false;
    }

    pub fn blocked(&self) -> bool {
        self.inner.lock().blocked
    }

    pub fn connected(&self) -> bool {
        self.inner.lock().state == ConnectionState::Connected
    }

    pub fn closing(&self) -> bool {
        self.inner.lock().state == ConnectionState::Closing
    }

    pub fn closed(&self) -> bool {
        self.inner.lock().state == ConnectionState::Closed
    }

    pub fn errored(&self) -> bool {
        self.inner.lock().state == ConnectionState::Error
    }
}

#[derive(Clone, Debug)]
pub enum ConnectionState {
    Initial,
    SentProtocolHeader(
        Pinky<Result<Connection>, Result<()>>,
        Credentials,
        ConnectionProperties,
    ),
    SentStartOk(Pinky<Result<Connection>, Result<()>>, Credentials),
    SentOpen(Pinky<Result<Connection>, Result<()>>),
    Connected,
    Closing,
    Closed,
    Error,
}

impl Default for ConnectionState {
    fn default() -> Self {
        ConnectionState::Initial
    }
}

impl PartialEq for ConnectionState {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (ConnectionState::Initial, ConnectionState::Initial) => true,
            (ConnectionState::SentProtocolHeader(..), ConnectionState::SentProtocolHeader(..)) => {
                true
            }
            (ConnectionState::SentStartOk(..), ConnectionState::SentStartOk(..)) => true,
            (ConnectionState::SentOpen(_), ConnectionState::SentOpen(_)) => true,
            (ConnectionState::Connected, ConnectionState::Connected) => true,
            (ConnectionState::Closing, ConnectionState::Closing) => true,
            (ConnectionState::Closed, ConnectionState::Closed) => true,
            (ConnectionState::Error, ConnectionState::Error) => true,
            _ => false,
        }
    }
}

#[derive(Debug)]
struct Inner {
    state: ConnectionState,
    vhost: String,
    username: String,
    blocked: bool,
}

impl Default for Inner {
    fn default() -> Self {
        Self {
            state: ConnectionState::default(),
            vhost: "/".into(),
            username: "guest".into(),
            blocked: false,
        }
    }
}