blob: 6eca613f54df3a1591cdaf2cd95086747f0969cc [file] [log] [blame]
Yanbiao Li8ee37ed2015-05-19 12:44:04 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shic542f632017-07-18 14:20:32 +00002/*
Davide Pesavento3c8a8b02018-03-01 14:46:55 -05003 * Copyright (c) 2013-2018 Regents of the University of California.
Yanbiao Li8ee37ed2015-05-19 12:44:04 -07004 *
Alexander Afanasyev80b68e12015-09-17 17:01:04 -07005 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Yanbiao Li8ee37ed2015-05-19 12:44:04 -07006 *
Alexander Afanasyev80b68e12015-09-17 17:01:04 -07007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070010 *
Alexander Afanasyev80b68e12015-09-17 17:01:04 -070011 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070014 *
Alexander Afanasyev80b68e12015-09-17 17:01:04 -070015 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070020 */
21
22#ifndef NDN_MGMT_DISPATCHER_HPP
23#define NDN_MGMT_DISPATCHER_HPP
24
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070025#include "../encoding/block.hpp"
Davide Pesavento3c8a8b02018-03-01 14:46:55 -050026#include "../face.hpp"
Junxiao Shic542f632017-07-18 14:20:32 +000027#include "../ims/in-memory-storage-fifo.hpp"
Davide Pesavento3c8a8b02018-03-01 14:46:55 -050028#include "../security/key-chain.hpp"
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070029#include "control-response.hpp"
30#include "control-parameters.hpp"
31#include "status-dataset-context.hpp"
32
33#include <unordered_map>
34
35namespace ndn {
36namespace mgmt {
37
38// ---- AUTHORIZATION ----
39
40/** \brief a function to be called if authorization is successful
41 * \param requester a string that indicates the requester, whose semantics is determined by
42 * the Authorization function; this value is intended for logging only,
43 * and should not affect how the request is processed
44 */
45typedef std::function<void(const std::string& requester)> AcceptContinuation;
46
47/** \brief indicate how to reply in case authorization is rejected
48 */
49enum class RejectReply {
50 /** \brief do not reply
51 */
52 SILENT,
53 /** \brief reply with a ControlResponse where StatusCode is 403
54 */
55 STATUS403
56};
57
58/** \brief a function to be called if authorization is rejected
59 */
Davide Pesavento3c8a8b02018-03-01 14:46:55 -050060typedef std::function<void(RejectReply reply)> RejectContinuation;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070061
62/** \brief a function that performs authorization
63 * \param prefix top-level prefix, e.g., "/localhost/nfd";
64 * This argument can be inspected to allow Interests only under a subset of
65 * top-level prefixes (e.g., allow "/localhost/nfd" only),
66 * or to use different trust model regarding to the prefix.
67 * \param interest incoming Interest
68 * \param params parsed ControlParameters for ControlCommand, otherwise nullptr;
69 * This is guaranteed to be not-null and have correct type for the command,
70 * but may not be valid (e.g., can have missing fields).
71 *
72 * Either accept or reject must be called after authorization completes.
73 */
74typedef std::function<void(const Name& prefix, const Interest& interest,
75 const ControlParameters* params,
Junxiao Shif65a3362015-09-06 20:54:54 -070076 const AcceptContinuation& accept,
77 const RejectContinuation& reject)> Authorization;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070078
Davide Pesavento3c8a8b02018-03-01 14:46:55 -050079/** \brief return an Authorization that accepts all Interests, with empty string as requester
Yanbiao Li8ee37ed2015-05-19 12:44:04 -070080 */
81Authorization
82makeAcceptAllAuthorization();
83
84// ---- CONTROL COMMAND ----
85
86/** \brief a function to validate input ControlParameters
87 * \param params parsed ControlParameters;
88 * This is guaranteed to have correct type for the command.
89 */
90typedef std::function<bool(const ControlParameters& params)> ValidateParameters;
91
92/** \brief a function to be called after ControlCommandHandler completes
93 * \param resp the response to be sent to requester
94 */
95typedef std::function<void(const ControlResponse& resp)> CommandContinuation;
96
97/** \brief a function to handle an authorized ControlCommand
98 * \param prefix top-level prefix, e.g., "/localhost/nfd";
99 * \param interest incoming Interest
100 * \param params parsed ControlParameters;
101 * This is guaranteed to have correct type for the command,
102 * and is valid (e.g., has all required fields).
103 */
104typedef std::function<void(const Name& prefix, const Interest& interest,
105 const ControlParameters& params,
Junxiao Shif65a3362015-09-06 20:54:54 -0700106 const CommandContinuation& done)> ControlCommandHandler;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700107
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500108// ---- STATUS DATASET ----
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700109
110/** \brief a function to handle a StatusDataset request
111 * \param prefix top-level prefix, e.g., "/localhost/nfd";
112 * \param interest incoming Interest; its Name doesn't contain version and segment components
113 *
114 * This function can generate zero or more blocks and pass them to \p append,
115 * and must call \p end upon completion.
116 */
117typedef std::function<void(const Name& prefix, const Interest& interest,
118 StatusDatasetContext& context)> StatusDatasetHandler;
119
120//---- NOTIFICATION STREAM ----
121
122/** \brief a function to post a notification
123 */
124typedef std::function<void(const Block& notification)> PostNotification;
125
126// ---- DISPATCHER ----
127
128/** \brief represents a dispatcher on server side of NFD Management protocol
129 */
130class Dispatcher : noncopyable
131{
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700132public:
133 /** \brief constructor
134 * \param face the Face on which the dispatcher operates
135 * \param keyChain a KeyChain to sign Data
136 * \param signingInfo signing parameters to sign Data with \p keyChain
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800137 * \param imsCapacity capacity of the internal InMemoryStorage used by dispatcher
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700138 */
Alexander Afanasyev80782e02017-01-04 13:16:54 -0800139 Dispatcher(Face& face, KeyChain& keyChain,
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800140 const security::SigningInfo& signingInfo = security::SigningInfo(),
141 size_t imsCapacity = 256);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700142
143 virtual
144 ~Dispatcher();
145
146 /** \brief add a top-level prefix
147 * \param prefix a top-level prefix, e.g., "/localhost/nfd"
148 * \param wantRegister whether prefix registration should be performed through the Face
149 * \param signingInfo signing parameters to sign the prefix registration command
150 * \throw std::out_of_range \p prefix overlaps with an existing top-level prefix
151 *
152 * Procedure for adding a top-level prefix:
153 * 1. if the new top-level prefix overlaps with an existing top-level prefix
154 * (one top-level prefix is a prefix of another top-level prefix), throw std::domain_error
155 * 2. if wantRegister is true, invoke face.registerPrefix for the top-level prefix;
156 * the returned RegisteredPrefixId shall be recorded internally, indexed by the top-level
157 * prefix
158 * 3. foreach relPrefix from ControlCommands and StatusDatasets,
159 * join the top-level prefix with the relPrefix to obtain the full prefix,
160 * and invoke non-registering overload of face.setInterestFilter,
161 * with the InterestHandler set to an appropriate private method to handle incoming Interests
162 * for the ControlCommand or StatusDataset;
163 * the returned InterestFilterId shall be recorded internally, indexed by the top-level
164 * prefix
165 */
166 void
167 addTopPrefix(const Name& prefix, bool wantRegister = true,
168 const security::SigningInfo& signingInfo = security::SigningInfo());
169
170 /** \brief remove a top-level prefix
171 * \param prefix a top-level prefix, e.g., "/localhost/nfd"
172 *
173 * Procedure for removing a top-level prefix:
174 * 1. if the top-level prefix has not been added, abort these steps
175 * 2. if the top-level prefix has been added with wantRegister,
176 * invoke face.unregisterPrefix with the RegisteredPrefixId
177 * 3. foreach InterestFilterId recorded during addTopPrefix,
178 * invoke face.unsetInterestFilter with the InterestFilterId
179 */
180 void
181 removeTopPrefix(const Name& prefix);
182
183public: // ControlCommand
184 /** \brief register a ControlCommand
185 * \tparam CP subclass of ControlParameters used by this command
186 * \param relPrefix a prefix for this command, e.g., "faces/create";
187 * relPrefixes in ControlCommands, StatusDatasets, NotificationStreams must be
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500188 * non-overlapping (no relPrefix is a prefix of another relPrefix)
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400189 * \param authorize Callback to authorize the incoming commands
190 * \param validate Callback to validate parameters of the incoming commands
191 * \param handle Callback to handle the commands
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700192 * \pre no top-level prefix has been added
193 * \throw std::out_of_range \p relPrefix overlaps with an existing relPrefix
194 * \throw std::domain_error one or more top-level prefix has been added
195 *
196 * Procedure for processing a ControlCommand:
197 * 1. extract the NameComponent containing ControlParameters (the component after relPrefix),
198 * and parse ControlParameters into type CP; if parsing fails, abort these steps
199 * 2. perform authorization; if authorization is rejected,
200 * perform the RejectReply action, and abort these steps
201 * 3. validate ControlParameters; if validation fails,
202 * make ControlResponse with StatusCode 400, and go to step 5
203 * 4. invoke handler, wait until CommandContinuation is called
204 * 5. encode the ControlResponse into one Data packet
205 * 6. sign the Data packet
206 * 7. if the Data packet is too large, abort these steps and log an error
207 * 8. send the signed Data packet
208 */
209 template<typename CP>
210 void
211 addControlCommand(const PartialName& relPrefix,
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400212 Authorization authorize,
213 ValidateParameters validate,
214 ControlCommandHandler handle);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700215
216public: // StatusDataset
217 /** \brief register a StatusDataset or a prefix under which StatusDatasets can be requested
218 * \param relPrefix a prefix for this dataset, e.g., "faces/list";
219 * relPrefixes in ControlCommands, StatusDatasets, NotificationStreams must be
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500220 * non-overlapping (no relPrefix is a prefix of another relPrefix)
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400221 * \param authorize should set identity to Name() if the dataset is public
222 * \param handle Callback to process the incoming dataset requests
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700223 * \pre no top-level prefix has been added
224 * \throw std::out_of_range \p relPrefix overlaps with an existing relPrefix
225 * \throw std::domain_error one or more top-level prefix has been added
226 *
227 * The payload of the returned status dataset data packet is at most half of the maximum
228 * data packet size.
229 *
230 * Procedure for processing a StatusDataset request:
231 * 1. if the request Interest contains version or segment components, abort these steps;
232 * note: the request may contain more components after relPrefix, e.g., a query condition
233 * 2. perform authorization; if authorization is rejected,
234 * perform the RejectReply action, and abort these steps
235 * 3. invoke handler, store blocks passed to StatusDatasetAppend calls in a buffer,
236 * wait until StatusDatasetEnd is called
237 * 4. allocate a version
238 * 5. segment the buffer into one or more segments under the allocated version,
239 * such that the Data packets will not become too large after signing
240 * 6. set FinalBlockId on at least the last segment
241 * 7. sign the Data packets
242 * 8. send the signed Data packets
243 *
244 * As an optimization, a Data packet may be sent as soon as enough octets have been collected
245 * through StatusDatasetAppend calls.
246 */
247 void
248 addStatusDataset(const PartialName& relPrefix,
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400249 Authorization authorize,
250 StatusDatasetHandler handle);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700251
252public: // NotificationStream
253 /** \brief register a NotificationStream
254 * \param relPrefix a prefix for this notification stream, e.g., "faces/events";
255 * relPrefixes in ControlCommands, StatusDatasets, NotificationStreams must be
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500256 * non-overlapping (no relPrefix is a prefix of another relPrefix)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700257 * \return a function into which notifications can be posted
258 * \pre no top-level prefix has been added
259 * \throw std::out_of_range \p relPrefix overlaps with an existing relPrefix
260 * \throw std::domain_error one or more top-level prefix has been added
261 *
262 * Procedure for posting a notification:
263 * 1. if no top-level prefix has been added, or more than one top-level prefixes have been
264 * added,
265 * abort these steps and log an error
266 * 2. assign the next sequence number to the notification
267 * 3. place the notification block into one Data packet under the sole top-level prefix
268 * 4. sign the Data packet
269 * 5. if the Data packet is too large, abort these steps and log an error
270 * 6. send the signed Data packet
271 */
272 PostNotification
273 addNotificationStream(const PartialName& relPrefix);
274
275private:
276 typedef std::function<void(const Name& prefix,
277 const Interest& interest)> InterestHandler;
278
279 typedef std::function<void(const std::string& requester,
280 const Name& prefix,
281 const Interest& interest,
Junxiao Shid97c9532017-04-27 16:17:04 +0000282 const shared_ptr<ControlParameters>&)> AuthorizationAcceptedCallback;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700283
284 typedef std::function<void(RejectReply act,
285 const Interest& interest)> AuthorizationRejectedCallback;
286
287 /**
288 * @brief the parser of extracting control parameters from name component.
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500289 * @param comp name component that may encode control parameters.
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700290 * @return a shared pointer to the extracted control parameters.
291 * @throw tlv::Error if the NameComponent cannot be parsed as ControlParameters
292 */
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500293 typedef std::function<shared_ptr<ControlParameters>(const name::Component& comp)> ControlParametersParser;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700294
295 bool
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500296 isOverlappedWithOthers(const PartialName& relPrefix) const;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700297
298 /**
299 * @brief process unauthorized request
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700300 * @param act action to reply
301 * @param interest the incoming Interest
302 */
303 void
304 afterAuthorizationRejected(RejectReply act, const Interest& interest);
305
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800306 /**
307 * @brief query Data the in-memory storage by a given Interest
308 *
309 * if the query fails, invoke @p missContinuation to process @p interest.
310 *
311 * @param prefix the top-level prefix
312 * @param interest the request
313 * @param missContinuation the handler of request when the query fails
314 */
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700315 void
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800316 queryStorage(const Name& prefix, const Interest& interest, const InterestHandler& missContinuation);
317
318 enum class SendDestination {
319 NONE = 0,
320 FACE = 1,
321 IMS = 2,
322 FACE_AND_IMS = 3
323 };
324
325 /**
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500326 * @brief send data to the face and/or in-memory storage
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800327 *
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500328 * Create a Data packet with the given @p dataName, @p content, and @p metaInfo,
329 * set its FreshnessPeriod to DEFAULT_FRESHNESS_PERIOD, and then send it out through
330 * the face and/or insert it into the in-memory storage as specified in @p destination.
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800331 *
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500332 * If it's toward the in-memory storage, set its CachePolicy to NO_CACHE and limit
333 * its FreshnessPeriod in the storage to @p imsFresh.
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800334 *
335 * @param dataName the name of this piece of data
336 * @param content the content of this piece of data
337 * @param metaInfo some meta information of this piece of data
338 * @param destination where to send this piece of data
339 * @param imsFresh freshness period of this piece of data in in-memory storage
340 */
341 void
342 sendData(const Name& dataName, const Block& content, const MetaInfo& metaInfo,
343 SendDestination destination, time::milliseconds imsFresh);
344
345 /**
346 * @brief send out a data packt through the face
347 *
348 * @param data the data packet to insert
349 */
350 void
351 sendOnFace(const Data& data);
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700352
353 /**
354 * @brief process the control-command Interest before authorization.
355 *
356 * @param prefix the top-level prefix
357 * @param relPrefix the relative prefix
358 * @param interest the incoming Interest
359 * @param parser to extract control parameters from the \p interest
360 * @param authorization to process validation on this command
361 * @param accepted the callback for successful authorization
362 * @param rejected the callback for failed authorization
363 */
364 void
365 processControlCommandInterest(const Name& prefix,
366 const Name& relPrefix,
367 const Interest& interest,
368 const ControlParametersParser& parser,
369 const Authorization& authorization,
370 const AuthorizationAcceptedCallback& accepted,
371 const AuthorizationRejectedCallback& rejected);
372
373 /**
374 * @brief process the authorized control-command.
375 *
376 * @param requester the requester
377 * @param prefix the top-level prefix
378 * @param interest the incoming Interest
379 * @param parameters control parameters of this command
380 * @param validate to validate control parameters
381 * @param handler to process this command
382 */
383 void
384 processAuthorizedControlCommandInterest(const std::string& requester,
385 const Name& prefix,
386 const Interest& interest,
Junxiao Shid97c9532017-04-27 16:17:04 +0000387 const shared_ptr<ControlParameters>& parameters,
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700388 const ValidateParameters& validate,
389 const ControlCommandHandler& handler);
390
391 void
392 sendControlResponse(const ControlResponse& resp, const Interest& interest, bool isNack = false);
393
394 /**
395 * @brief process the status-dataset Interest before authorization.
396 *
397 * @param prefix the top-level prefix
398 * @param interest the incoming Interest
399 * @param authorization to process verification
400 * @param accepted callback for successful authorization
401 * @param rejected callback for failed authorization
402 */
403 void
404 processStatusDatasetInterest(const Name& prefix,
405 const Interest& interest,
406 const Authorization& authorization,
407 const AuthorizationAcceptedCallback& accepted,
408 const AuthorizationRejectedCallback& rejected);
409
410 /**
411 * @brief process the authorized status-dataset request
412 *
413 * @param requester the requester
414 * @param prefix the top-level prefix
415 * @param interest the incoming Interest
416 * @param handler to process this request
417 */
418 void
419 processAuthorizedStatusDatasetInterest(const std::string& requester,
420 const Name& prefix,
421 const Interest& interest,
422 const StatusDatasetHandler& handler);
423
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800424 /**
425 * @brief send a segment of StatusDataset
426 *
427 * @param dataName the name of this piece of data
428 * @param content the content of this piece of data
429 * @param imsFresh the freshness period of this piece of data in the in-memory storage
430 * @param isFinalBlock indicates whether this piece of data is the final block
431 */
432 void
433 sendStatusDatasetSegment(const Name& dataName, const Block& content,
434 time::milliseconds imsFresh, bool isFinalBlock);
435
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700436 void
437 postNotification(const Block& notification, const PartialName& relPrefix);
438
439private:
440 struct TopPrefixEntry
441 {
442 Name topPrefix;
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400443 optional<const RegisteredPrefixId*> registeredPrefixId;
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500444 std::vector<const InterestFilterId*> interestFilters;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700445 };
446 std::unordered_map<Name, TopPrefixEntry> m_topLevelPrefixes;
447
448 Face& m_face;
Alexander Afanasyev80782e02017-01-04 13:16:54 -0800449 KeyChain& m_keyChain;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700450 security::SigningInfo m_signingInfo;
451
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500452 std::unordered_map<PartialName, InterestHandler> m_handlers;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700453
454 // NotificationStream name => next sequence number
455 std::unordered_map<Name, uint64_t> m_streams;
Yanbiao Li4b4f7542016-03-11 02:04:43 +0800456
457NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Junxiao Shic542f632017-07-18 14:20:32 +0000458 InMemoryStorageFifo m_storage;
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700459};
460
461template<typename CP>
462void
463Dispatcher::addControlCommand(const PartialName& relPrefix,
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400464 Authorization authorize,
465 ValidateParameters validate,
466 ControlCommandHandler handle)
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700467{
468 if (!m_topLevelPrefixes.empty()) {
Junxiao Shid97c9532017-04-27 16:17:04 +0000469 BOOST_THROW_EXCEPTION(std::domain_error("one or more top-level prefix has been added"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700470 }
471
472 if (isOverlappedWithOthers(relPrefix)) {
Junxiao Shid97c9532017-04-27 16:17:04 +0000473 BOOST_THROW_EXCEPTION(std::out_of_range("relPrefix overlaps with another relPrefix"));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700474 }
475
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400476 auto parser = [] (const name::Component& comp) -> shared_ptr<ControlParameters> {
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500477 return make_shared<CP>(comp.blockFromValue());
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700478 };
479
480 AuthorizationAcceptedCallback accepted =
481 bind(&Dispatcher::processAuthorizedControlCommandInterest, this,
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400482 _1, _2, _3, _4, std::move(validate), std::move(handle));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700483
484 AuthorizationRejectedCallback rejected =
485 bind(&Dispatcher::afterAuthorizationRejected, this, _1, _2);
486
487 m_handlers[relPrefix] = bind(&Dispatcher::processControlCommandInterest, this,
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400488 _1, relPrefix, _2, std::move(parser), std::move(authorize),
489 std::move(accepted), std::move(rejected));
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700490}
491
492} // namespace mgmt
493} // namespace ndn
Davide Pesavento3c8a8b02018-03-01 14:46:55 -0500494
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700495#endif // NDN_MGMT_DISPATCHER_HPP