OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
agent_xmpp_channel.cc
Go to the documentation of this file.
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>
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 
25  : channel_(channel), mgr_(mgr) {
27  boost::bind(&DnsAgentXmppChannel::ReceiveReq, this, _1));
28 
29 }
30 
34 }
35 
38  if (mgr_)
40 }
41 
43  if (msg && msg->type == XmppStanza::IQ_STANZA) {
44  XmlBase *impl = msg->dom.get();
45  XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl);
46  pugi::xml_node node = pugi->FindNode("dns");
48  std::string source_name = msg->from;
49  uint32_t xid;
50  uint16_t code;
51  std::unique_ptr<DnsUpdateData> rcv_data(new DnsUpdateData());
52  DnsUpdateData *data = rcv_data.get();
53  if (DnsAgentXmpp::DnsAgentXmppDecode(node, type, xid, code, data, source_name)) {
54  if (type == DnsAgentXmpp::Update) {
55  HandleAgentUpdate(std::move(rcv_data));
56  }
57  }
58  }
59 }
60 
62  std::unique_ptr<DnsUpdateData> rcv_data) {
63  DnsUpdateData *data = rcv_data.get();
64  if (data->virtual_dns.empty() || data->zone.empty()) {
65  // if key is not present, ignore the update
66  return;
67  }
68  DataSet::iterator it = update_data_.find(data);
69  if (it != update_data_.end()) {
70  DnsUpdateData *xmpp_data = *it;
71  for (DnsItems::iterator iter = data->items.begin();
72  iter != data->items.end();) {
73  bool change;
75  if ((*iter).IsDelete()) {
76  change = xmpp_data->DelItem(*iter);
78  } else {
79  change = xmpp_data->AddItem(*iter, true);
80  if (!change) {
82  change = true;
83  }
84  }
85 
86  if (!change) {
87  data->items.erase(iter++);
88  } else {
89  boost::shared_ptr<DnsAgentXmppChannelManager::RecordRequest>
91  op, GetDnsRecordName(data->virtual_dns, *iter),
92  data->virtual_dns, *iter));
93  mgr_->EnqueueRecord(req);
94  ++iter;
95  }
96  }
97  if (!xmpp_data->items.size()) {
98  update_data_.erase(xmpp_data);
99  delete xmpp_data;
100  }
101  } else {
102  for (DnsItems::iterator iter = data->items.begin();
103  iter != data->items.end();) {
104  if ((*iter).IsDelete())
105  data->items.erase(iter++);
106  else {
107  boost::shared_ptr<DnsAgentXmppChannelManager::RecordRequest>
110  GetDnsRecordName(data->virtual_dns, *iter),
111  data->virtual_dns, *iter));
112  mgr_->EnqueueRecord(req);
113  ++iter;
114  }
115  }
116  update_data_.insert(data);
117  rcv_data.release();
118  }
119 }
120 
122  for (DataSet::iterator it = update_data_.begin();
123  it != update_data_.end(); ++it) {
124  for (DnsItems::const_iterator item = (*it)->items.begin();
125  item != (*it)->items.end(); ++item) {
126  boost::shared_ptr<DnsAgentXmppChannelManager::RecordRequest>
128  op, GetDnsRecordName((*it)->virtual_dns, *item),
129  (*it)->virtual_dns, *item));
130  mgr_->EnqueueRecord(req);
131  }
132  }
133 }
134 
135 std::string DnsAgentXmppChannel::GetDnsRecordName(std::string &vdns_name,
136  const DnsItem &item) {
137  std::stringstream str;
138  str << vdns_name << ":" << item.type << ":" << item.name << ":" << item.data;
139  return str.str();
140 }
141 
142 void DnsAgentXmppChannel::GetAgentDnsData(AgentDnsData &data) {
143  data.set_agent(channel_->connection()->endpoint().address().to_string());
144  std::vector<AgentDnsDataItem> items;
145  for (DataSet::iterator it = update_data_.begin();
146  it != update_data_.end(); ++it) {
147  AgentDnsDataItem item;
148  item.set_virtual_dns((*it)->virtual_dns);
149  item.set_zone((*it)->zone);
150  std::vector<VirtualDnsRecordTraceData> records;
151  for (DnsItems::iterator iter = (*it)->items.begin();
152  iter != (*it)->items.end(); ++iter) {
153  VirtualDnsRecordTraceData record;
154  record.rec_name = (*iter).name;
155  record.rec_type = BindUtil::DnsType((*iter).type);
156  record.rec_class = "IN";
157  record.rec_data = (*iter).data;
158  record.rec_ttl = (*iter).ttl;
159  record.source = "Agent";
160  record.installed = "yes";
161  record.rec_source_name = (*iter).source_name;
162  records.push_back(record);
163  }
164  item.set_records(records);
165  items.push_back(item);
166  }
167  data.set_agent_data(items);
168 }
169 
171  XmppServer *server)
172  : server_(server),
173  work_queue_(TaskScheduler::GetInstance()->GetTaskId("dns::Config"), 0,
174  boost::bind(&DnsAgentXmppChannelManager::ProcessRecord,
175  this, _1)) {
176  if (server_) {
179  this, _1, _2));
180  }
181 }
182 
184  if (server_)
186  channel_map_.clear();
188 }
189 
191  boost::shared_ptr<RecordRequest> req) {
192  Dns::GetDnsManager()->ProcessAgentUpdate(req->op, req->record_name,
193  req->vdns_name, req->item);
194  return true;
195 }
196 
198  boost::shared_ptr<RecordRequest> req) {
199  work_queue_.Enqueue(req);
200 }
201 
203  channel_map_.erase(ch);
204 }
205 
207 DnsAgentXmppChannelManager::DnsAgentXmppChannelManager::FindChannel(
208  const XmppChannel *ch) {
209  tbb::mutex::scoped_lock lock(mutex_);
210  ChannelMap::iterator it = channel_map_.find(ch);
211  if (it == channel_map_.end())
212  return NULL;
213  return it->second;
214 }
215 
216 void
218  xmps::PeerState state) {
219  tbb::mutex::scoped_lock lock(mutex_);
220  ChannelMap::iterator it = channel_map_.find(channel);
221 
222  if (state == xmps::READY) {
223  if (it == channel_map_.end()) {
224  DnsAgentXmppChannel *agent_xmpp_channel =
225  new DnsAgentXmppChannel(channel, this);
226  channel_map_.insert(std::make_pair(channel, agent_xmpp_channel));
227  ConfigClientManager *config_manager =
229  if (config_manager && !config_manager->GetEndOfRibComputed()) {
230  DNS_XMPP_TRACE(DnsXmppTrace, "Peer:" + channel->PeerAddress() +
231  " Close due to EndofRib not computed");
232  channel->Close();
233  }
234  }
235  } else if (state == xmps::NOT_READY) {
236  if (it != channel_map_.end()) {
237  DnsAgentXmppChannel *agent_xmpp_channel = (*it).second;
238  agent_xmpp_channel->Close();
239  delete agent_xmpp_channel;
240  } else {
241  DNS_XMPP_TRACE(DnsXmppTrace,
242  "Peer not found on channel not ready event");
243  }
244  }
245 }
246 
248  const XmppConnection *conn = xc->connection();
249  if (conn) {
250  const XmppSession *sess = conn->session();
251  if (sess) {
252  return sess->GetDscpValue();
253  }
254  }
255  return 0;
256 }
257 
258 void DnsAgentXmppChannelManager::GetAgentData(std::vector<AgentData> &list) {
259  tbb::mutex::scoped_lock lock(mutex_);
260  for (ChannelMap::iterator iter = channel_map_.begin();
261  iter != channel_map_.end(); ++iter) {
262  const XmppChannel *channel = iter->first;
263  AgentData agent_data;
264  agent_data.set_peer(channel->ToString());
265  agent_data.set_peer_address(
266  channel->connection()->endpoint().address().to_string());
267  agent_data.set_local_address(
268  channel->connection()->local_endpoint().address().to_string());
269  agent_data.set_state(channel->StateName());
270  agent_data.set_last_event(channel->LastEvent());
271  agent_data.set_last_state(channel->LastStateName());
272  agent_data.set_last_state_at(channel->LastStateChangeAt());
273  agent_data.set_dscp(ChannelToDscp(channel));
274  list.push_back(agent_data);
275  }
276 }
277 
278 void DnsAgentXmppChannelManager::GetAgentDnsData(std::vector<AgentDnsData> &dt) {
279  tbb::mutex::scoped_lock lock(mutex_);
280  for (ChannelMap::iterator iter = channel_map_.begin();
281  iter != channel_map_.end(); ++iter) {
282  DnsAgentXmppChannel *ch = iter->second;
283  AgentDnsData data;
284  ch->GetAgentDnsData(data);
285  dt.push_back(data);
286  }
287 }
288 
289 void ShowAgentList::HandleRequest() const {
290  DnsAgentListResponse *resp = new DnsAgentListResponse();
291  resp->set_context(context());
292 
293  std::vector<AgentData> agent_list_sandesh;
294  Dns::GetAgentXmppChannelManager()->GetAgentData(agent_list_sandesh);
295 
296  resp->set_agent(agent_list_sandesh);
297  resp->Response();
298 }
299 
300 void ShowAgentXmppDnsData::HandleRequest() const {
301  AgentXmppDnsDataResponse *resp = new AgentXmppDnsDataResponse();
302  resp->set_context(context());
303 
304  std::vector<AgentDnsData> agent_data;
306 
307  resp->set_data(agent_data);
308  resp->Response();
309 }
virtual const XmppConnection * connection() const =0
pugi::xml_node FindNode(const std::string &name)
Definition: xml_pugi.cc:51
void UnRegisterConnectionEvent(xmps::PeerId)
Definition: xmpp_server.cc:457
void UpdateDnsRecords(BindUtil::Operation op)
XmppMessageType type
Definition: xmpp_proto.h:57
std::string zone
Definition: bind_util.h:207
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
std::string GetDnsRecordName(std::string &vdns_name, const DnsItem &item)
void Shutdown(bool delete_entries=true)
Definition: queue_task.h:152
virtual void RegisterReceive(xmps::PeerId, ReceiveCb)=0
virtual boost::asio::ip::tcp::endpoint endpoint() const
uint8_t ChannelToDscp(const XmppChannel *xc) const
void HandleAgentUpdate(std::unique_ptr< DnsUpdateData > rcv_data)
void EnqueueRecord(boost::shared_ptr< RecordRequest > req)
ConfigClientManager * get_config_manager()
Definition: dns_mgr.h:92
virtual void Close()=0
std::string name
Definition: bind_util.h:158
bool ProcessRecord(boost::shared_ptr< RecordRequest > req)
void GetAgentData(std::vector< AgentData > &list)
void ProcessAgentUpdate(BindUtil::Operation event, const std::string &name, const std::string &vdns_name, const DnsItem &item)
Definition: dns_mgr.cc:128
std::string virtual_dns
Definition: bind_util.h:206
DnsAgentXmppChannel(XmppChannel *channel, DnsAgentXmppChannelManager *mgr)
virtual std::string LastStateChangeAt() const =0
std::unique_ptr< XmlBase > dom
Definition: xmpp_proto.h:62
uint8_t type
Definition: load_balance.h:109
virtual std::string StateName() const =0
static DnsManager * GetDnsManager()
Definition: dns.h:34
virtual std::string LastEvent() const =0
void RemoveChannel(XmppChannel *ch)
RecordRequestWorkQueue work_queue_
std::string data
Definition: bind_util.h:160
virtual const std::string & ToString() const =0
virtual void UnRegisterReceive(xmps::PeerId)=0
virtual std::string LastStateName() const =0
bool AddItem(DnsItem &item, bool replace=false) const
Definition: bind_util.h:224
void GetAgentDnsData(AgentDnsData &data)
void ReceiveReq(const XmppStanza::XmppMessage *msg)
DnsAgentXmppChannelManager * mgr_
#define DNS_XMPP_TRACE(obj, arg)
Definition: xmpp_dns_agent.h:9
bool DelItem(DnsItem &item) const
Definition: bind_util.h:236
static bool DnsAgentXmppDecode(const pugi::xml_node dns, XmppType &type, uint32_t &xid, uint16_t &resp_code, DnsUpdateData *data, std::string source_name="")
DnsAgentXmppChannelManager(XmppServer *server)
void HandleXmppChannelEvent(XmppChannel *channel, xmps::PeerState state)
void GetAgentDnsData(std::vector< AgentDnsData > &dt)
virtual void UnRegisterWriteReady(xmps::PeerId id)=0
static uint16_t DnsType(const std::string &tp)
Definition: bind_util.cc:125
DnsItems items
Definition: bind_util.h:208
const XmppSession * session() const
virtual boost::asio::ip::tcp::endpoint local_endpoint() const
bool Enqueue(QueueEntryT entry)
Definition: queue_task.h:248
virtual std::string PeerAddress() const =0
void RegisterConnectionEvent(xmps::PeerId, ConnectionEventCb)
Definition: xmpp_server.cc:452
uint8_t GetDscpValue() const
Definition: tcp_session.cc:573
static DnsAgentXmppChannelManager * GetAgentXmppChannelManager()
Definition: dns.h:46
uint16_t type
Definition: bind_util.h:150