NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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  throw Error("Not supported");
149 }
150 
151 void
152 FaceManager::onFaceRequest(const Interest& request)
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();
253  ndn::nfd::FaceCreateCommand command;
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,
287  bind(&FaceManager::onCreated,
288  this, requestName, parameters, _1),
289  bind(&FaceManager::onConnectFailed,
290  this, requestName, _1));
291  }
292  catch (const std::runtime_error& error)
293  {
294  std::string errorMessage = "NFD error: ";
295  errorMessage += error.what();
296 
297  NFD_LOG_ERROR(errorMessage);
298  sendResponse(requestName, 500, errorMessage);
299  }
300  catch (const std::logic_error& error)
301  {
302  std::string errorMessage = "NFD error: ";
303  errorMessage += error.what();
304 
305  NFD_LOG_ERROR(errorMessage);
306  sendResponse(requestName, 500, errorMessage);
307  }
308 }
309 
310 
311 void
312 FaceManager::destroyFace(const Interest& request,
313  ControlParameters& parameters)
314 {
315  const Name& requestName = request.getName();
316  ndn::nfd::FaceDestroyCommand command;
317 
318  if (!validateParameters(command, parameters))
319  {
320  sendResponse(requestName, 400, "Malformed command");
321  return;
322  }
323 
324  shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
325  if (static_cast<bool>(target))
326  {
327  target->close();
328  }
329 
330  sendResponse(requestName, 200, "Success", parameters.wireEncode());
331 
332 }
333 
334 void
335 FaceManager::onAddFace(shared_ptr<Face> face)
336 {
337  ndn::nfd::FaceEventNotification notification;
338  notification.setKind(ndn::nfd::FACE_EVENT_CREATED);
339  face->copyStatusTo(notification);
340 
341  m_notificationStream.postNotification(notification);
342 }
343 
344 void
345 FaceManager::onRemoveFace(shared_ptr<Face> face)
346 {
347  ndn::nfd::FaceEventNotification notification;
348  notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED);
349  face->copyStatusTo(notification);
350 
351  m_notificationStream.postNotification(notification);
352 }
353 
354 bool
355 FaceManager::extractLocalControlParameters(const Interest& request,
356  ControlParameters& parameters,
357  ControlCommand& command,
358  shared_ptr<LocalFace>& outFace,
359  LocalControlFeature& outFeature)
360 {
361  if (!validateParameters(command, parameters))
362  {
363  sendResponse(request.getName(), 400, "Malformed command");
364  return false;
365  }
366 
367  shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
368 
369  if (!static_cast<bool>(face))
370  {
371  NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
372  sendResponse(request.getName(), 410, "Face not found");
373  return false;
374  }
375  else if (!face->isLocal())
376  {
377  NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
378  face->getId());
379  sendResponse(request.getName(), 412, "Face is non-local");
380  return false;
381  }
382 
383  outFace = dynamic_pointer_cast<LocalFace>(face);
384  outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
385 
386  return true;
387 }
388 
389 void
390 FaceManager::enableLocalControl(const Interest& request,
391  ControlParameters& parameters)
392 {
393  ndn::nfd::FaceEnableLocalControlCommand command;
394 
395 
396  shared_ptr<LocalFace> face;
397  LocalControlFeature feature;
398 
399  if (extractLocalControlParameters(request, parameters, command, face, feature))
400  {
401  face->setLocalControlHeaderFeature(feature, true);
402  sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
403  }
404 }
405 
406 void
407 FaceManager::disableLocalControl(const Interest& request,
408  ControlParameters& parameters)
409 {
410  ndn::nfd::FaceDisableLocalControlCommand command;
411  shared_ptr<LocalFace> face;
412  LocalControlFeature feature;
413 
414  if (extractLocalControlParameters(request, parameters, command, face, feature))
415  {
416  face->setLocalControlHeaderFeature(feature, false);
417  sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
418  }
419 }
420 
421 void
422 FaceManager::listFaces(const Interest& request)
423 {
424  const Name& command = request.getName();
425  const size_t commandNComps = command.size();
426 
427  if (commandNComps < FACES_LIST_DATASET_NCOMPS ||
428  !FACES_LIST_DATASET_PREFIX.isPrefixOf(command))
429  {
430  NFD_LOG_DEBUG("command result: malformed");
431  sendResponse(command, 400, "Malformed command");
432  return;
433  }
434 
435  m_faceStatusPublisher.publish();
436 }
437 
438 void
439 FaceManager::listChannels(const Interest& request)
440 {
441  NFD_LOG_DEBUG("in listChannels");
442  const Name& command = request.getName();
443  const size_t commandNComps = command.size();
444 
445  if (commandNComps < CHANNELS_LIST_DATASET_NCOMPS ||
446  !CHANNELS_LIST_DATASET_PREFIX.isPrefixOf(command))
447  {
448  NFD_LOG_DEBUG("command result: malformed");
449  sendResponse(command, 400, "Malformed command");
450  return;
451  }
452 
453  NFD_LOG_DEBUG("publishing");
454  m_channelStatusPublisher.publish();
455 }
456 
457 void
458 FaceManager::listQueriedFaces(const Interest& request)
459 {
460  NFD_LOG_DEBUG("in listQueriedFaces");
461  const Name& query = request.getName();
462  const size_t queryNComps = query.size();
463 
464  if (queryNComps < FACES_QUERY_DATASET_NCOMPS ||
465  !FACES_QUERY_DATASET_PREFIX.isPrefixOf(query))
466  {
467  NFD_LOG_DEBUG("query result: malformed");
468  sendNack(query);
469  return;
470  }
471 
472  ndn::nfd::FaceQueryFilter faceFilter;
473  try
474  {
475  faceFilter.wireDecode(query[-1].blockFromValue());
476  }
477  catch (tlv::Error&)
478  {
479  NFD_LOG_DEBUG("query result: malformed filter");
480  sendNack(query);
481  return;
482  }
483 
485  faceQueryStatusPublisher(m_faceTable, *m_face, query, faceFilter, m_keyChain);
486 
487  faceQueryStatusPublisher.publish();
488 }
489 
490 shared_ptr<ProtocolFactory>
491 FaceManager::findFactory(const std::string& protocol)
492 {
493  FactoryMap::iterator factory = m_factories.find(protocol);
494  if (factory != m_factories.end())
495  return factory->second;
496  else
497  return shared_ptr<ProtocolFactory>();
498 }
499 
500 } // namespace nfd
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.
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:36
ndn::KeyChain & m_keyChain
void add(shared_ptr< Face > face)
Definition: face-table.cpp:59
void sendResponse(const Name &name, const ControlResponse &response)
#define NFD_LOG_ERROR(expression)
Definition: logger.hpp:38
static bool extractParameters(const Name::Component &parameterComponent, ControlParameters &extractedParameters)
container of all Faces
Definition: face-table.hpp:38
void addSectionHandler(const std::string &sectionName, ConfigSectionHandler subscriber)
setup notification of configuration file sections
Definition: config-file.cpp:63
void onFaceRequest(const Interest &request)
const std::string FACE_MANAGER_PRIVILEGE
void onCommandValidationFailed(const shared_ptr< const Interest > &command, const std::string &error)
boost::property_tree::ptree ConfigSection
void sendNack(const Name &name)
virtual ~FaceManager()
#define NFD_LOG_INIT(name)
Definition: logger.hpp:33
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:35
virtual bool validateParameters(const ControlCommand &command, ControlParameters &parameters)
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)