NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
remote-registrator.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "remote-registrator.hpp"
27 #include "core/logger.hpp"
28 #include "core/scheduler.hpp"
29 #include <ndn-cxx/security/signing-helpers.hpp>
30 
31 namespace nfd {
32 namespace rib {
33 
34 NFD_LOG_INIT("RemoteRegistrator");
35 
38 
39 const Name RemoteRegistrator::LOCAL_REGISTRATION_PREFIX = "/localhost";
40 const Name RemoteRegistrator::REMOTE_HUB_PREFIX = "/localhop/nfd";
41 const name::Component RemoteRegistrator::IGNORE_COMMPONENT("rib");
42 
44  ndn::KeyChain& keyChain,
45  Rib& rib)
46  : m_nfdController(controller)
47  , m_keyChain(keyChain)
48  , m_rib(rib)
49  , m_refreshInterval(time::seconds(25))
50  , m_hasConnectedHub(false)
51  , m_nRetries(0)
52 {
53 }
54 
56 {
57  // cancel all periodically refresh events.
58  for (auto&& entry : m_regEntries)
59  {
60  scheduler::cancel(entry.second);
61  }
62 }
63 
64 void
66 {
67  size_t cost = 15, timeout = 10000;
68  size_t retry = 0;
69  size_t interval = 0;
70  const size_t intervalDef = 25, intervalMax = 600;
71 
72  NFD_LOG_INFO("Load remote_register section in rib section");
73  for (auto&& i : configSection)
74  {
75  if (i.first == "cost")
76  {
77  cost = i.second.get_value<size_t>();
78  }
79  else if (i.first == "timeout")
80  {
81  timeout = i.second.get_value<size_t>();
82  }
83  else if (i.first == "retry")
84  {
85  retry = i.second.get_value<size_t>();
86  }
87  else if (i.first == "refresh_interval")
88  {
89  interval = i.second.get_value<size_t>();
90  }
91  else
92  {
93  BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" + i.first +
94  "\" in \"remote-registrator\" section"));
95  }
96  }
97 
98  m_controlParameters
99  .setCost(cost)
100  .setOrigin(ndn::nfd::ROUTE_ORIGIN_CLIENT)// set origin to client.
101  .setFaceId(0);// the remote hub will take the input face as the faceId.
102 
103  m_commandOptions
104  .setPrefix(REMOTE_HUB_PREFIX)
105  .setTimeout(time::milliseconds(timeout));
106 
107  m_nRetries = retry;
108 
109  if (interval == 0)
110  {
111  interval = intervalDef;
112  }
113 
114  interval = std::min(interval, intervalMax);
115 
116  m_refreshInterval = time::seconds(interval);
117 }
118 
119 void
121 {
122  // do remote registration after an entry is inserted into the RIB.
123  m_afterInsertConnection =
124  m_rib.afterInsertEntry.connect([this] (const Name& prefix) {
125  registerPrefix(prefix);
126  });
127 
128  // do remote unregistration after an entry is erased from the RIB.
129  m_afterEraseConnection =
130  m_rib.afterEraseEntry.connect([this] (const Name& prefix) {
131  unregisterPrefix(prefix);
132  });
133 }
134 
135 void
137 {
138  m_afterInsertConnection.disconnect();
139  m_afterEraseConnection.disconnect();
140 }
141 
142 void
144 {
145  if (LOCAL_REGISTRATION_PREFIX.isPrefixOf(prefix))
146  {
147  NFD_LOG_INFO("local registration only for " << prefix);
148  return;
149  }
150 
151  bool isHubPrefix = prefix == REMOTE_HUB_PREFIX;
152 
153  if (isHubPrefix)
154  {
155  NFD_LOG_INFO("this is a prefix registered by some hub: " << prefix);
156 
157  m_hasConnectedHub = true;
158 
159  redoRegistration();
160  return;
161  }
162 
163  if (!m_hasConnectedHub)
164  {
165  NFD_LOG_INFO("no hub connected when registering " << prefix);
166  return;
167  }
168 
169  std::pair<Name, size_t> identity = findIdentityForRegistration(prefix);
170 
171  if (0 == identity.second)
172  {
173  NFD_LOG_INFO("no proper identity found for registering " << prefix);
174  return;
175  }
176 
177  Name prefixForRegistration;
178  if (identity.first.size() == identity.second)
179  {
180  prefixForRegistration = identity.first;
181  }
182  else
183  {
184  prefixForRegistration = identity.first.getPrefix(-1);
185  }
186 
187  if (m_regEntries.find(prefixForRegistration) != m_regEntries.end())
188  {
189  NFD_LOG_INFO("registration already in process for " << prefix);
190  return;
191  }
192 
193  // make copies of m_controlParameters and m_commandOptions to
194  // avoid unreasonable overwriting during concurrent registration
195  // and unregistration.
196  ControlParameters parameters = m_controlParameters;
197  CommandOptions options = m_commandOptions;
198 
199  startRegistration(parameters.setName(prefixForRegistration),
200  options.setSigningInfo(signingByIdentity(identity.first)),
201  m_nRetries);
202 }
203 
204 void
206 {
207  if (prefix == REMOTE_HUB_PREFIX)
208  {
209  NFD_LOG_INFO("disconnected to hub with prefix: " << prefix);
210 
211  // for phase 1: suppose there is at most one hub connected.
212  // if the hub prefix has been unregistered locally, there may
213  // be no connected hub.
214  m_hasConnectedHub = false;
215 
216  clearRefreshEvents();
217  return;
218  }
219 
220  if (!m_hasConnectedHub)
221  {
222  NFD_LOG_INFO("no hub connected when unregistering " << prefix);
223  return;
224  }
225 
226  std::pair<Name, size_t> identity = findIdentityForRegistration(prefix);
227 
228  if (0 == identity.second)
229  {
230  NFD_LOG_INFO("no proper identity found for unregistering " << prefix);
231  return;
232  }
233 
234  Name prefixForRegistration;
235  if (identity.first.size() == identity.second)
236  {
237  prefixForRegistration = identity.first;
238  }
239  else
240  {
241  prefixForRegistration = identity.first.getPrefix(-1);
242  }
243 
244  RegisteredEntryIt iRegEntry = m_regEntries.find(prefixForRegistration);
245  if (m_regEntries.end() == iRegEntry)
246  {
247  NFD_LOG_INFO("no existing entry found when unregistering " << prefix);
248  return;
249  }
250 
251  for (auto&& entry : m_rib)
252  {
253  if (prefixForRegistration.isPrefixOf(entry.first) &&
254  findIdentityForRegistration(entry.first) == identity)
255  {
256  NFD_LOG_INFO("this identity should be kept for other rib entry: "
257  << entry.first);
258  return;
259  }
260  }
261 
262  scheduler::cancel(iRegEntry->second);
263  m_regEntries.erase(iRegEntry);
264 
265  // make copies of m_controlParameters and m_commandOptions to
266  // avoid unreasonable overwriting during concurrent registration
267  // and unregistration.
268  ControlParameters parameters = m_controlParameters;
269  CommandOptions options = m_commandOptions;
270 
271  startUnregistration(parameters.setName(prefixForRegistration).unsetCost(),
272  options.setSigningInfo(signingByIdentity(identity.first)),
273  m_nRetries);
274 }
275 
276 std::pair<Name, size_t>
277 RemoteRegistrator::findIdentityForRegistration(const Name& prefix)
278 {
279  std::pair<Name, size_t> candidateIdentity;
280  std::vector<Name> identities;
281  bool isPrefix = false;
282  size_t maxLength = 0, curLength = 0;
283 
284  // get all identies from the key-cahin except the default one.
285  m_keyChain.getAllIdentities(identities, false);
286 
287  // get the default identity.
288  identities.push_back(m_keyChain.getDefaultIdentity());
289 
290  // longest prefix matching to all indenties.
291  for (auto&& i : identities)
292  {
293  if (!i.empty() && IGNORE_COMMPONENT == i.at(-1))
294  {
295  isPrefix = i.getPrefix(-1).isPrefixOf(prefix);
296  curLength = i.size() - 1;
297  }
298  else
299  {
300  isPrefix = i.isPrefixOf(prefix);
301  curLength = i.size();
302  }
303 
304  if (isPrefix && curLength > maxLength)
305  {
306  candidateIdentity.first = i;
307  maxLength = curLength;
308  }
309  }
310 
311  candidateIdentity.second = maxLength;
312 
313  return candidateIdentity;
314 }
315 
316 void
317 RemoteRegistrator::startRegistration(const ControlParameters& parameters,
318  const CommandOptions& options,
319  int nRetries)
320 {
321  NFD_LOG_INFO("start register " << parameters.getName());
322 
323  m_nfdController.start<ndn::nfd::RibRegisterCommand>(
324  parameters,
325  bind(&RemoteRegistrator::onRegSuccess,
326  this, parameters, options),
327  bind(&RemoteRegistrator::onRegFailure,
328  this, _1, _2, parameters, options, nRetries),
329  options);
330 }
331 
332 void
333 RemoteRegistrator::startUnregistration(const ControlParameters& parameters,
334  const CommandOptions& options,
335  int nRetries)
336 {
337  NFD_LOG_INFO("start unregister " << parameters.getName());
338 
339  m_nfdController.start<ndn::nfd::RibUnregisterCommand>(
340  parameters,
341  bind(&RemoteRegistrator::onUnregSuccess,
342  this, parameters, options),
343  bind(&RemoteRegistrator::onUnregFailure,
344  this, _1, _2, parameters, options, nRetries),
345  options);
346 }
347 
348 void
349 RemoteRegistrator::onRegSuccess(const ControlParameters& parameters,
350  const CommandOptions& options)
351 {
352  NFD_LOG_INFO("success to register " << parameters.getName());
353 
354  RegisteredEntryIt iRegEntry = m_regEntries.find(parameters.getName());
355 
356  if (m_regEntries.end() != iRegEntry)
357  {
358  NFD_LOG_DEBUG("Existing Entry: (" << iRegEntry->first
359  << ", " << iRegEntry->second
360  << ")");
361 
362  scheduler::cancel(iRegEntry->second);
363  iRegEntry->second = scheduler::schedule(
364  m_refreshInterval,
365  bind(&RemoteRegistrator::startRegistration,
366  this, parameters, options, m_nRetries));
367  }
368  else
369  {
370  NFD_LOG_DEBUG("New Entry");
371  m_regEntries.insert(RegisteredEntry(
372  parameters.getName(),
374  m_refreshInterval,
375  bind(&RemoteRegistrator::startRegistration,
376  this, parameters, options, m_nRetries))));
377  }
378 }
379 
380 void
381 RemoteRegistrator::onRegFailure(uint32_t code, const std::string& reason,
382  const ControlParameters& parameters,
383  const CommandOptions& options,
384  int nRetries)
385 {
386  NFD_LOG_INFO("fail to register " << parameters.getName()
387  << "\n\t reason:" << reason
388  << "\n\t remain retries:" << nRetries);
389 
390  if (nRetries > 0)
391  {
392  startRegistration(parameters, options, nRetries - 1);
393  }
394 }
395 
396 void
397 RemoteRegistrator::onUnregSuccess(const ControlParameters& parameters,
398  const CommandOptions& options)
399 {
400  NFD_LOG_INFO("success to unregister " << parameters.getName());
401 }
402 
403 void
404 RemoteRegistrator::onUnregFailure(uint32_t code, const std::string& reason,
405  const ControlParameters& parameters,
406  const CommandOptions& options,
407  int nRetries)
408 {
409  NFD_LOG_INFO("fail to unregister " << parameters.getName()
410  << "\n\t reason:" << reason
411  << "\n\t remain retries:" << nRetries);
412 
413  if (nRetries > 0)
414  {
415  startUnregistration(parameters, options, nRetries - 1);
416  }
417 }
418 
419 void
420 RemoteRegistrator::redoRegistration()
421 {
422  NFD_LOG_INFO("redo " << m_regEntries.size()
423  << " registration when new Hub connection is built.");
424 
425  for (auto&& entry : m_regEntries)
426  {
427  // make copies to avoid unreasonable overwrite.
428  ControlParameters parameters = m_controlParameters;
429  CommandOptions options = m_commandOptions;
430  startRegistration(parameters.setName(entry.first),
431  options.setSigningInfo(signingByIdentity(entry.first)),
432  m_nRetries);
433  }
434 }
435 
436 void
437 RemoteRegistrator::clearRefreshEvents()
438 {
439  for (auto&& entry : m_regEntries)
440  {
441  scheduler::cancel(entry.second);
442  }
443 }
444 
445 } // namespace rib
446 } // namespace nfd
void start(const ControlParameters &parameters, const CommandSucceedCallback &onSuccess, const CommandFailCallback &onFailure, const CommandOptions &options=CommandOptions())
start command execution
ControlParameters & setFaceId(uint64_t faceId)
represents the RIB
Definition: rib.hpp:45
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:36
represents parameters in a ControlCommand request or response
void cancel(const EventId &eventId)
cancel a scheduled event
Definition: scheduler.cpp:58
void registerPrefix(const Name &prefix)
register a prefix to remote hub(s).
void unregisterPrefix(const Name &prefix)
unregister a prefix from remote hub(s).
void disable()
disable remote registration/unregistration.
void loadConfig(const ConfigSection &configSection)
load the "remote_register" section from config file
CommandOptions & setTimeout(const time::milliseconds &timeout)
sets command timeout
#define NFD_LOG_INFO(expression)
Definition: logger.hpp:37
contains options for ControlCommand execution
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:38
SigningInfo signingByIdentity(const Name &identity)
NFD Management protocol - ControlCommand client.
boost::property_tree::ptree ConfigSection
EventId schedule(const time::nanoseconds &after, const std::function< void()> &event)
schedule an event
Definition: scheduler.cpp:50
Name abstraction to represent an absolute name.
Definition: name.hpp:46
represents a rib/unregister command
CommandOptions & setSigningInfo(const security::SigningInfo &signingInfo)
sets signing parameters
represents a rib/register command
ndn::util::signal::Signal< Rib, Name > afterInsertEntry
Definition: rib.hpp:208
ControlParameters & setCost(uint64_t cost)
void disconnect()
disconnects the connection manually
Component holds a read-only name component value.
RemoteRegistrator(ndn::nfd::Controller &controller, ndn::KeyChain &keyChain, Rib &rib)
ndn::util::signal::Signal< Rib, Name > afterEraseEntry
Definition: rib.hpp:209
void enable()
enable remote registration/unregistration.
#define NFD_LOG_INIT(name)
Definition: logger.hpp:33
ControlParameters & setOrigin(uint64_t origin)
ControlParameters & setName(const Name &name)
bool isPrefixOf(const Name &name) const
Check if the N components of this name are the same as the first N components of the given name...
Definition: name.cpp:320
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix (PartialName) of the name, containing first nComponents components.
Definition: name.hpp:249
CommandOptions & setPrefix(const Name &prefix)
sets command prefix