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
use parking_lot::RwLock;

use std::sync::Arc;

use crate::{
  Connection, ConnectionProperties,
  auth::Credentials,
  wait::WaitHandle,
};

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

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

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

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

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

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

  pub(crate) fn unblock(&self) {
    self.inner.write().blocked = true;
  }

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

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

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

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

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

#[derive(Clone, Debug)]
pub enum ConnectionState {
  Initial,
  SentProtocolHeader(WaitHandle<Connection>, Credentials, ConnectionProperties),
  SentStartOk(WaitHandle<Connection>, Credentials),
  SentOpen(WaitHandle<Connection>),
  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,
  blocked: bool,
}

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