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 | /* |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 3 | * Copyright (c) 2013-2018 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 | |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 25 | #include "../encoding/block.hpp" |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 26 | #include "../face.hpp" |
Junxiao Shi | c542f63 | 2017-07-18 14:20:32 +0000 | [diff] [blame] | 27 | #include "../ims/in-memory-storage-fifo.hpp" |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 28 | #include "../security/key-chain.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 | */ |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 60 | typedef std::function<void(RejectReply reply)> RejectContinuation; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 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 | |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 79 | /** \brief return an Authorization that accepts all Interests, with empty string as requester |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 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 | |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 108 | // ---- STATUS DATASET ---- |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 109 | |
| 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 | */ |
| 117 | typedef 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 | */ |
| 124 | typedef std::function<void(const Block& notification)> PostNotification; |
| 125 | |
| 126 | // ---- DISPATCHER ---- |
| 127 | |
| 128 | /** \brief represents a dispatcher on server side of NFD Management protocol |
| 129 | */ |
| 130 | class Dispatcher : noncopyable |
| 131 | { |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 132 | public: |
| 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 Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 137 | * \param imsCapacity capacity of the internal InMemoryStorage used by dispatcher |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 138 | */ |
Alexander Afanasyev | 80782e0 | 2017-01-04 13:16:54 -0800 | [diff] [blame] | 139 | Dispatcher(Face& face, KeyChain& keyChain, |
Yanbiao Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 140 | const security::SigningInfo& signingInfo = security::SigningInfo(), |
| 141 | size_t imsCapacity = 256); |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 142 | |
| 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 | |
| 183 | public: // 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 Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 188 | * non-overlapping (no relPrefix is a prefix of another relPrefix) |
Alexander Afanasyev | f2a4622 | 2015-09-17 18:01:30 -0700 | [diff] [blame] | 189 | * \param authorization Callback to authorize the incoming commands |
| 190 | * \param validateParams Callback to validate parameters of the incoming commands |
| 191 | * \param handler Callback to handle the commands |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 192 | * \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, |
Junxiao Shi | f65a336 | 2015-09-06 20:54:54 -0700 | [diff] [blame] | 212 | const Authorization& authorization, |
| 213 | const ValidateParameters& validateParams, |
| 214 | const ControlCommandHandler& handler); |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 215 | |
| 216 | public: // 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 Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 220 | * non-overlapping (no relPrefix is a prefix of another relPrefix) |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 221 | * \param authorization should set identity to Name() if the dataset is public |
Alexander Afanasyev | f2a4622 | 2015-09-17 18:01:30 -0700 | [diff] [blame] | 222 | * \param handler Callback to process the incoming dataset requests |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 223 | * \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, |
Junxiao Shi | f65a336 | 2015-09-06 20:54:54 -0700 | [diff] [blame] | 249 | const Authorization& authorization, |
| 250 | const StatusDatasetHandler& handler); |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 251 | |
| 252 | public: // 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 Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 256 | * non-overlapping (no relPrefix is a prefix of another relPrefix) |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 257 | * \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 | |
| 275 | private: |
| 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 Shi | d97c953 | 2017-04-27 16:17:04 +0000 | [diff] [blame] | 282 | const shared_ptr<ControlParameters>&)> AuthorizationAcceptedCallback; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 283 | |
| 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 Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 289 | * @param comp name component that may encode control parameters. |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 290 | * @return a shared pointer to the extracted control parameters. |
| 291 | * @throw tlv::Error if the NameComponent cannot be parsed as ControlParameters |
| 292 | */ |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 293 | typedef std::function<shared_ptr<ControlParameters>(const name::Component& comp)> ControlParametersParser; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 294 | |
| 295 | bool |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 296 | isOverlappedWithOthers(const PartialName& relPrefix) const; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 297 | |
| 298 | /** |
| 299 | * @brief process unauthorized request |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 300 | * @param act action to reply |
| 301 | * @param interest the incoming Interest |
| 302 | */ |
| 303 | void |
| 304 | afterAuthorizationRejected(RejectReply act, const Interest& interest); |
| 305 | |
Yanbiao Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 306 | /** |
| 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 Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 315 | void |
Yanbiao Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 316 | 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 Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 326 | * @brief send data to the face and/or in-memory storage |
Yanbiao Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 327 | * |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 328 | * 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 Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 331 | * |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 332 | * 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 Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 334 | * |
| 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 Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 352 | |
| 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 Shi | d97c953 | 2017-04-27 16:17:04 +0000 | [diff] [blame] | 387 | const shared_ptr<ControlParameters>& parameters, |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 388 | 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 Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 424 | /** |
| 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 Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 436 | void |
| 437 | postNotification(const Block& notification, const PartialName& relPrefix); |
| 438 | |
| 439 | private: |
| 440 | struct TopPrefixEntry |
| 441 | { |
| 442 | Name topPrefix; |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 443 | optional<const RegisteredPrefixId*> registeredPrefixId = nullopt; |
| 444 | std::vector<const InterestFilterId*> interestFilters; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 445 | }; |
| 446 | std::unordered_map<Name, TopPrefixEntry> m_topLevelPrefixes; |
| 447 | |
| 448 | Face& m_face; |
Alexander Afanasyev | 80782e0 | 2017-01-04 13:16:54 -0800 | [diff] [blame] | 449 | KeyChain& m_keyChain; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 450 | security::SigningInfo m_signingInfo; |
| 451 | |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 452 | std::unordered_map<PartialName, InterestHandler> m_handlers; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 453 | |
| 454 | // NotificationStream name => next sequence number |
| 455 | std::unordered_map<Name, uint64_t> m_streams; |
Yanbiao Li | 4b4f754 | 2016-03-11 02:04:43 +0800 | [diff] [blame] | 456 | |
| 457 | NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: |
Junxiao Shi | c542f63 | 2017-07-18 14:20:32 +0000 | [diff] [blame] | 458 | InMemoryStorageFifo m_storage; |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 459 | }; |
| 460 | |
| 461 | template<typename CP> |
| 462 | void |
| 463 | Dispatcher::addControlCommand(const PartialName& relPrefix, |
Junxiao Shi | f65a336 | 2015-09-06 20:54:54 -0700 | [diff] [blame] | 464 | const Authorization& authorization, |
| 465 | const ValidateParameters& validateParams, |
| 466 | const ControlCommandHandler& handler) |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 467 | { |
| 468 | if (!m_topLevelPrefixes.empty()) { |
Junxiao Shi | d97c953 | 2017-04-27 16:17:04 +0000 | [diff] [blame] | 469 | 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] | 470 | } |
| 471 | |
| 472 | if (isOverlappedWithOthers(relPrefix)) { |
Junxiao Shi | d97c953 | 2017-04-27 16:17:04 +0000 | [diff] [blame] | 473 | BOOST_THROW_EXCEPTION(std::out_of_range("relPrefix overlaps with another relPrefix")); |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 474 | } |
| 475 | |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 476 | ControlParametersParser parser = [] (const name::Component& comp) -> shared_ptr<ControlParameters> { |
| 477 | return make_shared<CP>(comp.blockFromValue()); |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 478 | }; |
| 479 | |
| 480 | AuthorizationAcceptedCallback accepted = |
| 481 | bind(&Dispatcher::processAuthorizedControlCommandInterest, this, |
| 482 | _1, _2, _3, _4, validateParams, handler); |
| 483 | |
| 484 | AuthorizationRejectedCallback rejected = |
| 485 | bind(&Dispatcher::afterAuthorizationRejected, this, _1, _2); |
| 486 | |
| 487 | m_handlers[relPrefix] = bind(&Dispatcher::processControlCommandInterest, this, |
| 488 | _1, relPrefix, _2, parser, authorization, accepted, rejected); |
| 489 | } |
| 490 | |
| 491 | } // namespace mgmt |
| 492 | } // namespace ndn |
Davide Pesavento | 3c8a8b0 | 2018-03-01 14:46:55 -0500 | [diff] [blame^] | 493 | |
Yanbiao Li | 8ee37ed | 2015-05-19 12:44:04 -0700 | [diff] [blame] | 494 | #endif // NDN_MGMT_DISPATCHER_HPP |