LCOV - code coverage report
Current view: top level - dns/agent - agent_xmpp_channel.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 208 0.0 %
Date: 2026-06-04 02:06:09 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "base/logging.h"
       6             : #include "base/task_trigger.h"
       7             : #include <pugixml/pugixml.hpp>
       8             : #include "agent/agent_xmpp_channel.h"
       9             : 
      10             : #include "xml/xml_pugi.h"
      11             : #include "xmpp/xmpp_connection.h"
      12             : #include "xmpp/xmpp_server.h"
      13             : #include "cmn/dns.h"
      14             : #include "mgr/dns_mgr.h"
      15             : #include "mgr/dns_oper.h"
      16             : #include "bind/bind_util.h"
      17             : #include "bind/bind_resolver.h"
      18             : #include "bind/named_config.h"
      19             : #include "bind/xmpp_dns_agent.h"
      20             : #include "sandesh/sandesh_trace.h"
      21             : #include "cmn/dns_types.h"
      22             : 
      23           0 : DnsAgentXmppChannel:: DnsAgentXmppChannel(XmppChannel *channel,
      24           0 :                                           DnsAgentXmppChannelManager *mgr)
      25           0 :                                         : channel_(channel), mgr_(mgr) {
      26           0 :     channel_->RegisterReceive(xmps::DNS,
      27             :                      boost::bind(&DnsAgentXmppChannel::ReceiveReq, this, _1));
      28             : 
      29           0 : }
      30             : 
      31           0 : DnsAgentXmppChannel::~DnsAgentXmppChannel() {
      32           0 :     channel_->UnRegisterWriteReady(xmps::DNS);
      33           0 :     channel_->UnRegisterReceive(xmps::DNS);
      34           0 : }
      35             : 
      36           0 : void DnsAgentXmppChannel::Close() {
      37           0 :     UpdateDnsRecords(BindUtil::DELETE_UPDATE);
      38           0 :     if (mgr_)
      39           0 :         mgr_->RemoveChannel(channel_);
      40           0 : }
      41             : 
      42           0 : void DnsAgentXmppChannel::ReceiveReq(const XmppStanza::XmppMessage *msg) {
      43           0 :     if (msg && msg->type == XmppStanza::IQ_STANZA) {
      44           0 :         XmlBase *impl = msg->dom.get();
      45           0 :         XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl);
      46           0 :         pugi::xml_node node = pugi->FindNode("dns");
      47             :         DnsAgentXmpp::XmppType type;
      48           0 :         std::string source_name = msg->from;
      49             :         uint32_t xid;
      50             :         uint16_t code;
      51           0 :         std::unique_ptr<DnsUpdateData> rcv_data(new DnsUpdateData());
      52           0 :         DnsUpdateData *data = rcv_data.get();
      53           0 :         if (DnsAgentXmpp::DnsAgentXmppDecode(node, type, xid, code, data, source_name)) {
      54           0 :             if (type == DnsAgentXmpp::Update) {
      55           0 :                 HandleAgentUpdate(std::move(rcv_data));
      56             :             }
      57             :         }
      58           0 :     }
      59           0 : }
      60             : 
      61           0 : void DnsAgentXmppChannel::HandleAgentUpdate(
      62             :     std::unique_ptr<DnsUpdateData> rcv_data) {
      63           0 :     DnsUpdateData *data = rcv_data.get();
      64           0 :     if (data->virtual_dns.empty() || data->zone.empty()) {
      65             :         // if key is not present, ignore the update
      66           0 :         return;
      67             :     }
      68           0 :     DataSet::iterator it = update_data_.find(data);
      69           0 :     if (it != update_data_.end()) {
      70           0 :         DnsUpdateData *xmpp_data = *it;
      71           0 :         for (DnsItems::iterator iter = data->items.begin();
      72           0 :              iter != data->items.end();) {
      73             :             bool change;
      74           0 :             BindUtil::Operation op = BindUtil::ADD_UPDATE;
      75           0 :             if ((*iter).IsDelete()) {
      76           0 :                 change = xmpp_data->DelItem(*iter);
      77           0 :                 op = BindUtil::DELETE_UPDATE;
      78             :             } else {
      79           0 :                 change = xmpp_data->AddItem(*iter, true);
      80           0 :                 if (!change) {
      81           0 :                     op = BindUtil::CHANGE_UPDATE;
      82           0 :                     change = true;
      83             :                 }
      84             :             }
      85             : 
      86           0 :             if (!change) {
      87           0 :                 data->items.erase(iter++);
      88             :             } else {
      89             :                 boost::shared_ptr<DnsAgentXmppChannelManager::RecordRequest>
      90             :                     req(new DnsAgentXmppChannelManager::RecordRequest(
      91           0 :                             op, GetDnsRecordName(data->virtual_dns, *iter),
      92           0 :                             data->virtual_dns, *iter));
      93           0 :                 mgr_->EnqueueRecord(req);
      94           0 :                 ++iter;
      95           0 :             }
      96             :         }
      97           0 :         if (!xmpp_data->items.size()) {
      98           0 :             update_data_.erase(xmpp_data);
      99           0 :             delete xmpp_data;
     100             :         }
     101             :     } else {
     102           0 :         for (DnsItems::iterator iter = data->items.begin();
     103           0 :              iter != data->items.end();) {
     104           0 :             if ((*iter).IsDelete())
     105           0 :                 data->items.erase(iter++);
     106             :             else {
     107             :                 boost::shared_ptr<DnsAgentXmppChannelManager::RecordRequest>
     108             :                     req(new DnsAgentXmppChannelManager::RecordRequest(
     109             :                             BindUtil::ADD_UPDATE,
     110           0 :                             GetDnsRecordName(data->virtual_dns, *iter),
     111           0 :                             data->virtual_dns, *iter));
     112           0 :                 mgr_->EnqueueRecord(req);
     113           0 :                 ++iter;
     114           0 :             }
     115             :         }
     116           0 :         update_data_.insert(data);
     117           0 :         rcv_data.release();
     118             :     }
     119             : }
     120             : 
     121           0 : void DnsAgentXmppChannel::UpdateDnsRecords(BindUtil::Operation op) {
     122           0 :     for (DataSet::iterator it = update_data_.begin();
     123           0 :          it != update_data_.end(); ++it) {
     124           0 :         for (DnsItems::const_iterator item = (*it)->items.begin();
     125           0 :              item != (*it)->items.end(); ++item) {
     126             :             boost::shared_ptr<DnsAgentXmppChannelManager::RecordRequest>
     127             :                 req(new DnsAgentXmppChannelManager::RecordRequest(
     128           0 :                         op, GetDnsRecordName((*it)->virtual_dns, *item),
     129           0 :                         (*it)->virtual_dns, *item));
     130           0 :             mgr_->EnqueueRecord(req);
     131           0 :         }
     132             :     }
     133           0 : }
     134             : 
     135           0 : std::string DnsAgentXmppChannel::GetDnsRecordName(std::string &vdns_name,
     136             :                                                   const DnsItem &item) {
     137           0 :     std::stringstream str;
     138           0 :     str << vdns_name << ":" << item.type << ":" << item.name << ":" << item.data;
     139           0 :     return str.str();
     140           0 : }
     141             : 
     142           0 : void DnsAgentXmppChannel::GetAgentDnsData(AgentDnsData &data) {
     143           0 :     data.set_agent(channel_->connection()->endpoint().address().to_string());
     144           0 :     std::vector<AgentDnsDataItem> items;
     145           0 :     for (DataSet::iterator it = update_data_.begin();
     146           0 :          it != update_data_.end(); ++it) {
     147           0 :         AgentDnsDataItem item;
     148           0 :         item.set_virtual_dns((*it)->virtual_dns);
     149           0 :         item.set_zone((*it)->zone);
     150           0 :         std::vector<VirtualDnsRecordTraceData> records;
     151           0 :         for (DnsItems::iterator iter = (*it)->items.begin();
     152           0 :              iter != (*it)->items.end(); ++iter) {
     153           0 :             VirtualDnsRecordTraceData record;
     154           0 :             record.rec_name = (*iter).name;
     155           0 :             record.rec_type = BindUtil::DnsType((*iter).type);
     156           0 :             record.rec_class = "IN";
     157           0 :             record.rec_data = (*iter).data;
     158           0 :             record.rec_ttl = (*iter).ttl;
     159           0 :             record.source = "Agent";
     160           0 :             record.installed = "yes";
     161           0 :             record.rec_source_name = (*iter).source_name;
     162           0 :             records.push_back(record);
     163           0 :         }
     164           0 :         item.set_records(records);
     165           0 :         items.push_back(item);
     166           0 :     }
     167           0 :     data.set_agent_data(items);
     168           0 : }
     169             : 
     170           0 : DnsAgentXmppChannelManager::DnsAgentXmppChannelManager(
     171           0 :                             XmppServer *server)
     172           0 :     : server_(server),
     173           0 :       work_queue_(TaskScheduler::GetInstance()->GetTaskId("dns::Config"), 0,
     174             :                   boost::bind(&DnsAgentXmppChannelManager::ProcessRecord,
     175           0 :                               this, _1)) {
     176           0 :     if (server_) {
     177           0 :         server_->RegisterConnectionEvent(xmps::DNS,
     178             :         boost::bind(&DnsAgentXmppChannelManager::HandleXmppChannelEvent,
     179             :                     this, _1, _2));
     180             :     }
     181           0 : }
     182             : 
     183           0 : DnsAgentXmppChannelManager::~DnsAgentXmppChannelManager() {
     184           0 :     if (server_)
     185           0 :         server_->UnRegisterConnectionEvent(xmps::DNS);
     186           0 :     channel_map_.clear();
     187           0 :     work_queue_.Shutdown();
     188           0 : }
     189             : 
     190           0 : bool DnsAgentXmppChannelManager::ProcessRecord(
     191             :                                  boost::shared_ptr<RecordRequest> req) {
     192           0 :     Dns::GetDnsManager()->ProcessAgentUpdate(req->op, req->record_name,
     193           0 :                                              req->vdns_name, req->item);
     194           0 :     return true;
     195             : }
     196             : 
     197           0 : void DnsAgentXmppChannelManager::EnqueueRecord(
     198             :                                  boost::shared_ptr<RecordRequest> req) {
     199           0 :     work_queue_.Enqueue(req);
     200           0 : }
     201             : 
     202           0 : void DnsAgentXmppChannelManager::RemoveChannel(XmppChannel *ch) {
     203           0 :     channel_map_.erase(ch);
     204           0 : }
     205             : 
     206             : DnsAgentXmppChannel *
     207           0 : DnsAgentXmppChannelManager::DnsAgentXmppChannelManager::FindChannel(
     208             :     const XmppChannel *ch) {
     209           0 :     std::scoped_lock lock(mutex_);
     210           0 :     ChannelMap::iterator it = channel_map_.find(ch);
     211           0 :     if (it == channel_map_.end())
     212           0 :         return NULL;
     213           0 :     return it->second;
     214           0 : }
     215             : 
     216             : void
     217           0 : DnsAgentXmppChannelManager::HandleXmppChannelEvent(XmppChannel *channel,
     218             :                                                    xmps::PeerState state) {
     219           0 :     std::scoped_lock lock(mutex_);
     220           0 :     ChannelMap::iterator it = channel_map_.find(channel);
     221             : 
     222           0 :     if (state == xmps::READY) {
     223           0 :         if (it == channel_map_.end()) {
     224             :             DnsAgentXmppChannel *agent_xmpp_channel =
     225           0 :                             new DnsAgentXmppChannel(channel, this);
     226           0 :             channel_map_.insert(std::make_pair(channel, agent_xmpp_channel));
     227             :             ConfigClientManager *config_manager =
     228           0 :                 Dns::GetDnsManager()->get_config_manager();
     229           0 :             if (config_manager && !config_manager->GetEndOfRibComputed()) {
     230           0 :                 DNS_XMPP_TRACE(DnsXmppTrace, "Peer:" + channel->PeerAddress() +
     231             :                                " Close due to EndofRib not computed");
     232           0 :                 channel->Close();
     233             :             }
     234             :         }
     235           0 :     } else if (state == xmps::NOT_READY) {
     236           0 :         if (it != channel_map_.end()) {
     237           0 :             DnsAgentXmppChannel *agent_xmpp_channel = (*it).second;
     238           0 :             agent_xmpp_channel->Close();
     239           0 :             delete agent_xmpp_channel;
     240             :         } else {
     241           0 :             DNS_XMPP_TRACE(DnsXmppTrace,
     242             :                            "Peer not found on channel not ready event");
     243             :         }
     244             :     }
     245           0 : }
     246             : 
     247           0 : uint8_t DnsAgentXmppChannelManager::ChannelToDscp(const XmppChannel *xc) const {
     248           0 :     const XmppConnection *conn = xc->connection();
     249           0 :     if (conn) {
     250           0 :         const XmppSession *sess = conn->session();
     251           0 :         if (sess) {
     252           0 :             return sess->GetDscpValue();
     253             :         }
     254             :     }
     255           0 :     return 0;
     256             : }
     257             : 
     258           0 : void DnsAgentXmppChannelManager::GetAgentData(std::vector<AgentData> &list) {
     259           0 :     std::scoped_lock lock(mutex_);
     260           0 :     for (ChannelMap::iterator iter = channel_map_.begin();
     261           0 :          iter != channel_map_.end(); ++iter) {
     262           0 :         const XmppChannel *channel = iter->first;
     263           0 :         AgentData agent_data;
     264           0 :         agent_data.set_peer(channel->ToString());
     265           0 :         agent_data.set_peer_address(
     266           0 :             channel->connection()->endpoint().address().to_string());
     267           0 :         agent_data.set_local_address(
     268           0 :             channel->connection()->local_endpoint().address().to_string());
     269           0 :         agent_data.set_state(channel->StateName());
     270           0 :         agent_data.set_last_event(channel->LastEvent());
     271           0 :         agent_data.set_last_state(channel->LastStateName());
     272           0 :         agent_data.set_last_state_at(channel->LastStateChangeAt());
     273           0 :         agent_data.set_dscp(ChannelToDscp(channel));
     274           0 :         list.push_back(agent_data);
     275           0 :     }
     276           0 : }
     277             : 
     278           0 : void DnsAgentXmppChannelManager::GetAgentDnsData(std::vector<AgentDnsData> &dt) {
     279           0 :     std::scoped_lock lock(mutex_);
     280           0 :     for (ChannelMap::iterator iter = channel_map_.begin();
     281           0 :          iter != channel_map_.end(); ++iter) {
     282           0 :         DnsAgentXmppChannel *ch = iter->second;
     283           0 :         AgentDnsData data;
     284           0 :         ch->GetAgentDnsData(data);
     285           0 :         dt.push_back(data);
     286           0 :     }
     287           0 : }
     288             : 
     289           0 : void ShowAgentList::HandleRequest() const {
     290           0 :     DnsAgentListResponse *resp = new DnsAgentListResponse();
     291           0 :     resp->set_context(context());
     292             : 
     293           0 :     std::vector<AgentData> agent_list_sandesh;
     294           0 :     Dns::GetAgentXmppChannelManager()->GetAgentData(agent_list_sandesh);
     295             : 
     296           0 :     resp->set_agent(agent_list_sandesh);
     297           0 :     resp->Response();
     298           0 : }
     299             : 
     300           0 : void ShowAgentXmppDnsData::HandleRequest() const {
     301           0 :     AgentXmppDnsDataResponse *resp = new AgentXmppDnsDataResponse();
     302           0 :     resp->set_context(context());
     303             : 
     304           0 :     std::vector<AgentDnsData> agent_data;
     305           0 :     Dns::GetAgentXmppChannelManager()->GetAgentDnsData(agent_data);
     306             : 
     307           0 :     resp->set_data(agent_data);
     308           0 :     resp->Response();
     309           0 : }

Generated by: LCOV version 1.14