Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #ifndef __XMPP_STATE_MC__ 6 : #define __XMPP_STATE_MC__ 7 : 8 : #include <mutex> 9 : 10 : #include <boost/asio.hpp> 11 : #include <boost/statechart/state_machine.hpp> 12 : 13 : #include "base/queue_task.h" 14 : #include "base/timer.h" 15 : #include "io/ssl_session.h" 16 : #include "xmpp/xmpp_proto.h" 17 : 18 : namespace sc = boost::statechart; 19 : 20 : namespace xmsm { 21 : struct Idle; 22 : struct Active; 23 : struct Connect; 24 : struct OpenSent; 25 : struct OpenConfirm; 26 : struct XmppStreamEstablished; 27 : } 28 : 29 : namespace xmsm { 30 : struct EvStart; 31 : struct Idle; 32 : 33 : typedef enum { 34 : IDLE = 0, 35 : ACTIVE = 1, 36 : CONNECT = 2, 37 : OPENSENT = 3, 38 : OPENCONFIRM = 4, 39 : ESTABLISHED = 5 40 : } XmState; 41 : 42 : typedef enum { 43 : OPENCONFIRM_INIT = 0, 44 : OPENCONFIRM_FEATURE_NEGOTIATION = 1, 45 : OPENCONFIRM_FEATURE_SUCCESS = 2 46 : } XmOpenConfirmState; 47 : 48 : 49 : typedef enum { 50 : EvTLSHANDSHAKE_FAILURE = 0, 51 : EvTLSHANDSHAKE_SUCCESS = 1 52 : } SslHandShakeResponse; 53 : 54 : } 55 : 56 : class XmppConnection; 57 : class XmppSession; 58 : class TcpSession; 59 : class XmppConnectionInfo; 60 : 61 : class XmppStateMachine : 62 : public sc::state_machine<XmppStateMachine, xmsm::Idle> { 63 : public: 64 : static const int kOpenTime = 15; // seconds 65 : static const int kConnectInterval = 30; // seconds 66 : static const int kHoldTime = 90; // seconds 67 : static const int kMaxAttempts = 4; 68 : static const int kJitter = 10; // percentage 69 : 70 : XmppStateMachine(XmppConnection *connection, bool active, bool auth_enabled = false, int config_hold_time = kHoldTime); 71 : ~XmppStateMachine(); 72 : 73 : void Initialize(); 74 : void Clear(); 75 : void SetAdminState(bool down); 76 : 77 : // State transitions 78 : void OnStart(const xmsm::EvStart &event); 79 : 80 : virtual void StartConnectTimer(int seconds); 81 : void CancelConnectTimer(); 82 : virtual void StartOpenTimer(int seconds); 83 : void CancelOpenTimer(); 84 : 85 : int GetConfiguredHoldTime() const; 86 : virtual void StartHoldTimer(); 87 : void CancelHoldTimer(); 88 : void ResetSession(); 89 : 90 22000 : bool IsAuthEnabled() { return auth_enabled_; } 91 : 92 : void TimerErrorHandler(std::string name, std::string error); 93 : 94 : // Feed session events into the state machine. 95 : virtual void OnSessionEvent(TcpSession *session, TcpSession::Event event); 96 : 97 : // Receive Passive Open. 98 : bool PassiveOpen(XmppSession *session); 99 : 100 : // Receive incoming message 101 : void OnMessage(XmppSession *session, const XmppStanza::XmppMessage *msg); 102 : void ProcessMessage(XmppSession *session, 103 : const XmppStanza::XmppMessage *msg); 104 : 105 : // Receive incoming ssl events 106 : //void OnEvent(XmppSession *session, xmsm::SslHandShakeResponse); 107 : void OnEvent(SslSession *session, xmsm::SslHandShakeResponse); 108 : 109 : //void OnSessionError(Error error); 110 : 111 : // transfer the ownership of the session to the connection. 112 : void AssignSession(); 113 : 114 : // Calculate Timer value for active to connect transition. 115 : int GetConnectTime() const; 116 : 117 33 : void SetHandShakeCbHandler(SslHandShakeCallbackHandler cb) { 118 33 : handshake_cb_ = cb; 119 33 : } 120 : 121 2931 : SslHandShakeCallbackHandler HandShakeCbHandler() { return handshake_cb_; } 122 : 123 : std::string StateName() const; 124 : std::string LastStateName() const; 125 : std::string LastStateChangeAt() const; 126 : xmsm::XmState StateType() const; 127 : xmsm::XmOpenConfirmState OpenConfirmStateType() const; 128 : 129 : // getters and setters 130 29974220 : XmppConnection *connection() { return connection_; } 131 : void set_connection(const XmppConnection *connection) { 132 : connection_ = const_cast<XmppConnection *>(connection); 133 : } 134 : void SwapXmppConnection(XmppStateMachine *other); 135 : bool IsActiveChannel(); 136 : bool logUVE(); 137 : const char *ChannelType(); 138 : void set_session(TcpSession *session); 139 : void clear_session(); 140 : void DeleteSession(XmppSession *session); 141 4183024 : XmppSession *session() { return session_; } 142 0 : void RemoveSession() { session_ = NULL; } 143 : void set_state(xmsm::XmState state); 144 37630 : xmsm::XmState get_state() { return state_; } 145 : void set_openconfirm_state(xmsm::XmOpenConfirmState state); 146 73 : xmsm::XmOpenConfirmState get_openconfirm_state() { 147 73 : return openconfirm_state_; 148 : } 149 : 150 7563 : void connect_attempts_inc() { attempts_++; } 151 3023 : void connect_attempts_clear() { attempts_ = 0; } 152 9012 : int get_connect_attempts() const { return attempts_; } 153 : 154 2481526 : void keepalive_count_inc() { keepalive_count_++; } 155 15710 : void keepalive_count_clear() { keepalive_count_ = 0; } 156 2481789 : int get_keepalive_count() const { return keepalive_count_; } 157 : 158 990 : int hold_time() const { return hold_time_; } 159 12388 : virtual int hold_time_msecs() const { return hold_time_ * 1000; } 160 6552 : void set_hold_time(int hold_time) { hold_time_ = hold_time; } 161 : 162 : void unconsumed_event(const sc::event_base &event); 163 : 164 : void SendConnectionInfo(const std::string &event, 165 : const std::string &nextstate = ""); 166 : 167 : void SendConnectionInfo(XmppConnectionInfo *info, const std::string &event, 168 : const std::string &nextstate = ""); 169 : void ResurrectOldConnection(XmppConnection *connection, 170 : XmppSession *session); 171 : 172 4178226 : void set_last_event(const std::string &event) { 173 4178226 : std::scoped_lock lock(mutex_); 174 4178230 : last_event_ = event; 175 4178226 : last_event_at_ = UTCTimestampUsec(); 176 4178230 : } 177 : 178 : void update_last_event(const std::string &event); 179 : 180 559 : const std::string last_event() const { 181 559 : std::scoped_lock lock(mutex_); 182 1118 : return last_event_; 183 559 : } 184 : 185 7485 : bool ConnectTimerCancelled() { return connect_timer_->cancelled(); } 186 1 : bool OpenTimerCancelled() { return open_timer_->cancelled(); } 187 13 : bool HoldTimerCancelled() { return hold_timer_->cancelled(); } 188 : void AssertOnHoldTimeout(); 189 : bool HoldTimerExpired(); 190 1420 : const Timer *hold_timer() const { return hold_timer_; } 191 : 192 : private: 193 : friend class XmppStateMachineTest; 194 : 195 : bool ConnectTimerExpired(); 196 : bool OpenTimerExpired(); 197 : bool Enqueue(const sc::event_base &ev); 198 : bool DequeueEvent(boost::intrusive_ptr<const sc::event_base> event); 199 : void ProcessEvent(const sc::event_base &event); 200 : void ProcessStreamHeaderMessage(XmppSession *session, 201 : const XmppStanza::XmppMessage *msg); 202 : 203 : WorkQueue<boost::intrusive_ptr<const sc::event_base> > work_queue_; 204 : XmppConnection *connection_; 205 : XmppSession *session_; 206 : TcpServer *server_; 207 : Timer *connect_timer_; 208 : Timer *open_timer_; 209 : Timer *hold_timer_; 210 : int config_hold_time_; 211 : int hold_time_; 212 : uint32_t attempts_; 213 : uint32_t keepalive_count_; 214 : bool deleted_; 215 : bool in_dequeue_; 216 : bool is_active_; 217 : bool auth_enabled_; 218 : xmsm::XmState state_; 219 : xmsm::XmState last_state_; 220 : xmsm::XmOpenConfirmState openconfirm_state_; 221 : uint64_t state_since_; 222 : std::string last_event_; 223 : uint64_t last_event_at_; 224 : SslHandShakeCallbackHandler handshake_cb_; 225 : mutable std::mutex mutex_; 226 : 227 : DISALLOW_COPY_AND_ASSIGN(XmppStateMachine); 228 : }; 229 : 230 : #endif