LCOV - code coverage report
Current view: top level - xmpp - xmpp_client.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 126 167 75.4 %
Date: 2026-06-08 02:02:55 Functions: 24 29 82.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "xmpp/xmpp_client.h"
       6             : 
       7             : #include <boost/foreach.hpp>
       8             : #include <boost/tuple/tuple.hpp>
       9             : 
      10             : #include "base/task_annotations.h"
      11             : #include "xmpp/xmpp_factory.h"
      12             : #include "xmpp/xmpp_log.h"
      13             : #include "xmpp/xmpp_session.h"
      14             : 
      15             : #include "sandesh/common/vns_types.h"
      16             : #include "sandesh/common/vns_constants.h"
      17             : #include "sandesh/xmpp_client_server_sandesh_types.h"
      18             : 
      19             : using namespace std;
      20             : using namespace boost::asio;
      21             : using boost::tie;
      22             : 
      23             : class XmppClient::DeleteActor : public LifetimeActor {
      24             : public:
      25        5036 :     DeleteActor(XmppClient *client)
      26        5036 :         : LifetimeActor(client->lifetime_manager()), client_(client) { }
      27        5036 :     virtual bool MayDelete() const {
      28        5036 :         CHECK_CONCURRENCY("bgp::Config");
      29        5036 :         return (client_->GetSessionQueueSize() == 0);
      30             :     }
      31        5036 :     virtual void Shutdown() {
      32        5036 :         CHECK_CONCURRENCY("bgp::Config");
      33        5036 :     }
      34        5036 :     virtual void Destroy() {
      35        5036 :         CHECK_CONCURRENCY("bgp::Config");
      36        5036 :     }
      37             : 
      38             : private:
      39             :     XmppClient *client_;
      40             : };
      41             : 
      42          35 : XmppClient::XmppClient(EventManager *evm)
      43             :     : XmppConnectionManager(evm, ssl::context::sslv23_client, false, false),
      44          35 :       config_mgr_(new XmppConfigManager),
      45          35 :       lifetime_manager_(new LifetimeManager(
      46          70 :           TaskScheduler::GetInstance()->GetTaskId("bgp::Config"))),
      47          35 :       deleter_(new DeleteActor(this)),
      48          35 :       auth_enabled_(false),
      49          35 :       tcp_hold_time_(XmppChannelConfig::kTcpHoldTime) {
      50          35 : }
      51             : 
      52        5001 : XmppClient::XmppClient(EventManager *evm, const XmppChannelConfig *config)
      53             :     : XmppConnectionManager(
      54        5001 :           evm, ssl::context::sslv23_client, config->auth_enabled, true),
      55        5001 :       config_mgr_(new XmppConfigManager),
      56        5001 :       lifetime_manager_(new LifetimeManager(
      57       10002 :           TaskScheduler::GetInstance()->GetTaskId("bgp::Config"))),
      58        5001 :       deleter_(new DeleteActor(this)),
      59        5001 :       auth_enabled_(config->auth_enabled),
      60        5001 :       tcp_hold_time_(config->tcp_hold_time) {
      61             : 
      62        5001 :     if (config->auth_enabled) {
      63             : 
      64             :         // Get SSL context from base class and update
      65         901 :         boost::asio::ssl::context *ctx = context();
      66         901 :         boost::system::error_code ec;
      67             : 
      68             :         //set mode
      69         901 :         ctx->set_options(ssl::context::default_workarounds |
      70             :                          ssl::context::no_sslv3 | ssl::context::no_sslv2 | ssl::context::no_tlsv1, ec);
      71         901 :         if (ec.value() != 0) {
      72           0 :             LOG(ERROR, "Error : " << ec.message() << ", setting ssl options");
      73           0 :             exit(EINVAL);
      74             :         }
      75             : 
      76             :         // CA certificate, used to verify if the peer certificate
      77             :         // is signed by a trusted CA
      78         901 :         std::string ca_cert_filename = config->path_to_ca_cert;
      79         901 :         if (!ca_cert_filename.empty()) {
      80             : 
      81             :             // Verify peer has CA signed certificate
      82           0 :             ctx->set_verify_mode(boost::asio::ssl::verify_peer, ec);
      83           0 :             if (ec.value() != 0) {
      84           0 :                 LOG(ERROR, "Error : " << ec.message()
      85             :                     << ", while setting ssl verification mode");
      86           0 :                 exit(EINVAL);
      87             :             }
      88             : 
      89           0 :             ctx->load_verify_file(config->path_to_ca_cert, ec);
      90           0 :             if (ec.value() != 0) {
      91           0 :                 LOG(ERROR, "Error : " << ec.message()
      92             :                     << ", while using cacert file : "
      93             :                     << config->path_to_ca_cert);
      94           0 :                 exit(EINVAL);
      95             :             }
      96             :         }
      97             : 
      98             :         // server certificate
      99         901 :         ctx->use_certificate_chain_file(config->path_to_server_cert, ec);
     100         901 :         if (ec.value() != 0) {
     101           0 :             LOG(ERROR, "Error : " << ec.message() <<
     102             :                 ", while using server cert file : "
     103             :                 << config->path_to_server_cert);
     104           0 :             exit(EINVAL);
     105             :         }
     106             : 
     107             :         // server private key
     108         901 :         ctx->use_private_key_file(config->path_to_server_priv_key,
     109             :                                   boost::asio::ssl::context::pem, ec);
     110         901 :         if (ec.value() != 0) {
     111           0 :             LOG(ERROR, "Error : " << ec.message()
     112             :                 << ", while using privkey file : "
     113             :                 << config->path_to_server_priv_key);
     114           0 :             exit(EINVAL);
     115             :         }
     116         901 :     }
     117        5001 : }
     118             : 
     119       10034 : XmppClient::~XmppClient() {
     120       10034 : }
     121             : 
     122           0 : bool XmppClient::Initialize(short port) {
     123           0 :     TcpServer::Initialize(port);
     124           0 :     return true;
     125             : }
     126             : 
     127        5036 : LifetimeActor *XmppClient::deleter() {
     128        5036 :     return deleter_.get();
     129             : }
     130             : 
     131       10072 : LifetimeManager *XmppClient::lifetime_manager() {
     132       10072 :     return lifetime_manager_.get();
     133             : }
     134             : 
     135        7506 : TcpSession *XmppClient::CreateSession() {
     136             :     typedef boost::asio::detail::socket_option::boolean<
     137             :         SOL_SOCKET, SO_REUSEADDR> reuse_addr_t;
     138             : 
     139        7506 :     TcpSession *session = TcpServer::CreateSession();
     140        7506 :     Socket *socket = session->socket();
     141             : 
     142        7506 :     boost::system::error_code err;
     143        7506 :     socket->open(ip::tcp::v4(), err);
     144        7506 :     if (err) {
     145           0 :         XMPP_WARNING(ClientOpenFail, session->ToUVEKey(), XMPP_PEER_DIR_OUT,
     146             :                      err.message());
     147           0 :         DeleteSession(session);
     148           0 :         return NULL;
     149             :     }
     150             : 
     151        7506 :     socket->set_option(reuse_addr_t(true), err);
     152        7506 :     if (err) {
     153           0 :         XMPP_WARNING(SetSockOptFail, session->ToUVEKey(), XMPP_PEER_DIR_OUT,
     154             :                      err.message());
     155           0 :         return session;
     156             :     }
     157             : 
     158        7506 :     err = session->SetSocketOptions();
     159        7506 :     if (err) {
     160           0 :         DeleteSession(session);
     161           0 :         assert(0);
     162             :     }
     163             : 
     164        7506 :     return session;
     165             : }
     166             : 
     167        5036 : void XmppClient::Shutdown() {
     168        5036 :     XmppConnectionManager::Shutdown();
     169        5036 :     deleter_->Delete();
     170        5036 : }
     171             : 
     172             : void
     173        5000 : XmppClient::ProcessConfigUpdate(XmppConfigManager::DiffType delta,
     174             :     const XmppChannelConfig *current, const XmppChannelConfig *future) {
     175        5000 :     if (delta == XmppConfigManager::DF_ADD) {
     176        4991 :         XmppClientConnection *connection = CreateConnection(future);
     177        4991 :         connection->Initialize(); // trigger state-machine
     178             :     }
     179        5000 :     if (delta == XmppConfigManager::DF_DELETE) {
     180           9 :         ConnectionMap::iterator loc = connection_map_.find(current->endpoint);
     181           9 :         if (loc != connection_map_.end()) {
     182           9 :             loc->second->ManagedDelete();
     183             :         }
     184             :     }
     185        5000 : }
     186             : 
     187             : void
     188        5000 : XmppClient::ConfigUpdate(const XmppConfigData *cfg) {
     189        5000 :     config_mgr_->SetFuture(cfg);
     190        5000 :     config_mgr_->PeerConfigDiff(
     191             :         boost::bind(&XmppClient::ProcessConfigUpdate, this, _1, _2, _3));
     192        5000 :     config_mgr_->AcceptFuture();
     193        5000 : }
     194             : 
     195        4980 : void XmppClient::RegisterConnectionEvent(xmps::PeerId id,
     196             :     ConnectionEventCb cb) {
     197        4980 :     std::scoped_lock lock(connection_event_map_mutex_);
     198        4980 :     connection_event_map_.insert(make_pair(id, cb));
     199        4980 : }
     200             : 
     201           2 : void XmppClient::UnRegisterConnectionEvent(xmps::PeerId id) {
     202           2 :     std::scoped_lock lock(connection_event_map_mutex_);
     203           2 :     ConnectionEventCbMap::iterator it =  connection_event_map_.find(id);
     204           2 :     if (it != connection_event_map_.end())
     205           2 :         connection_event_map_.erase(it);
     206           2 : }
     207             : 
     208       12833 : void XmppClient::NotifyConnectionEvent(XmppChannelMux *mux,
     209             :     xmps::PeerState state) {
     210       12833 :     std::scoped_lock lock(connection_event_map_mutex_);
     211       12833 :     ConnectionEventCbMap::iterator iter = connection_event_map_.begin();
     212       25585 :     for (; iter != connection_event_map_.end(); ++iter) {
     213       12752 :         ConnectionEventCb cb = iter->second;
     214       12752 :         cb(mux, state);
     215       12752 :     }
     216       12833 : }
     217             : 
     218           0 : size_t XmppClient::ConnectionEventCount() const {
     219           0 :     return connection_event_map_.size();
     220             : }
     221             : 
     222        9956 : size_t XmppClient::ConnectionCount() const {
     223        9956 :     return connection_map_.size();
     224             : }
     225             : 
     226        7506 : SslSession *XmppClient::AllocSession(SslSocket *socket) {
     227        7506 :     SslSession *session = new XmppSession(this, socket);
     228        7506 :     return session;
     229             : }
     230             : 
     231      102614 : XmppClientConnection *XmppClient::FindConnection(const string &address) {
     232      102614 :     for (auto& value : connection_map_) {
     233      102614 :         if (value.second->ToString() == address)
     234      102614 :             return value.second;
     235             :     }
     236           0 :     return NULL;
     237             : }
     238             : 
     239        5009 : XmppClientConnection *XmppClient::CreateConnection(
     240             :     const XmppChannelConfig *config) {
     241             :     XmppClientConnection *connection =
     242        5009 :         XmppStaticObjectFactory::Create<XmppClientConnection>(this, config);
     243        5009 :     Endpoint endpoint = connection->endpoint();
     244        5009 :     ConnectionMap::iterator loc;
     245             :     bool result;
     246        5009 :     tie(loc, result) = connection_map_.insert(make_pair(endpoint, connection));
     247        5009 :     assert(result);
     248             : 
     249        5009 :     return connection;
     250             : }
     251             : 
     252          27 : void XmppClient::InsertConnection(XmppClientConnection *connection) {
     253          27 :     assert(!connection->IsDeleted());
     254          27 :     Endpoint endpoint = connection->endpoint();
     255          27 :     ConnectionMap::iterator loc;
     256             :     bool result;
     257          27 :     tie(loc, result) = connection_map_.insert(make_pair(endpoint, connection));
     258          27 :     assert(result);
     259          27 : }
     260             : 
     261        5036 : void XmppClient::RemoveConnection(XmppClientConnection *connection) {
     262        5036 :     assert(connection->IsDeleted());
     263        5036 :     Endpoint endpoint = connection->endpoint();
     264        5036 :     ConnectionMap::iterator loc = connection_map_.find(endpoint);
     265        5036 :     assert(loc != connection_map_.end() && loc->second == connection);
     266        5036 :     connection_map_.erase(loc);
     267        5036 : }
     268             : 
     269       93715 : XmppChannel *XmppClient::FindChannel(const string &address) {
     270       93715 :     XmppClientConnection *connection = FindConnection(address);
     271       93715 :     return (connection ? connection->ChannelMux() : NULL);
     272             : }
     273             : 
     274           0 : int XmppClient::SetDscpValue(uint8_t value, const char *conn_id) {
     275           0 :     XmppClientConnection *connection = FindConnection(conn_id);
     276           0 :     if (connection) {
     277           0 :         return connection->SetDscpValue(value);
     278             :     }
     279           0 :     return 0;
     280             : }
     281             : 
     282           0 : void XmppClient::UpdateTimeOut(uint8_t time_out, const char *conn_id) {
     283           0 :     XmppClientConnection *connection = FindConnection(conn_id);
     284           0 :     if (connection) {
     285           0 :         return connection->UpdateKeepAliveTimer(time_out);
     286             :     }
     287             : }
     288             : 
     289           0 : uint32_t XmppClient::XmppTimeOut(const char *conn_id) {
     290           0 :     XmppClientConnection *connection = FindConnection(conn_id);
     291           0 :     if (connection) {
     292           0 :         return connection->state_machine()->hold_time();
     293             :     }
     294           0 :     return 0;
     295             : }
     296             : 

Generated by: LCOV version 1.14