Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "xmpp/xmpp_channel_mux.h" 6 : 7 : #include <boost/foreach.hpp> 8 : 9 : #include "base/task_annotations.h" 10 : #include "xmpp/xmpp_init.h" 11 : #include "xmpp/xmpp_connection.h" 12 : 13 : using namespace std; 14 : using namespace xmsm; 15 : 16 11628 : XmppChannelMux::XmppChannelMux(XmppConnection *connection) 17 11628 : : connection_(connection), rx_message_trace_cb_(NULL), 18 23256 : tx_message_trace_cb_(NULL) { 19 11628 : last_received_ = 0; 20 11628 : last_sent_ = 0; 21 11628 : } 22 : 23 11729 : XmppChannelMux::~XmppChannelMux() { 24 11628 : assert(map_.empty()); 25 11729 : } 26 : 27 545 : void XmppChannelMux::Close() { 28 545 : connection_->Clear(); 29 545 : } 30 : 31 11524 : bool XmppChannelMux::LastReceived(time_t duration) const { 32 11524 : return (UTCTimestamp() - last_received_) <= duration; 33 : } 34 : 35 4916 : bool XmppChannelMux::LastSent(time_t duration) const { 36 4916 : return (UTCTimestamp() - last_sent_) <= duration; 37 : } 38 : 39 3577929 : xmps::PeerState XmppChannelMux::GetPeerState() const { 40 3577929 : xmsm::XmState st = connection_->GetStateMcState(); 41 3577872 : return (st == xmsm::ESTABLISHED) ? xmps::READY : 42 3577872 : xmps::NOT_READY; 43 : } 44 : 45 3 : void XmppChannelMux::WriteReady(const boost::system::error_code &ec) { 46 3 : std::scoped_lock lock(mutex_); 47 : 48 3 : WriteReadyCbMap::iterator iter = map_.begin(); 49 3 : WriteReadyCbMap::iterator next = iter; 50 6 : for (; iter != map_.end(); iter = next) { 51 3 : ++next; 52 3 : SendReadyCb cb = iter->second; 53 3 : cb(ec); 54 3 : map_.erase(iter); 55 3 : } 56 3 : } 57 : 58 1646529 : bool XmppChannelMux::Send(const uint8_t *msg, size_t msgsize, 59 : const string *msg_str, xmps::PeerId id, 60 : SendReadyCb cb) { 61 1646529 : if (!connection_) return false; 62 : 63 1646529 : std::scoped_lock lock(mutex_); 64 1647054 : last_sent_ = UTCTimestamp(); 65 1647209 : bool res = connection_->Send(msg, msgsize, msg_str); 66 1647112 : if (res == false) { 67 105 : RegisterWriteReady(id, cb); 68 : } 69 1647112 : return res; 70 1647112 : } 71 : 72 22394 : int XmppChannelMux::GetTaskInstance() const { 73 22394 : return connection_->GetTaskInstance(); 74 : } 75 : 76 10008 : void XmppChannelMux::RegisterReferer(xmps::PeerId id) { 77 10008 : referers_.insert(id); 78 10008 : } 79 : 80 10008 : void XmppChannelMux::UnRegisterReferer(xmps::PeerId id) { 81 10008 : referers_.erase(id); 82 10008 : } 83 : 84 13973 : void XmppChannelMux::RegisterReceive(xmps::PeerId id, ReceiveCb cb) { 85 13973 : rxmap_.insert(make_pair(id, cb)); 86 13973 : } 87 : 88 14093 : void XmppChannelMux::UnRegisterReceive(xmps::PeerId id) { 89 14093 : ReceiveCbMap::iterator it = rxmap_.find(id); 90 14093 : if (it != rxmap_.end()) { 91 13969 : rxmap_.erase(it); 92 : } 93 : 94 14093 : if (ReceiverCount()) 95 4088 : return; 96 : 97 : XmppServerConnection *server_connection = 98 10257 : dynamic_cast<XmppServerConnection *>(connection_); 99 : 100 : // If GracefulRestart helper mode close process is complete, restart the 101 : // state machine to form new session with the client. 102 10526 : if (!connection_->IsDeleted() && server_connection && 103 269 : server_connection->server()->IsGRHelperModeEnabled()) { 104 252 : server_connection->state_machine()->Initialize(); 105 252 : return; 106 : } 107 : 108 10005 : connection_->RetryDelete(); 109 : } 110 : 111 11690 : size_t XmppChannelMux::RefererCount() const { 112 11690 : return referers_.size(); 113 : } 114 : 115 31965 : size_t XmppChannelMux::ReceiverCount() const { 116 31965 : return rxmap_.size(); 117 : } 118 : 119 72 : vector<string> XmppChannelMux::GetReceiverList() const { 120 72 : vector<string> receivers; 121 96 : for (const auto& value : rxmap_) { 122 24 : receivers.push_back(xmps::PeerIdToName(value.first)); 123 : } 124 72 : return receivers; 125 0 : } 126 : 127 : // 128 : // To be called after acquiring mutex 129 : // 130 106 : void XmppChannelMux::RegisterWriteReady(xmps::PeerId id, SendReadyCb cb) { 131 106 : map_.insert(make_pair(id, cb)); 132 106 : } 133 : 134 : // 135 : // To be called after acquiring mutex 136 : // 137 13869 : void XmppChannelMux::UnRegisterWriteReady(xmps::PeerId id) { 138 13869 : map_.erase(id); 139 13869 : } 140 : 141 1702255 : const std::string &XmppChannelMux::ToString() const { 142 1702255 : return connection_->ToString(); 143 : } 144 : 145 0 : const std::string &XmppChannelMux::FromString() const { 146 0 : return connection_->FromString(); 147 : } 148 : 149 974 : std::string XmppChannelMux::StateName() const { 150 974 : return connection_->StateName(); 151 : } 152 : 153 0 : std::string XmppChannelMux::AuthType() const { 154 0 : return connection_->GetXmppAuthenticationType(); 155 : } 156 : 157 0 : std::string XmppChannelMux::PeerAddress() const { 158 0 : return connection_->endpoint_string(); 159 : } 160 : 161 3217152 : inline bool MatchCallback(string to, xmps::PeerId peer) { 162 3217152 : if ((to.find(XmppInit::kBgpPeer) != string::npos) && 163 : (peer == xmps::BGP)) { 164 1636997 : return true; 165 : } 166 1580158 : if ((to.find(XmppInit::kConfigPeer) != string::npos) && 167 : (peer == xmps::CONFIG)) { 168 0 : return true; 169 : } 170 1580159 : if ((to.find(XmppInit::kDnsPeer) != string::npos) && 171 : (peer == xmps::DNS)) { 172 0 : return true; 173 : } 174 1580159 : if ((to.find(XmppInit::kOtherPeer) != string::npos) && 175 : (peer == xmps::OTHER)) { 176 4 : return true; 177 : } 178 1580155 : return false; 179 : } 180 : 181 1637208 : void XmppChannelMux::ProcessXmppMessage(const XmppStanza::XmppMessage *msg) { 182 1637208 : last_received_ = UTCTimestamp(); 183 1637208 : ReceiveCbMap::iterator iter = rxmap_.begin(); 184 4854357 : for (; iter != rxmap_.end(); ++iter) { 185 3217151 : if (MatchCallback(msg->to, iter->first)) { 186 1637000 : ReceiveCb cb = iter->second; 187 1636998 : cb(msg, GetPeerState()); 188 1637000 : } 189 : } 190 1637204 : } 191 : 192 25376 : void XmppChannelMux::HandleStateEvent(xmsm::XmState state) { 193 25376 : CHECK_CONCURRENCY("xmpp::StateMachine"); 194 25372 : xmps::PeerState st = xmps::NOT_READY; 195 25372 : if (state == xmsm::ESTABLISHED) { 196 12626 : st = xmps::READY; 197 12746 : } else if (state == xmsm::ACTIVE) { 198 365 : st = xmps::TIMEDOUT; 199 : } 200 : 201 25372 : if (connection_->IsClient()) { 202 12448 : XmppClient *client = static_cast<XmppClient *>(connection_->server()); 203 12448 : client->NotifyConnectionEvent(this, st); 204 : } else { 205 : // Event to create the peer on server 206 12924 : XmppServer *server = static_cast<XmppServer *>(connection_->server()); 207 12931 : server->NotifyConnectionEvent(this, st); 208 : } 209 25383 : } 210 : 211 501 : std::string XmppChannelMux::LastStateName() const { 212 501 : return connection_->LastStateName(); 213 : } 214 487 : std::string XmppChannelMux::LastStateChangeAt() const { 215 487 : return connection_->LastStateChangeAt(); 216 : } 217 487 : std::string XmppChannelMux::LastEvent() const { 218 487 : return connection_->LastEvent(); 219 : } 220 569 : uint32_t XmppChannelMux::rx_open() const { 221 569 : return connection_->rx_open(); 222 : } 223 569 : uint32_t XmppChannelMux::rx_close() const { 224 569 : return connection_->rx_close(); 225 : } 226 569 : uint32_t XmppChannelMux::rx_update() const { 227 569 : return connection_->rx_update(); 228 : } 229 569 : uint32_t XmppChannelMux::rx_keepalive() const { 230 569 : return connection_->rx_keepalive(); 231 : } 232 569 : uint32_t XmppChannelMux::tx_open() const { 233 569 : return connection_->tx_open(); 234 : } 235 569 : uint32_t XmppChannelMux::tx_close() const { 236 569 : return connection_->tx_close(); 237 : } 238 569 : uint32_t XmppChannelMux::tx_update() const { 239 569 : return connection_->tx_update(); 240 : } 241 569 : uint32_t XmppChannelMux::tx_keepalive() const { 242 569 : return connection_->tx_keepalive(); 243 : } 244 1461 : uint32_t XmppChannelMux::FlapCount() const { 245 1461 : return connection_->flap_count(); 246 : } 247 1461 : std::string XmppChannelMux::LastFlap() const { 248 1461 : return connection_->last_flap_at(); 249 : } 250 : 251 4 : void XmppChannelMux::RegisterRxMessageTraceCallback(RxMessageTraceCb cb) { 252 4 : rx_message_trace_cb_ = cb; 253 4 : } 254 4 : void XmppChannelMux::RegisterTxMessageTraceCallback(TxMessageTraceCb cb) { 255 4 : tx_message_trace_cb_ = cb; 256 4 : } 257 : 258 1657531 : bool XmppChannelMux::RxMessageTrace(const std::string &to_address, 259 : int port, 260 : int msg_size, 261 : const std::string &msg, 262 : const XmppStanza::XmppMessage *xmpp_msg) { 263 1657531 : if (rx_message_trace_cb_) { 264 0 : return rx_message_trace_cb_(to_address, port, msg_size, msg, xmpp_msg); 265 : } 266 1657531 : return false; 267 : } 268 : 269 1646267 : bool XmppChannelMux::TxMessageTrace(const std::string &to_address, 270 : int port, 271 : int msg_size, 272 : const std::string &msg, 273 : const XmppStanza::XmppMessage *xmpp_msg) { 274 1646267 : if (tx_message_trace_cb_) { 275 0 : return tx_message_trace_cb_(to_address, port, msg_size, msg, xmpp_msg); 276 : } 277 1646305 : return false; 278 : }