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

Generated by: LCOV version 1.14