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
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 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
  }
}

#[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,
    }
  }
}