NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
face-manager.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "face-manager.hpp"
27 
28 #include "core/logger.hpp"
29 #include "core/config-file.hpp"
31 #include "fw/face-table.hpp"
32 
33 #include <ndn-cxx/management/nfd-face-event-notification.hpp>
34 #include <ndn-cxx/management/nfd-face-query-filter.hpp>
35 
36 namespace nfd {
37 
38 NFD_LOG_INIT("FaceManager");
39 
40 const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
41 
42 const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
43  FaceManager::COMMAND_PREFIX.size() +
44  1 + // verb
45  1; // verb parameters
46 
47 const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
48  FaceManager::COMMAND_UNSIGNED_NCOMPS +
49  4; // (timestamp, nonce, signed info tlv, signature tlv)
50 
51 const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
52  {
53  SignedVerbAndProcessor(
54  Name::Component("create"),
55  &FaceManager::createFace
56  ),
57 
58  SignedVerbAndProcessor(
59  Name::Component("destroy"),
60  &FaceManager::destroyFace
61  ),
62 
63  SignedVerbAndProcessor(
64  Name::Component("enable-local-control"),
65  &FaceManager::enableLocalControl
66  ),
67 
68  SignedVerbAndProcessor(
69  Name::Component("disable-local-control"),
70  &FaceManager::disableLocalControl
71  ),
72  };
73 
74 const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
75  {
76  UnsignedVerbAndProcessor(
77  Name::Component("list"),
78  &FaceManager::listFaces
79  ),
80 
81  UnsignedVerbAndProcessor(
82  Name::Component("events"),
83  &FaceManager::ignoreUnsignedVerb
84  ),
85 
86  UnsignedVerbAndProcessor(
87  Name::Component("channels"),
88  &FaceManager::listChannels
89  ),
90 
91  UnsignedVerbAndProcessor(
92  Name::Component("query"),
93  &FaceManager::listQueriedFaces
94  ),
95  };
96 
97 const Name FaceManager::FACES_LIST_DATASET_PREFIX("/localhost/nfd/faces/list");
98 const size_t FaceManager::FACES_LIST_DATASET_NCOMPS = FACES_LIST_DATASET_PREFIX.size();
99 
100 const Name FaceManager::FACE_EVENTS_PREFIX("/localhost/nfd/faces/events");
101 
102 const Name FaceManager::CHANNELS_LIST_DATASET_PREFIX("/localhost/nfd/faces/channels");
103 const size_t FaceManager::CHANNELS_LIST_DATASET_NCOMPS = CHANNELS_LIST_DATASET_PREFIX.size();
104 
105 const Name FaceManager::FACES_QUERY_DATASET_PREFIX("/localhost/nfd/faces/query");
106 const size_t FaceManager::FACES_QUERY_DATASET_NCOMPS = FACES_QUERY_DATASET_PREFIX.size() + 1;
107 
109  shared_ptr<InternalFace> face,
110  ndn::KeyChain& keyChain)
111  : ManagerBase(face, FACE_MANAGER_PRIVILEGE, keyChain)
112  , m_faceTable(faceTable)
113  , m_faceAddConn(m_faceTable.onAdd.connect(bind(&FaceManager::onAddFace, this, _1)))
114  , m_faceRemoveConn(m_faceTable.onRemove.connect(bind(&FaceManager::onRemoveFace, this, _1)))
115  , m_faceStatusPublisher(m_faceTable, *m_face, FACES_LIST_DATASET_PREFIX, keyChain)
116  , m_channelStatusPublisher(m_factories, *m_face, CHANNELS_LIST_DATASET_PREFIX, keyChain)
117  , m_notificationStream(*m_face, FACE_EVENTS_PREFIX, keyChain)
118  , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
119  SIGNED_COMMAND_VERBS +
120  (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
121  , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
122  UNSIGNED_COMMAND_VERBS +
123  (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
124 
125 {
126  face->setInterestFilter("/localhost/nfd/faces",
127  bind(&FaceManager::onFaceRequest, this, _2));
128 }
129 
131 {
132 
133 }
134 
135 void
137 {
138  configFile.addSectionHandler("face_system",
139  bind(&FaceManager::onConfig, this, _1, _2, _3));
140 }
141 
142 
143 void
144 FaceManager::onConfig(const ConfigSection& configSection,
145  bool isDryRun,
146  const std::string& filename)
147 {
148  BOOST_THROW_EXCEPTION(Error("Not supported"));
149 }
150 
151 void
153 {
154  const Name& command = request.getName();
155  const size_t commandNComps = command.size();
156 
157  if (commandNComps <= COMMAND_PREFIX.size())
158  {
159  // command is too short to have a verb
160  NFD_LOG_DEBUG("command result: malformed");
161  sendResponse(command, 400, "Malformed command");
162  return;
163  }
164 
165  const Name::Component& verb = command.at(COMMAND_PREFIX.size());
166 
167  const auto unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
168  if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
169  {
170  NFD_LOG_DEBUG("command result: processing verb: " << verb);
171  (unsignedVerbProcessor->second)(this, request);
172  }
173  else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
174  commandNComps < COMMAND_SIGNED_NCOMPS)
175  {
176  NFD_LOG_DEBUG("command result: unsigned verb: " << command);
177  sendResponse(command, 401, "Signature required");
178  }
179  else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
180  !COMMAND_PREFIX.isPrefixOf(command))
181  {
182  NFD_LOG_DEBUG("command result: malformed");
183  sendResponse(command, 400, "Malformed command");
184  }
185  else
186  {
187  validate(request,
188  bind(&FaceManager::onValidatedFaceRequest, this, _1),
189  bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
190  }
191 }
192 
193 void
194 FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
195 {
196  const Name& command = request->getName();
197  const Name::Component& verb = command[COMMAND_PREFIX.size()];
198  const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
199 
200  SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
201  if (signedVerbProcessor != m_signedVerbDispatch.end())
202  {
203  ControlParameters parameters;
204  if (!extractParameters(parameterComponent, parameters))
205  {
206  sendResponse(command, 400, "Malformed command");
207  return;
208  }
209 
210  NFD_LOG_DEBUG("command result: processing verb: " << verb);
211  (signedVerbProcessor->second)(this, *request, parameters);
212  }
213  else
214  {
215  NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
216  sendResponse(command, 501, "Unsupported command");
217  }
218 
219 }
220 
221 void
222 FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
223 {
224  m_faceTable.add(newFace);
225 
226  //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
227 }
228 
229 void
230 FaceManager::onCreated(const Name& requestName,
231  ControlParameters& parameters,
232  const shared_ptr<Face>& newFace)
233 {
234  addCreatedFaceToForwarder(newFace);
235  parameters.setFaceId(newFace->getId());
236  parameters.setUri(newFace->getRemoteUri().toString());
237 
238  sendResponse(requestName, 200, "Success", parameters.wireEncode());
239 }
240 
241 void
242 FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
243 {
244  NFD_LOG_DEBUG("Failed to create face: " << reason);
245  sendResponse(requestName, 408, reason);
246 }
247 
248 void
249 FaceManager::createFace(const Interest& request,
250  ControlParameters& parameters)
251 {
252  const Name& requestName = request.getName();
254 
255  if (!validateParameters(command, parameters))
256  {
257  sendResponse(requestName, 400, "Malformed command");
258  NFD_LOG_TRACE("invalid control parameters URI");
259  return;
260  }
261 
262  FaceUri uri;
263  if (!uri.parse(parameters.getUri()))
264  {
265  sendResponse(requestName, 400, "Malformed command");
266  NFD_LOG_TRACE("failed to parse URI");
267  return;
268  }
269 
270  if (!uri.isCanonical())
271  {
272  sendResponse(requestName, 400, "Non-canonical URI");
273  NFD_LOG_TRACE("received non-canonical URI");
274  return;
275  }
276 
277  FactoryMap::iterator factory = m_factories.find(uri.getScheme());
278  if (factory == m_factories.end())
279  {
280  sendResponse(requestName, 501, "Unsupported protocol");
281  return;
282  }
283 
284  try
285  {
286  factory->second->createFace(uri,
288  bind(&FaceManager::onCreated,
289  this, requestName, parameters, _1),
290  bind(&FaceManager::onConnectFailed,
291  this, requestName, _1));
292  }
293  catch (const std::runtime_error& error)
294  {
295  std::string errorMessage = "NFD error: ";
296  errorMessage += error.what();
297 
298  NFD_LOG_ERROR(errorMessage);
299  sendResponse(requestName, 500, errorMessage);
300  }
301  catch (const std::logic_error& error)
302  {
303  std::string errorMessage = "NFD error: ";
304  errorMessage += error.what();
305 
306  NFD_LOG_ERROR(errorMessage);
307  sendResponse(requestName, 500, errorMessage);
308  }
309 }
310 
311 
312 void
313 FaceManager::destroyFace(const Interest& request,
314  ControlParameters& parameters)
315 {
316  const Name& requestName = request.getName();
318 
319  if (!validateParameters(command, parameters))
320  {
321  sendResponse(requestName, 400, "Malformed command");
322  return;
323  }
324 
325  shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
326  if (static_cast<bool>(target))
327  {
328  target->close();
329  }
330 
331  sendResponse(requestName, 200, "Success", parameters.wireEncode());
332 
333 }
334 
335 void
336 FaceManager::onAddFace(shared_ptr<Face> face)
337 {
338  ndn::nfd::FaceEventNotification notification;
340  face->copyStatusTo(notification);
341 
342  m_notificationStream.postNotification(notification);
343 }
344 
345 void
346 FaceManager::onRemoveFace(shared_ptr<Face> face)
347 {
348  ndn::nfd::FaceEventNotification notification;
350  face->copyStatusTo(notification);
351 
352  m_notificationStream.postNotification(notification);
353 }
354 
355 bool
356 FaceManager::extractLocalControlParameters(const Interest& request,
357  ControlParameters& parameters,
358  ControlCommand& command,
359  shared_ptr<LocalFace>& outFace,
360  LocalControlFeature& outFeature)
361 {
362  if (!validateParameters(command, parameters))
363  {
364  sendResponse(request.getName(), 400, "Malformed command");
365  return false;
366  }
367 
368  shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
369 
370  if (!static_cast<bool>(face))
371  {
372  NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
373  sendResponse(request.getName(), 410, "Face not found");
374  return false;
375  }
376  else if (!face->isLocal())
377  {
378  NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
379  face->getId());
380  sendResponse(request.getName(), 412, "Face is non-local");
381  return false;
382  }
383 
384  outFace = dynamic_pointer_cast<LocalFace>(face);
385  outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
386 
387  return true;
388 }
389 
390 void
391 FaceManager::enableLocalControl(const Interest& request,
392  ControlParameters& parameters)
393 {
395 
396 
397  shared_ptr<LocalFace> face;
398  LocalControlFeature feature;
399 
400  if (extractLocalControlParameters(request, parameters, command, face, feature))
401  {
402  face->setLocalControlHeaderFeature(feature, true);
403  sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
404  }
405 }
406 
407 void
408 FaceManager::disableLocalControl(const Interest& request,
409  ControlParameters& parameters)
410 {
412  shared_ptr<LocalFace> face;
413  LocalControlFeature feature;
414 
415  if (extractLocalControlParameters(request, parameters, command, face, feature))
416  {
417  face->setLocalControlHeaderFeature(feature, false);
418  sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
419  }
420 }
421 
422 void
423 FaceManager::listFaces(const Interest& request)
424 {
425  const Name& command = request.getName();
426  const size_t commandNComps = command.size();
427 
428  if (commandNComps < FACES_LIST_DATASET_NCOMPS ||
429  !FACES_LIST_DATASET_PREFIX.isPrefixOf(command))
430  {
431  NFD_LOG_DEBUG("command result: malformed");
432  sendResponse(command, 400, "Malformed command");
433  return;
434  }
435 
436  m_faceStatusPublisher.publish();
437 }
438 
439 void
440 FaceManager::listChannels(const Interest& request)
441 {
442  NFD_LOG_DEBUG("in listChannels");
443  const Name& command = request.getName();
444  const size_t commandNComps = command.size();
445 
446  if (commandNComps < CHANNELS_LIST_DATASET_NCOMPS ||
447  !CHANNELS_LIST_DATASET_PREFIX.isPrefixOf(command))
448  {
449  NFD_LOG_DEBUG("command result: malformed");
450  sendResponse(command, 400, "Malformed command");
451  return;
452  }
453 
454  NFD_LOG_DEBUG("publishing");
455  m_channelStatusPublisher.publish();
456 }
457 
458 void
459 FaceManager::listQueriedFaces(const Interest& request)
460 {
461  NFD_LOG_DEBUG("in listQueriedFaces");
462  const Name& query = request.getName();
463  const size_t queryNComps = query.size();
464 
465  if (queryNComps < FACES_QUERY_DATASET_NCOMPS ||
466  !FACES_QUERY_DATASET_PREFIX.isPrefixOf(query))
467  {
468  NFD_LOG_DEBUG("query result: malformed");
469  sendNack(query);
470  return;
471  }
472 
473  ndn::nfd::FaceQueryFilter faceFilter;
474  try
475  {
476  faceFilter.wireDecode(query[-1].blockFromValue());
477  }
478  catch (tlv::Error&)
479  {
480  NFD_LOG_DEBUG("query result: malformed filter");
481  sendNack(query);
482  return;
483  }
484 
486  faceQueryStatusPublisher(m_faceTable, *m_face, query, faceFilter, m_keyChain);
487 
488  faceQueryStatusPublisher.publish();
489 }
490 
491 shared_ptr<ProtocolFactory>
492 FaceManager::findFactory(const std::string& protocol)
493 {
494  FactoryMap::iterator factory = m_factories.find(protocol);
495  if (factory != m_factories.end())
496  return factory->second;
497  else
498  return shared_ptr<ProtocolFactory>();
499 }
500 
501 } // namespace nfd
represents a faces/disable-local-control command
shared_ptr< InternalFace > m_face
FaceManager(FaceTable &faceTable, shared_ptr< InternalFace > face, ndn::KeyChain &keyChain)
void setConfigFile(ConfigFile &configFile)
Subscribe to a face management section(s) for the config file.
ControlParameters & setFaceId(uint64_t faceId)
const Name & getName() const
Definition: interest.hpp:216
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:36
bool parse(const std::string &uri)
exception-safe parsing
Definition: face-uri.cpp:63
represents parameters in a ControlCommand request or response
ndn::KeyChain & m_keyChain
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:44
void add(shared_ptr< Face > face)
Definition: face-table.cpp:59
void sendResponse(const Name &name, const ControlResponse &response)
base class of NFD ControlCommand
represents a Face status change notification
represents an Interest packet
Definition: interest.hpp:45
#define NFD_LOG_ERROR(expression)
Definition: logger.hpp:38
FaceEventNotification & setKind(FaceEventKind kind)
ControlParameters & setUri(const std::string &uri)
represents a faces/create command
Table::const_iterator iterator
Definition: cs-internal.hpp:41
represents a faces/enable-local-control command
size_t wireEncode(EncodingImpl< TAG > &encoder) const
bool isCanonical() const
determine whether this FaceUri is in canonical form
Definition: face-uri.cpp:507
static bool extractParameters(const Name::Component &parameterComponent, ControlParameters &extractedParameters)
container of all Faces
Definition: face-table.hpp:38
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:38
void addSectionHandler(const std::string &sectionName, ConfigSectionHandler subscriber)
setup notification of configuration file sections
Definition: config-file.cpp:61
void onFaceRequest(const Interest &request)
const std::string FACE_MANAGER_PRIVILEGE
const std::string & getScheme() const
get scheme (protocol)
Definition: face-uri.hpp:109
void onCommandValidationFailed(const shared_ptr< const Interest > &command, const std::string &error)
uint64_t getIncomingFaceId() const
Definition: interest.hpp:290
size_t size() const
Get the number of components.
Definition: name.hpp:408
boost::property_tree::ptree ConfigSection
Name abstraction to represent an absolute name.
Definition: name.hpp:46
represents Face Query Filter
void sendNack(const Name &name)
LocalControlFeature getLocalControlFeature() const
Component holds a read-only name component value.
virtual ~FaceManager()
#define NFD_LOG_INIT(name)
Definition: logger.hpp:33
represents a face
Definition: local-face.hpp:40
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:35
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
virtual bool validateParameters(const ControlCommand &command, ControlParameters &parameters)
represents a faces/destroy command
shared_ptr< Face > get(FaceId id) const
Definition: face-table.cpp:46
void validate(const Interest &interest, const ndn::OnInterestValidated &onValidated, const ndn::OnInterestValidationFailed &onValidationFailed)
void wireDecode(const Block &wire)
decode FaceQueryFilter
const std::string & getUri() const
const Component & at(ssize_t i) const
Get component at the specified index.
Definition: name.hpp:442
represents an error in TLV encoding or decoding
Definition: tlv.hpp:50