NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
dispatcher.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "dispatcher.hpp"
27 
28 #include <algorithm>
29 
30 // #define NDN_CXX_MGMT_DISPATCHER_ENABLE_LOGGING
31 
32 namespace ndn {
33 namespace mgmt {
34 
37 {
38  return [] (const Name& prefix,
39  const Interest& interest,
40  const ControlParameters* params,
41  AcceptContinuation accept,
42  RejectContinuation reject) {
43  accept("");
44  };
45 }
46 
48  const security::SigningInfo& signingInfo)
49  : m_face(face)
50  , m_keyChain(keyChain)
51  , m_signingInfo(signingInfo)
52 {
53 }
54 
56 {
57  std::vector<Name> topPrefixNames;
58 
59  std::transform(m_topLevelPrefixes.begin(),
60  m_topLevelPrefixes.end(),
61  std::back_inserter(topPrefixNames),
62  [] (const std::unordered_map<Name, TopPrefixEntry>::value_type& entry) {
63  return entry.second.topPrefix;
64  });
65 
66  for (auto&& name : topPrefixNames) {
68  }
69 }
70 
71 void
73  bool wantRegister,
74  const security::SigningInfo& signingInfo)
75 {
76  bool hasOverlap = std::any_of(m_topLevelPrefixes.begin(),
77  m_topLevelPrefixes.end(),
78  [&] (const std::unordered_map<Name, TopPrefixEntry>::value_type& x) {
79  return x.first.isPrefixOf(prefix) || prefix.isPrefixOf(x.first);
80  });
81  if (hasOverlap) {
82  BOOST_THROW_EXCEPTION(std::out_of_range("Top-level Prefixes overlapped"));
83  }
84 
85  TopPrefixEntry& topPrefixEntry = m_topLevelPrefixes[prefix];;
86  topPrefixEntry.topPrefix = prefix;
87  topPrefixEntry.wantRegister = wantRegister;
88 
89  if (wantRegister) {
90  RegisterPrefixFailureCallback failure = [] (const Name& name, const std::string& reason) {
91  BOOST_THROW_EXCEPTION(std::runtime_error(reason));
92  };
93  topPrefixEntry.registerPrefixId =
94  m_face.registerPrefix(prefix, bind([]{}), failure, signingInfo);
95  }
96 
97  for (auto&& entry : m_handlers) {
98  Name fullPrefix = prefix;
99  fullPrefix.append(entry.first);
100 
101  const InterestFilterId* interestFilterId =
102  m_face.setInterestFilter(fullPrefix, std::bind(entry.second, prefix, _2));
103 
104  topPrefixEntry.interestFilters.push_back(interestFilterId);
105  }
106 }
107 
108 void
110 {
111  auto it = m_topLevelPrefixes.find(prefix);
112  if (it == m_topLevelPrefixes.end()) {
113  return;
114  }
115 
116  const TopPrefixEntry& topPrefixEntry = it->second;
117  if (topPrefixEntry.wantRegister) {
118  m_face.unregisterPrefix(topPrefixEntry.registerPrefixId, bind([]{}), bind([]{}));
119  }
120 
121  for (auto&& filter : topPrefixEntry.interestFilters) {
122  m_face.unsetInterestFilter(filter);
123  }
124 
125  m_topLevelPrefixes.erase(it);
126 }
127 
128 bool
129 Dispatcher::isOverlappedWithOthers(const PartialName& relPrefix)
130 {
131  bool hasOverlapWithHandlers =
132  std::any_of(m_handlers.begin(), m_handlers.end(),
133  [&] (const HandlerMap::value_type& entry) {
134  return entry.first.isPrefixOf(relPrefix) || relPrefix.isPrefixOf(entry.first);
135  });
136  bool hasOverlapWithStreams =
137  std::any_of(m_streams.begin(), m_streams.end(),
138  [&] (const std::unordered_map<PartialName, uint64_t>::value_type& entry) {
139  return entry.first.isPrefixOf(relPrefix) || relPrefix.isPrefixOf(entry.first);
140  });
141 
142  return hasOverlapWithHandlers || hasOverlapWithStreams;
143 }
144 
145 void
146 Dispatcher::afterAuthorizationRejected(RejectReply act, const Interest& interest)
147 {
148  if (act == RejectReply::STATUS403) {
149  sendControlResponse(ControlResponse(403, "authorization rejected"), interest);
150  }
151 }
152 
153 void
154 Dispatcher::sendData(const Name& dataName, const Block& content,
155  const MetaInfo& metaInfo)
156 {
157  shared_ptr<Data> data = make_shared<Data>(dataName);
158  data->setContent(content).setMetaInfo(metaInfo);
159 
160  m_keyChain.sign(*data, m_signingInfo);
161 
162  try {
163  m_face.put(*data);
164  }
165  catch (Face::Error& e) {
166 #ifdef NDN_CXX_MGMT_DISPATCHER_ENABLE_LOGGING
167  std::clog << e.what() << std::endl;
168 #endif // NDN_CXX_MGMT_DISPATCHER_ENABLE_LOGGING.
169  }
170 }
171 
172 void
173 Dispatcher::processControlCommandInterest(const Name& prefix,
174  const Name& relPrefix,
175  const Interest& interest,
176  const ControlParametersParser& parser,
177  const Authorization& authorization,
178  const AuthorizationAcceptedCallback& accepted,
179  const AuthorizationRejectedCallback& rejected)
180 {
181  // /<prefix>/<relPrefix>/<parameters>
182  size_t parametersLoc = prefix.size() + relPrefix.size();
183  const name::Component& pc = interest.getName().get(parametersLoc);
184 
185  shared_ptr<ControlParameters> parameters;
186  try {
187  parameters = parser(pc);
188  }
189  catch (tlv::Error& e) {
190  return;
191  }
192 
193  AcceptContinuation accept = bind(accepted, _1, prefix, interest, parameters.get());
194  RejectContinuation reject = bind(rejected, _1, interest);
195  authorization(prefix, interest, parameters.get(), accept, reject);
196 }
197 
198 void
199 Dispatcher::processAuthorizedControlCommandInterest(const std::string& requester,
200  const Name& prefix,
201  const Interest& interest,
202  const ControlParameters* parameters,
203  const ValidateParameters& validateParams,
204  const ControlCommandHandler& handler)
205 {
206  if (validateParams(*parameters)) {
207  handler(prefix, interest, *parameters,
208  bind(&Dispatcher::sendControlResponse, this, _1, interest, false));
209  }
210  else {
211  sendControlResponse(ControlResponse(400, "failed in validating parameters"), interest);
212  }
213 }
214 
215 void
216 Dispatcher::sendControlResponse(const ControlResponse& resp, const Interest& interest,
217  bool isNack/*= false*/)
218 {
219  MetaInfo info;
220  if (isNack) {
222  }
223 
224  sendData(interest.getName(), resp.wireEncode(), info);
225 }
226 
227 void
229  Authorization authorization,
230  StatusDatasetHandler handler)
231 {
232  if (!m_topLevelPrefixes.empty()) {
233  BOOST_THROW_EXCEPTION(std::domain_error("one or more top-level prefix has been added"));
234  }
235 
236  if (isOverlappedWithOthers(relPrefix)) {
237  BOOST_THROW_EXCEPTION(std::out_of_range("relPrefix overlapped"));
238  }
239 
240  AuthorizationAcceptedCallback accepted =
241  bind(&Dispatcher::processAuthorizedStatusDatasetInterest, this,
242  _1, _2, _3, handler);
243  AuthorizationRejectedCallback rejected =
244  bind(&Dispatcher::afterAuthorizationRejected, this, _1, _2);
245  m_handlers[relPrefix] = bind(&Dispatcher::processStatusDatasetInterest, this,
246  _1, _2, authorization, accepted, rejected);
247 }
248 
249 void
250 Dispatcher::processStatusDatasetInterest(const Name& prefix,
251  const Interest& interest,
252  const Authorization& authorization,
253  const AuthorizationAcceptedCallback& accepted,
254  const AuthorizationRejectedCallback& rejected)
255 {
256  const Name& interestName = interest.getName();
257  bool endsWithVersionOrSegment = interestName.size() >= 1 &&
258  (interestName[-1].isVersion() || interestName[-1].isSegment());
259  if (endsWithVersionOrSegment) {
260  return;
261  }
262 
263  AcceptContinuation accept = bind(accepted, _1, prefix, interest, nullptr);
264  RejectContinuation reject = bind(rejected, _1, interest);
265  authorization(prefix, interest, nullptr, accept, reject);
266 }
267 
268 void
269 Dispatcher::processAuthorizedStatusDatasetInterest(const std::string& requester,
270  const Name& prefix,
271  const Interest& interest,
272  const StatusDatasetHandler& handler)
273 {
274  StatusDatasetContext context(interest, bind(&Dispatcher::sendData, this, _1, _2, _3));
275  handler(prefix, interest, context);
276 }
277 
280 {
281  if (!m_topLevelPrefixes.empty()) {
282  throw std::domain_error("one or more top-level prefix has been added");
283  }
284 
285  if (isOverlappedWithOthers(relPrefix)) {
286  throw std::out_of_range("relPrefix overlaps with another relPrefix");
287  }
288 
289  m_streams[relPrefix] = 0;
290  return bind(&Dispatcher::postNotification, this, _1, relPrefix);
291 }
292 
293 void
294 Dispatcher::postNotification(const Block& notification, const PartialName& relPrefix)
295 {
296  if (m_topLevelPrefixes.empty() || m_topLevelPrefixes.size() > 1) {
297 #ifdef NDN_CXX_MGMT_DISPATCHER_ENABLE_LOGGING
298  std::clog << "no top-level prefix or too many top-level prefixes" << std::endl;
299 #endif // NDN_CXX_MGMT_DISPATCHER_ENABLE_LOGGING.
300  return;
301  }
302 
303  Name streamName(m_topLevelPrefixes.begin()->second.topPrefix);
304  streamName.append(relPrefix);
305  streamName.appendSequenceNumber(m_streams[streamName]++);
306  sendData(streamName, notification, MetaInfo());
307 }
308 
309 } // namespace mgmt
310 } // namespace ndn
const Name & getName() const
Definition: interest.hpp:216
Copyright (c) 2011-2015 Regents of the University of California.
indicates a producer generated NACK
Definition: tlv.hpp:135
std::function< void(const Block &notification)> PostNotification
a function to post a notification
Definition: dispatcher.hpp:126
RejectReply
indicate how to reply in case authorization is rejected
Definition: dispatcher.hpp:52
reply with a ControlResponse where StatusCode is 403
The packet signing interface.
Definition: key-chain.hpp:48
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
represents an Interest packet
Definition: interest.hpp:45
std::function< void(RejectReply act)> RejectContinuation
a function to be called if authorization is rejected
Definition: dispatcher.hpp:63
std::function< void(const std::string &requester)> AcceptContinuation
a function to be called if authorization is successful
Definition: dispatcher.hpp:48
const Block & wireEncode() const
void sign(Data &data, const SigningInfo &params=DEFAULT_SIGNING_INFO)
Sign data according to the supplied signing information.
Definition: key-chain.cpp:517
Authorization makeAcceptAllAuthorization()
Definition: dispatcher.cpp:36
Signing parameters passed to KeyChain.
void unregisterPrefix(const RegisteredPrefixId *registeredPrefixId, const UnregisterPrefixSuccessCallback &onSuccess, const UnregisterPrefixFailureCallback &onFailure)
Unregister prefix from RIB.
Definition: face.cpp:297
Name & appendSequenceNumber(uint64_t seqNo)
Append sequence number using NDN naming conventions.
Definition: name.cpp:253
ndn::mgmt::ControlResponse ControlResponse
MetaInfo & setType(uint32_t type)
set ContentType
Definition: meta-info.cpp:47
void addStatusDataset(const PartialName &relPrefix, Authorization authorization, StatusDatasetHandler handler)
register a StatusDataset or a prefix under which StatusDatasets can be requested
Definition: dispatcher.cpp:228
const RegisteredPrefixId * setInterestFilter(const InterestFilter &interestFilter, const OnInterest &onInterest, const RegisterPrefixFailureCallback &onFailure, const security::SigningInfo &signingInfo=security::SigningInfo(), uint64_t flags=nfd::ROUTE_FLAG_CHILD_INHERIT)
Set InterestFilter to dispatch incoming matching interest to onInterest callback and register the fil...
Definition: face.cpp:121
Dispatcher(Face &face, security::KeyChain &keyChain, const security::SigningInfo &signingInfo=security::SigningInfo())
constructor
Definition: dispatcher.cpp:47
Abstraction to communicate with local or remote NDN forwarder.
Definition: face.hpp:100
void addTopPrefix(const Name &prefix, bool wantRegister=true, const security::SigningInfo &signingInfo=security::SigningInfo())
add a top-level prefix
Definition: dispatcher.cpp:72
An MetaInfo holds the meta info which is signed inside the data packet.
Definition: meta-info.hpp:56
size_t size() const
Get the number of components.
Definition: name.hpp:408
function< void(const Name &, const std::string &)> RegisterPrefixFailureCallback
Callback called when registerPrefix or setInterestFilter command fails.
Definition: face.hpp:85
Name abstraction to represent an absolute name.
Definition: name.hpp:46
void unsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
Remove the registered prefix entry with the registeredPrefixId.
Definition: face.cpp:280
base class for a struct that contains ControlCommand parameters
Component holds a read-only name component value.
std::function< bool(const ControlParameters &params)> ValidateParameters
a function to validate input ControlParameters
Definition: dispatcher.hpp:93
Name & append(const uint8_t *value, size_t valueLength)
Append a new component, copying from value of length valueLength.
Definition: name.hpp:148
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
void removeTopPrefix(const Name &prefix)
remove a top-level prefix
Definition: dispatcher.cpp:109
ControlCommand response.
std::function< void(const Name &prefix, const Interest &interest, const ControlParameters &params, CommandContinuation done)> ControlCommandHandler
a function to handle an authorized ControlCommand
Definition: dispatcher.hpp:109
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:419
const RegisteredPrefixId * registerPrefix(const Name &prefix, const RegisterPrefixSuccessCallback &onSuccess, const RegisterPrefixFailureCallback &onFailure, const security::SigningInfo &signingInfo=security::SigningInfo(), uint64_t flags=nfd::ROUTE_FLAG_CHILD_INHERIT)
Register prefix with the connected NDN forwarder.
Definition: face.cpp:234
std::function< void(const Name &prefix, const Interest &interest, const ControlParameters *params, AcceptContinuation accept, RejectContinuation reject)> Authorization
a function that performs authorization
Definition: dispatcher.hpp:80
represents an error in TLV encoding or decoding
Definition: tlv.hpp:50
PostNotification addNotificationStream(const PartialName &relPrefix)
register a NotificationStream
Definition: dispatcher.cpp:279
void put(const Data &data)
Publish data packet.
Definition: face.cpp:87
std::function< void(const Name &prefix, const Interest &interest, StatusDatasetContext &context)> StatusDatasetHandler
a function to handle a StatusDataset request
Definition: dispatcher.hpp:120