Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
Junxiao Shi | c542f63 | 2017-07-18 14:20:32 +0000 | [diff] [blame^] | 2 | /* |
Alexander Afanasyev | 4c9a3d5 | 2017-01-03 17:45:19 -0800 | [diff] [blame] | 3 | * Copyright (c) 2013-2017 Regents of the University of California. |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 4 | * |
Alexander Afanasyev | 80b68e1 | 2015-09-17 17:01:04 -0700 | [diff] [blame] | 5 | * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 6 | * |
Alexander Afanasyev | 80b68e1 | 2015-09-17 17:01:04 -0700 | [diff] [blame] | 7 | * 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 Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 10 | * |
Alexander Afanasyev | 80b68e1 | 2015-09-17 17:01:04 -0700 | [diff] [blame] | 11 | * 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 Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 14 | * |
Alexander Afanasyev | 80b68e1 | 2015-09-17 17:01:04 -0700 | [diff] [blame] | 15 | * 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 Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 20 | */ |
| 21 | |
| 22 | #ifndef NDN_MGMT_DISPATCHER_HPP |
| 23 | #define NDN_MGMT_DISPATCHER_HPP |
| 24 | |
| 25 | #include "../face.hpp" |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 26 | #include "../encoding/block.hpp" |
Junxiao Shi | c542f63 | 2017-07-18 14:20:32 +0000 | [diff] [blame^] | 27 | #include "../security/key-chain.hpp" |
| 28 | #include "../ims/in-memory-storage-fifo.hpp" |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 29 | #include "control-response.hpp" |
| 30 | #include "control-parameters.hpp" |
| 31 | #include "status-dataset-context.hpp" |
| 32 | |
| 33 | #include <unordered_map> |
| 34 | |
| 35 | namespace ndn { |
| 36 | namespace 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 | */ |
| 45 | typedef std::function<void(const std::string& requester)> AcceptContinuation; |
| 46 | |
| 47 | /** \brief indicate how to reply in case authorization is rejected |
| 48 | */ |
| 49 | enum 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 | */ |
| 60 | typedef std::function<void(RejectReply act)> RejectContinuation; |
| 61 | |
| 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 | */ |
| 74 | typedef std::function<void(const Name& prefix, const Interest& interest, |
| 75 | const ControlParameters* params, |
Junxiao Shi | f65a336 | 2015-09-06 20:54:54 -0700 | [diff] [blame] | 76 | const AcceptContinuation& accept, |
| 77 | const RejectContinuation& reject)> Authorization; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 78 | |
| 79 | /** \return an Authorization that accepts all Interests, with empty string as requester |
| 80 | */ |
| 81 | Authorization |
| 82 | makeAcceptAllAuthorization(); |
| 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 | */ |
| 90 | typedef 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 | */ |
| 95 | typedef 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 | */ |
| 104 | typedef std::function<void(const Name& prefix, const Interest& interest, |
| 105 | const ControlParameters& params, |
Junxiao Shi | f65a336 | 2015-09-06 20:54:54 -0700 | [diff] [blame] | 106 | const CommandContinuation& done)> ControlCommandHandler; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 107 | |
| 108 | |
| 109 | /** \brief a function to handle a StatusDataset request |
| 110 | * \param prefix top-level prefix, e.g., "/localhost/nfd"; |
| 111 | * \param interest incoming Interest; its Name doesn't contain version and segment components |
| 112 | * |
| 113 | * This function can generate zero or more blocks and pass them to \p append, |
| 114 | * and must call \p end upon completion. |
| 115 | */ |
| 116 | typedef std::function<void(const Name& prefix, const Interest& interest, |
| 117 | StatusDatasetContext& context)> StatusDatasetHandler; |
| 118 | |
| 119 | //---- NOTIFICATION STREAM ---- |
| 120 | |
| 121 | /** \brief a function to post a notification |
| 122 | */ |
| 123 | typedef std::function<void(const Block& notification)> PostNotification; |
| 124 | |
| 125 | // ---- DISPATCHER ---- |
| 126 | |
| 127 | /** \brief represents a dispatcher on server side of NFD Management protocol |
| 128 | */ |
| 129 | class Dispatcher : noncopyable |
| 130 | { |
| 131 | class Error : public std::runtime_error |
| 132 | { |
| 133 | public: |
| 134 | explicit |
| 135 | Error(const std::string& what) |
| 136 | : std::runtime_error(what) |
| 137 | { |
| 138 | } |
| 139 | }; |
| 140 | |
| 141 | public: |
| 142 | /** \brief constructor |
| 143 | * \param face the Face on which the dispatcher operates |
| 144 | * \param keyChain a KeyChain to sign Data |
| 145 | * \param signingInfo signing parameters to sign Data with \p keyChain |
Yanbiao Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 146 | * \param imsCapacity capacity of the internal InMemoryStorage used by dispatcher |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 147 | */ |
Alexander Afanasyev | 80782e0 | 2017-01-04 13:16:54 -0800 | [diff] [blame] | 148 | Dispatcher(Face& face, KeyChain& keyChain, |
Yanbiao Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 149 | const security::SigningInfo& signingInfo = security::SigningInfo(), |
| 150 | size_t imsCapacity = 256); |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 151 | |
| 152 | virtual |
| 153 | ~Dispatcher(); |
| 154 | |
| 155 | /** \brief add a top-level prefix |
| 156 | * \param prefix a top-level prefix, e.g., "/localhost/nfd" |
| 157 | * \param wantRegister whether prefix registration should be performed through the Face |
| 158 | * \param signingInfo signing parameters to sign the prefix registration command |
| 159 | * \throw std::out_of_range \p prefix overlaps with an existing top-level prefix |
| 160 | * |
| 161 | * Procedure for adding a top-level prefix: |
| 162 | * 1. if the new top-level prefix overlaps with an existing top-level prefix |
| 163 | * (one top-level prefix is a prefix of another top-level prefix), throw std::domain_error |
| 164 | * 2. if wantRegister is true, invoke face.registerPrefix for the top-level prefix; |
| 165 | * the returned RegisteredPrefixId shall be recorded internally, indexed by the top-level |
| 166 | * prefix |
| 167 | * 3. foreach relPrefix from ControlCommands and StatusDatasets, |
| 168 | * join the top-level prefix with the relPrefix to obtain the full prefix, |
| 169 | * and invoke non-registering overload of face.setInterestFilter, |
| 170 | * with the InterestHandler set to an appropriate private method to handle incoming Interests |
| 171 | * for the ControlCommand or StatusDataset; |
| 172 | * the returned InterestFilterId shall be recorded internally, indexed by the top-level |
| 173 | * prefix |
| 174 | */ |
| 175 | void |
| 176 | addTopPrefix(const Name& prefix, bool wantRegister = true, |
| 177 | const security::SigningInfo& signingInfo = security::SigningInfo()); |
| 178 | |
| 179 | /** \brief remove a top-level prefix |
| 180 | * \param prefix a top-level prefix, e.g., "/localhost/nfd" |
| 181 | * |
| 182 | * Procedure for removing a top-level prefix: |
| 183 | * 1. if the top-level prefix has not been added, abort these steps |
| 184 | * 2. if the top-level prefix has been added with wantRegister, |
| 185 | * invoke face.unregisterPrefix with the RegisteredPrefixId |
| 186 | * 3. foreach InterestFilterId recorded during addTopPrefix, |
| 187 | * invoke face.unsetInterestFilter with the InterestFilterId |
| 188 | */ |
| 189 | void |
| 190 | removeTopPrefix(const Name& prefix); |
| 191 | |
| 192 | public: // ControlCommand |
| 193 | /** \brief register a ControlCommand |
| 194 | * \tparam CP subclass of ControlParameters used by this command |
| 195 | * \param relPrefix a prefix for this command, e.g., "faces/create"; |
| 196 | * relPrefixes in ControlCommands, StatusDatasets, NotificationStreams must be |
| 197 | * non-overlapping |
| 198 | * (no relPrefix is a prefix of another relPrefix) |
Alexander Afanasyev | f2a4622 | 2015-09-17 18:01:30 -0700 | [diff] [blame] | 199 | * \param authorization Callback to authorize the incoming commands |
| 200 | * \param validateParams Callback to validate parameters of the incoming commands |
| 201 | * \param handler Callback to handle the commands |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 202 | * \pre no top-level prefix has been added |
| 203 | * \throw std::out_of_range \p relPrefix overlaps with an existing relPrefix |
| 204 | * \throw std::domain_error one or more top-level prefix has been added |
| 205 | * |
| 206 | * Procedure for processing a ControlCommand: |
| 207 | * 1. extract the NameComponent containing ControlParameters (the component after relPrefix), |
| 208 | * and parse ControlParameters into type CP; if parsing fails, abort these steps |
| 209 | * 2. perform authorization; if authorization is rejected, |
| 210 | * perform the RejectReply action, and abort these steps |
| 211 | * 3. validate ControlParameters; if validation fails, |
| 212 | * make ControlResponse with StatusCode 400, and go to step 5 |
| 213 | * 4. invoke handler, wait until CommandContinuation is called |
| 214 | * 5. encode the ControlResponse into one Data packet |
| 215 | * 6. sign the Data packet |
| 216 | * 7. if the Data packet is too large, abort these steps and log an error |
| 217 | * 8. send the signed Data packet |
| 218 | */ |
| 219 | template<typename CP> |
| 220 | void |
| 221 | addControlCommand(const PartialName& relPrefix, |
Junxiao Shi | f65a336 | 2015-09-06 20:54:54 -0700 | [diff] [blame] | 222 | const Authorization& authorization, |
| 223 | const ValidateParameters& validateParams, |
| 224 | const ControlCommandHandler& handler); |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 225 | |
| 226 | public: // StatusDataset |
| 227 | /** \brief register a StatusDataset or a prefix under which StatusDatasets can be requested |
| 228 | * \param relPrefix a prefix for this dataset, e.g., "faces/list"; |
| 229 | * relPrefixes in ControlCommands, StatusDatasets, NotificationStreams must be |
| 230 | * non-overlapping |
| 231 | * (no relPrefix is a prefix of another relPrefix) |
| 232 | * \param authorization should set identity to Name() if the dataset is public |
Alexander Afanasyev | f2a4622 | 2015-09-17 18:01:30 -0700 | [diff] [blame] | 233 | * \param handler Callback to process the incoming dataset requests |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 234 | * \pre no top-level prefix has been added |
| 235 | * \throw std::out_of_range \p relPrefix overlaps with an existing relPrefix |
| 236 | * \throw std::domain_error one or more top-level prefix has been added |
| 237 | * |
| 238 | * The payload of the returned status dataset data packet is at most half of the maximum |
| 239 | * data packet size. |
| 240 | * |
| 241 | * Procedure for processing a StatusDataset request: |
| 242 | * 1. if the request Interest contains version or segment components, abort these steps; |
| 243 | * note: the request may contain more components after relPrefix, e.g., a query condition |
| 244 | * 2. perform authorization; if authorization is rejected, |
| 245 | * perform the RejectReply action, and abort these steps |
| 246 | * 3. invoke handler, store blocks passed to StatusDatasetAppend calls in a buffer, |
| 247 | * wait until StatusDatasetEnd is called |
| 248 | * 4. allocate a version |
| 249 | * 5. segment the buffer into one or more segments under the allocated version, |
| 250 | * such that the Data packets will not become too large after signing |
| 251 | * 6. set FinalBlockId on at least the last segment |
| 252 | * 7. sign the Data packets |
| 253 | * 8. send the signed Data packets |
| 254 | * |
| 255 | * As an optimization, a Data packet may be sent as soon as enough octets have been collected |
| 256 | * through StatusDatasetAppend calls. |
| 257 | */ |
| 258 | void |
| 259 | addStatusDataset(const PartialName& relPrefix, |
Junxiao Shi | f65a336 | 2015-09-06 20:54:54 -0700 | [diff] [blame] | 260 | const Authorization& authorization, |
| 261 | const StatusDatasetHandler& handler); |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 262 | |
| 263 | public: // NotificationStream |
| 264 | /** \brief register a NotificationStream |
| 265 | * \param relPrefix a prefix for this notification stream, e.g., "faces/events"; |
| 266 | * relPrefixes in ControlCommands, StatusDatasets, NotificationStreams must be |
| 267 | * non-overlapping |
| 268 | * (no relPrefix is a prefix of another relPrefix) |
| 269 | * \return a function into which notifications can be posted |
| 270 | * \pre no top-level prefix has been added |
| 271 | * \throw std::out_of_range \p relPrefix overlaps with an existing relPrefix |
| 272 | * \throw std::domain_error one or more top-level prefix has been added |
| 273 | * |
| 274 | * Procedure for posting a notification: |
| 275 | * 1. if no top-level prefix has been added, or more than one top-level prefixes have been |
| 276 | * added, |
| 277 | * abort these steps and log an error |
| 278 | * 2. assign the next sequence number to the notification |
| 279 | * 3. place the notification block into one Data packet under the sole top-level prefix |
| 280 | * 4. sign the Data packet |
| 281 | * 5. if the Data packet is too large, abort these steps and log an error |
| 282 | * 6. send the signed Data packet |
| 283 | */ |
| 284 | PostNotification |
| 285 | addNotificationStream(const PartialName& relPrefix); |
| 286 | |
| 287 | private: |
| 288 | typedef std::function<void(const Name& prefix, |
| 289 | const Interest& interest)> InterestHandler; |
| 290 | |
| 291 | typedef std::function<void(const std::string& requester, |
| 292 | const Name& prefix, |
| 293 | const Interest& interest, |
Junxiao Shi | d97c953 | 2017-04-27 16:17:04 +0000 | [diff] [blame] | 294 | const shared_ptr<ControlParameters>&)> AuthorizationAcceptedCallback; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 295 | |
| 296 | typedef std::function<void(RejectReply act, |
| 297 | const Interest& interest)> AuthorizationRejectedCallback; |
| 298 | |
| 299 | /** |
| 300 | * @brief the parser of extracting control parameters from name component. |
| 301 | * |
| 302 | * @param component name component that may encode control parameters. |
| 303 | * @return a shared pointer to the extracted control parameters. |
| 304 | * @throw tlv::Error if the NameComponent cannot be parsed as ControlParameters |
| 305 | */ |
| 306 | typedef std::function<shared_ptr<ControlParameters>(const name::Component& component)> |
| 307 | ControlParametersParser; |
| 308 | |
| 309 | bool |
| 310 | isOverlappedWithOthers(const PartialName& relPrefix); |
| 311 | |
| 312 | /** |
| 313 | * @brief process unauthorized request |
| 314 | * |
| 315 | * @param act action to reply |
| 316 | * @param interest the incoming Interest |
| 317 | */ |
| 318 | void |
| 319 | afterAuthorizationRejected(RejectReply act, const Interest& interest); |
| 320 | |
Yanbiao Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 321 | /** |
| 322 | * @brief query Data the in-memory storage by a given Interest |
| 323 | * |
| 324 | * if the query fails, invoke @p missContinuation to process @p interest. |
| 325 | * |
| 326 | * @param prefix the top-level prefix |
| 327 | * @param interest the request |
| 328 | * @param missContinuation the handler of request when the query fails |
| 329 | */ |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 330 | void |
Yanbiao Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 331 | queryStorage(const Name& prefix, const Interest& interest, const InterestHandler& missContinuation); |
| 332 | |
| 333 | enum class SendDestination { |
| 334 | NONE = 0, |
| 335 | FACE = 1, |
| 336 | IMS = 2, |
| 337 | FACE_AND_IMS = 3 |
| 338 | }; |
| 339 | |
| 340 | /** |
| 341 | * @brief send data to the face or in-memory storage |
| 342 | * |
| 343 | * create a data packet with the given @p dataName, @p content, and @p metaInfo, |
| 344 | * set its FreshnessPeriod to DEFAULT_FRESHNESS_PERIOD, and then send it out through the face and/or |
| 345 | * insert it into the in-memory storage as specified in @p option. |
| 346 | * |
| 347 | * if it's toward the in-memory storage, set its CachePolicy to NO_CACHE and limit |
| 348 | * its FreshnessPeriod in the storage as @p imsFresh |
| 349 | * |
| 350 | * @param dataName the name of this piece of data |
| 351 | * @param content the content of this piece of data |
| 352 | * @param metaInfo some meta information of this piece of data |
| 353 | * @param destination where to send this piece of data |
| 354 | * @param imsFresh freshness period of this piece of data in in-memory storage |
| 355 | */ |
| 356 | void |
| 357 | sendData(const Name& dataName, const Block& content, const MetaInfo& metaInfo, |
| 358 | SendDestination destination, time::milliseconds imsFresh); |
| 359 | |
| 360 | /** |
| 361 | * @brief send out a data packt through the face |
| 362 | * |
| 363 | * @param data the data packet to insert |
| 364 | */ |
| 365 | void |
| 366 | sendOnFace(const Data& data); |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 367 | |
| 368 | /** |
| 369 | * @brief process the control-command Interest before authorization. |
| 370 | * |
| 371 | * @param prefix the top-level prefix |
| 372 | * @param relPrefix the relative prefix |
| 373 | * @param interest the incoming Interest |
| 374 | * @param parser to extract control parameters from the \p interest |
| 375 | * @param authorization to process validation on this command |
| 376 | * @param accepted the callback for successful authorization |
| 377 | * @param rejected the callback for failed authorization |
| 378 | */ |
| 379 | void |
| 380 | processControlCommandInterest(const Name& prefix, |
| 381 | const Name& relPrefix, |
| 382 | const Interest& interest, |
| 383 | const ControlParametersParser& parser, |
| 384 | const Authorization& authorization, |
| 385 | const AuthorizationAcceptedCallback& accepted, |
| 386 | const AuthorizationRejectedCallback& rejected); |
| 387 | |
| 388 | /** |
| 389 | * @brief process the authorized control-command. |
| 390 | * |
| 391 | * @param requester the requester |
| 392 | * @param prefix the top-level prefix |
| 393 | * @param interest the incoming Interest |
| 394 | * @param parameters control parameters of this command |
| 395 | * @param validate to validate control parameters |
| 396 | * @param handler to process this command |
| 397 | */ |
| 398 | void |
| 399 | processAuthorizedControlCommandInterest(const std::string& requester, |
| 400 | const Name& prefix, |
| 401 | const Interest& interest, |
Junxiao Shi | d97c953 | 2017-04-27 16:17:04 +0000 | [diff] [blame] | 402 | const shared_ptr<ControlParameters>& parameters, |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 403 | const ValidateParameters& validate, |
| 404 | const ControlCommandHandler& handler); |
| 405 | |
| 406 | void |
| 407 | sendControlResponse(const ControlResponse& resp, const Interest& interest, bool isNack = false); |
| 408 | |
| 409 | /** |
| 410 | * @brief process the status-dataset Interest before authorization. |
| 411 | * |
| 412 | * @param prefix the top-level prefix |
| 413 | * @param interest the incoming Interest |
| 414 | * @param authorization to process verification |
| 415 | * @param accepted callback for successful authorization |
| 416 | * @param rejected callback for failed authorization |
| 417 | */ |
| 418 | void |
| 419 | processStatusDatasetInterest(const Name& prefix, |
| 420 | const Interest& interest, |
| 421 | const Authorization& authorization, |
| 422 | const AuthorizationAcceptedCallback& accepted, |
| 423 | const AuthorizationRejectedCallback& rejected); |
| 424 | |
| 425 | /** |
| 426 | * @brief process the authorized status-dataset request |
| 427 | * |
| 428 | * @param requester the requester |
| 429 | * @param prefix the top-level prefix |
| 430 | * @param interest the incoming Interest |
| 431 | * @param handler to process this request |
| 432 | */ |
| 433 | void |
| 434 | processAuthorizedStatusDatasetInterest(const std::string& requester, |
| 435 | const Name& prefix, |
| 436 | const Interest& interest, |
| 437 | const StatusDatasetHandler& handler); |
| 438 | |
Yanbiao Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 439 | /** |
| 440 | * @brief send a segment of StatusDataset |
| 441 | * |
| 442 | * @param dataName the name of this piece of data |
| 443 | * @param content the content of this piece of data |
| 444 | * @param imsFresh the freshness period of this piece of data in the in-memory storage |
| 445 | * @param isFinalBlock indicates whether this piece of data is the final block |
| 446 | */ |
| 447 | void |
| 448 | sendStatusDatasetSegment(const Name& dataName, const Block& content, |
| 449 | time::milliseconds imsFresh, bool isFinalBlock); |
| 450 | |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 451 | void |
| 452 | postNotification(const Block& notification, const PartialName& relPrefix); |
| 453 | |
| 454 | private: |
| 455 | struct TopPrefixEntry |
| 456 | { |
| 457 | Name topPrefix; |
| 458 | bool wantRegister; |
| 459 | const ndn::RegisteredPrefixId* registerPrefixId; |
| 460 | std::vector<const ndn::InterestFilterId*> interestFilters; |
| 461 | }; |
| 462 | std::unordered_map<Name, TopPrefixEntry> m_topLevelPrefixes; |
| 463 | |
| 464 | Face& m_face; |
Alexander Afanasyev | 80782e0 | 2017-01-04 13:16:54 -0800 | [diff] [blame] | 465 | KeyChain& m_keyChain; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 466 | security::SigningInfo m_signingInfo; |
| 467 | |
| 468 | typedef std::unordered_map<PartialName, InterestHandler> HandlerMap; |
| 469 | typedef HandlerMap::iterator HandlerMapIt; |
| 470 | HandlerMap m_handlers; |
| 471 | |
| 472 | // NotificationStream name => next sequence number |
| 473 | std::unordered_map<Name, uint64_t> m_streams; |
Yanbiao Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 474 | |
| 475 | NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: |
Junxiao Shi | c542f63 | 2017-07-18 14:20:32 +0000 | [diff] [blame^] | 476 | InMemoryStorageFifo m_storage; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 477 | }; |
| 478 | |
| 479 | template<typename CP> |
| 480 | void |
| 481 | Dispatcher::addControlCommand(const PartialName& relPrefix, |
Junxiao Shi | f65a336 | 2015-09-06 20:54:54 -0700 | [diff] [blame] | 482 | const Authorization& authorization, |
| 483 | const ValidateParameters& validateParams, |
| 484 | const ControlCommandHandler& handler) |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 485 | { |
| 486 | if (!m_topLevelPrefixes.empty()) { |
Junxiao Shi | d97c953 | 2017-04-27 16:17:04 +0000 | [diff] [blame] | 487 | BOOST_THROW_EXCEPTION(std::domain_error("one or more top-level prefix has been added")); |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 488 | } |
| 489 | |
| 490 | if (isOverlappedWithOthers(relPrefix)) { |
Junxiao Shi | d97c953 | 2017-04-27 16:17:04 +0000 | [diff] [blame] | 491 | BOOST_THROW_EXCEPTION(std::out_of_range("relPrefix overlaps with another relPrefix")); |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 492 | } |
| 493 | |
| 494 | ControlParametersParser parser = |
| 495 | [] (const name::Component& component) -> shared_ptr<ControlParameters> { |
| 496 | return make_shared<CP>(component.blockFromValue()); |
| 497 | }; |
| 498 | |
| 499 | AuthorizationAcceptedCallback accepted = |
| 500 | bind(&Dispatcher::processAuthorizedControlCommandInterest, this, |
| 501 | _1, _2, _3, _4, validateParams, handler); |
| 502 | |
| 503 | AuthorizationRejectedCallback rejected = |
| 504 | bind(&Dispatcher::afterAuthorizationRejected, this, _1, _2); |
| 505 | |
| 506 | m_handlers[relPrefix] = bind(&Dispatcher::processControlCommandInterest, this, |
| 507 | _1, relPrefix, _2, parser, authorization, accepted, rejected); |
| 508 | } |
| 509 | |
| 510 | } // namespace mgmt |
| 511 | } // namespace ndn |
| 512 | #endif // NDN_MGMT_DISPATCHER_HPP |