blob: a78179d624347c04e07fa39bebfc3ea680f65aa9 [file] [log] [blame]
Junxiao Shi5ec80222014-03-25 20:08:05 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
Junxiao Shi5ec80222014-03-25 20:08:05 -070011 */
12
13#ifndef NDN_MANAGEMENT_NFD_CONTROL_COMMAND_HPP
14#define NDN_MANAGEMENT_NFD_CONTROL_COMMAND_HPP
15
16#include "nfd-control-parameters.hpp"
17#include "../util/command-interest-generator.hpp"
18
19namespace ndn {
20namespace nfd {
21
22/** \brief base class of NFD ControlCommand
23 * \sa http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
24 */
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070025class ControlCommand : noncopyable
Junxiao Shi5ec80222014-03-25 20:08:05 -070026{
27public:
28 /** \brief represents an error in ControlParameters
29 */
30 class ArgumentError : public std::invalid_argument
31 {
32 public:
33 explicit
34 ArgumentError(const std::string& what)
35 : std::invalid_argument(what)
36 {
37 }
38 };
39
40 /** \return Name prefix of this ControlCommand
41 */
42 const Name&
43 getPrefix() const
44 {
45 return m_prefix;
46 }
47
48 /** \brief make a Command Interest from parameters
49 */
50 Interest
51 makeCommandInterest(const ControlParameters& parameters,
52 CommandInterestGenerator& commandInterestGenerator) const
53 {
54 this->validateRequest(parameters);
55
56 Name name = m_prefix;
57 name.append(parameters.wireEncode());
58 Interest commandInterest(name);
59 commandInterestGenerator.generate(commandInterest);
60 return commandInterest;
61 }
62
63 /** \brief validate request parameters
64 * \throw ArgumentError
65 */
66 virtual void
67 validateRequest(const ControlParameters& parameters) const
68 {
69 m_requestValidator.validate(parameters);
70 }
71
72 /** \brief apply default values to missing fields in request
73 */
74 virtual void
75 applyDefaultsToRequest(ControlParameters& parameters) const
76 {
77 }
78
79 /** \brief validate response parameters
80 * \throw ArgumentError
81 */
82 virtual void
83 validateResponse(const ControlParameters& parameters) const
84 {
85 m_responseValidator.validate(parameters);
86 }
87
88 /** \brief apply default values to missing fields in response
89 */
90 virtual void
91 applyDefaultsToResponse(ControlParameters& parameters) const
92 {
93 }
94
95protected:
96 ControlCommand(const std::string& module, const std::string& verb)
97 : m_prefix("ndn:/localhost/nfd")
98 {
99 m_prefix.append(module).append(verb);
100 }
101
102 class FieldValidator
103 {
104 public:
105 FieldValidator()
Junxiao Shi5f6c74f2014-04-18 16:29:44 -0700106 : m_required(CONTROL_PARAMETER_UBOUND)
107 , m_optional(CONTROL_PARAMETER_UBOUND)
Junxiao Shi5ec80222014-03-25 20:08:05 -0700108 {
Junxiao Shi5ec80222014-03-25 20:08:05 -0700109 }
110
111 /** \brief declare a required field
112 */
113 FieldValidator&
114 required(ControlParameterField field)
115 {
116 m_required[field] = true;
117 return *this;
118 }
119
120 /** \brief declare an optional field
121 */
122 FieldValidator&
123 optional(ControlParameterField field)
124 {
125 m_optional[field] = true;
126 return *this;
127 }
128
129 /** \brief verify that all required fields are present,
130 * and all present fields are either required or optional
131 * \throw ArgumentError
132 */
133 void
134 validate(const ControlParameters& parameters) const
135 {
136 const std::vector<bool>& presentFields = parameters.getPresentFields();
137
138 for (size_t i = 0; i < CONTROL_PARAMETER_UBOUND; ++i) {
139 bool isPresent = presentFields[i];
140 if (m_required[i]) {
141 if (!isPresent) {
142 throw ArgumentError(CONTROL_PARAMETER_FIELD[i] + " is required but missing");
143 }
144 }
145 else if (isPresent && !m_optional[i]) {
146 throw ArgumentError(CONTROL_PARAMETER_FIELD[i] + " is forbidden but present");
147 }
148 }
149 }
150
151 private:
152 std::vector<bool> m_required;
153 std::vector<bool> m_optional;
154 };
155
156protected:
157 /** \brief FieldValidator for request ControlParameters
158 *
159 * Constructor of subclass should populate this validator.
160 */
161 FieldValidator m_requestValidator;
162 /** \brief FieldValidator for response ControlParameters
163 *
164 * Constructor of subclass should populate this validator.
165 */
166 FieldValidator m_responseValidator;
167
168private:
169 Name m_prefix;
170};
171
172
173/** \brief represents a faces/create command
174 * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Create-a-face
175 */
176class FaceCreateCommand : public ControlCommand
177{
178public:
179 FaceCreateCommand()
180 : ControlCommand("faces", "create")
181 {
182 m_requestValidator
183 .required(CONTROL_PARAMETER_URI);
184 m_responseValidator
185 .required(CONTROL_PARAMETER_URI)
186 .required(CONTROL_PARAMETER_FACE_ID);
187 }
188
189 virtual void
190 validateResponse(const ControlParameters& parameters) const
191 {
192 this->ControlCommand::validateResponse(parameters);
193
194 if (parameters.getFaceId() == 0) {
195 throw ArgumentError("FaceId must not be zero");
196 }
197 }
198};
199
200
201/** \brief represents a faces/destroy command
202 * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Destroy-a-face
203 */
204class FaceDestroyCommand : public ControlCommand
205{
206public:
207 FaceDestroyCommand()
208 : ControlCommand("faces", "destroy")
209 {
210 m_requestValidator
211 .required(CONTROL_PARAMETER_FACE_ID);
212 m_responseValidator = m_requestValidator;
213 }
214
215 virtual void
216 validateRequest(const ControlParameters& parameters) const
217 {
218 this->ControlCommand::validateRequest(parameters);
219
220 if (parameters.getFaceId() == 0) {
221 throw ArgumentError("FaceId must not be zero");
222 }
223 }
224
225 virtual void
226 validateResponse(const ControlParameters& parameters) const
227 {
228 this->validateRequest(parameters);
229 }
230};
231
232
233class FaceLocalControlCommand : public ControlCommand
234{
Junxiao Shi6888bc12014-03-29 23:01:41 -0700235public:
236 virtual void
237 validateRequest(const ControlParameters& parameters) const
238 {
239 this->ControlCommand::validateRequest(parameters);
240
241 switch (parameters.getLocalControlFeature()) {
242 case LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID:
243 case LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID:
244 break;
245 default:
246 throw ArgumentError("LocalControlFeature is invalid");
247 }
248 }
249
250 virtual void
251 validateResponse(const ControlParameters& parameters) const
252 {
253 this->validateRequest(parameters);
254 }
255
Junxiao Shi5ec80222014-03-25 20:08:05 -0700256protected:
257 explicit
258 FaceLocalControlCommand(const std::string& verb)
259 : ControlCommand("faces", verb)
260 {
261 m_requestValidator
262 .required(CONTROL_PARAMETER_LOCAL_CONTROL_FEATURE);
263 m_responseValidator = m_requestValidator;
264 }
265};
266
267
268/** \brief represents a faces/enable-local-control command
269 * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Enable-a-LocalControlHeader-feature
270 */
271class FaceEnableLocalControlCommand : public FaceLocalControlCommand
272{
273public:
274 FaceEnableLocalControlCommand()
275 : FaceLocalControlCommand("enable-local-control")
276 {
277 }
278};
279
280
281/** \brief represents a faces/disable-local-control command
282 * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Disable-a-LocalControlHeader-feature
283 */
284class FaceDisableLocalControlCommand : public FaceLocalControlCommand
285{
286public:
287 FaceDisableLocalControlCommand()
288 : FaceLocalControlCommand("disable-local-control")
289 {
290 }
291};
292
293
294/** \brief represents a fib/add-nexthop command
295 * \sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#Add-a-nexthop
296 */
297class FibAddNextHopCommand : public ControlCommand
298{
299public:
300 FibAddNextHopCommand()
301 : ControlCommand("fib", "add-nexthop")
302 {
303 m_requestValidator
304 .required(CONTROL_PARAMETER_NAME)
305 .required(CONTROL_PARAMETER_FACE_ID)
306 .optional(CONTROL_PARAMETER_COST);
307 m_responseValidator
308 .required(CONTROL_PARAMETER_NAME)
309 .required(CONTROL_PARAMETER_FACE_ID)
310 .required(CONTROL_PARAMETER_COST);
311 }
312
313 virtual void
314 applyDefaultsToRequest(ControlParameters& parameters) const
315 {
316 if (!parameters.hasCost()) {
317 parameters.setCost(0);
318 }
319 }
320
321 virtual void
322 validateResponse(const ControlParameters& parameters) const
323 {
324 this->ControlCommand::validateResponse(parameters);
325
326 if (parameters.getFaceId() == 0) {
327 throw ArgumentError("FaceId must not be zero");
328 }
329 }
330};
331
332
333/** \brief represents a fib/remove-nexthop command
334 * \sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#Remove-a-nexthop
335 */
336class FibRemoveNextHopCommand : public ControlCommand
337{
338public:
339 FibRemoveNextHopCommand()
340 : ControlCommand("fib", "remove-nexthop")
341 {
342 m_requestValidator
343 .required(CONTROL_PARAMETER_NAME)
344 .required(CONTROL_PARAMETER_FACE_ID);
345 m_responseValidator
346 .required(CONTROL_PARAMETER_NAME)
347 .required(CONTROL_PARAMETER_FACE_ID);
348 }
349
350 virtual void
351 validateResponse(const ControlParameters& parameters) const
352 {
353 this->ControlCommand::validateResponse(parameters);
354
355 if (parameters.getFaceId() == 0) {
356 throw ArgumentError("FaceId must not be zero");
357 }
358 }
359};
360
361
362/** \brief represents a strategy-choice/set command
363 * \sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Set-the-strategy-for-a-namespace
364 */
365class StrategyChoiceSetCommand : public ControlCommand
366{
367public:
368 StrategyChoiceSetCommand()
369 : ControlCommand("strategy-choice", "set")
370 {
371 m_requestValidator
372 .required(CONTROL_PARAMETER_NAME)
373 .required(CONTROL_PARAMETER_STRATEGY);
374 m_responseValidator = m_requestValidator;
375 }
376};
377
378
379/** \brief represents a strategy-choice/set command
380 * \sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Unset-the-strategy-for-a-namespace
381 */
382class StrategyChoiceUnsetCommand : public ControlCommand
383{
384public:
385 StrategyChoiceUnsetCommand()
386 : ControlCommand("strategy-choice", "unset")
387 {
388 m_requestValidator
389 .required(CONTROL_PARAMETER_NAME);
390 m_responseValidator = m_requestValidator;
391 }
392
393 virtual void
394 validateRequest(const ControlParameters& parameters) const
395 {
396 this->ControlCommand::validateRequest(parameters);
397
398 if (parameters.getName().size() == 0) {
399 throw ArgumentError("Name must not be ndn:/");
400 }
401 }
402
403 virtual void
404 validateResponse(const ControlParameters& parameters) const
405 {
406 this->validateRequest(parameters);
407 }
408};
409
Junxiao Shi5f6c74f2014-04-18 16:29:44 -0700410
411enum {
412 // route origin
413 ROUTE_ORIGIN_APP = 0,
414 ROUTE_ORIGIN_NLSR = 128,
415 ROUTE_ORIGIN_STATIC = 255,
416
417 // route inheritance flags
418 ROUTE_FLAG_CHILD_INHERIT = 1,
419 ROUTE_FLAG_CAPTURE = 2
420};
421
422
423/** \brief represents a rib/register command
424 * \sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#Register-a-route
425 */
426class RibRegisterCommand : public ControlCommand
427{
428public:
429 RibRegisterCommand()
430 : ControlCommand("rib", "register")
431 {
432 m_requestValidator
433 .required(CONTROL_PARAMETER_NAME)
434 .optional(CONTROL_PARAMETER_FACE_ID)
435 .optional(CONTROL_PARAMETER_ORIGIN)
436 .optional(CONTROL_PARAMETER_COST)
437 .optional(CONTROL_PARAMETER_FLAGS)
438 .optional(CONTROL_PARAMETER_EXPIRATION_PERIOD);
439 m_responseValidator
440 .required(CONTROL_PARAMETER_NAME)
441 .required(CONTROL_PARAMETER_FACE_ID)
442 .required(CONTROL_PARAMETER_ORIGIN)
443 .required(CONTROL_PARAMETER_COST)
444 .required(CONTROL_PARAMETER_FLAGS)
445 .required(CONTROL_PARAMETER_EXPIRATION_PERIOD);
446 }
447
448 virtual void
449 applyDefaultsToRequest(ControlParameters& parameters) const
450 {
451 if (!parameters.hasFaceId()) {
452 parameters.setFaceId(0);
453 }
454 if (!parameters.hasOrigin()) {
455 parameters.setOrigin(ROUTE_ORIGIN_APP);
456 }
457 if (!parameters.hasCost()) {
458 parameters.setCost(0);
459 }
460 if (!parameters.hasFlags()) {
461 parameters.setFlags(ROUTE_FLAG_CHILD_INHERIT);
462 }
463 if (!parameters.hasExpirationPeriod()) {
464 if (parameters.getFaceId() == 0) {
465 parameters.setExpirationPeriod(time::milliseconds::max());
466 }
467 else {
468 parameters.setExpirationPeriod(time::hours(1));
469 }
470 }
471 }
472
473 virtual void
474 validateResponse(const ControlParameters& parameters) const
475 {
476 this->ControlCommand::validateResponse(parameters);
477
478 if (parameters.getFaceId() == 0) {
479 throw ArgumentError("FaceId must not be zero");
480 }
481 }
482};
483
484
485/** \brief represents a rib/unregister command
486 * \sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#Unregister-a-route
487 */
488class RibUnregisterCommand : public ControlCommand
489{
490public:
491 RibUnregisterCommand()
492 : ControlCommand("rib", "unregister")
493 {
494 m_requestValidator
495 .required(CONTROL_PARAMETER_NAME)
496 .optional(CONTROL_PARAMETER_FACE_ID)
497 .optional(CONTROL_PARAMETER_ORIGIN);
498 m_responseValidator
499 .required(CONTROL_PARAMETER_NAME)
500 .required(CONTROL_PARAMETER_FACE_ID)
501 .required(CONTROL_PARAMETER_ORIGIN);
502 }
503
504 virtual void
505 applyDefaultsToRequest(ControlParameters& parameters) const
506 {
507 if (!parameters.hasFaceId()) {
508 parameters.setFaceId(0);
509 }
510 if (!parameters.hasOrigin()) {
511 parameters.setOrigin(ROUTE_ORIGIN_APP);
512 }
513 }
514
515 virtual void
516 validateResponse(const ControlParameters& parameters) const
517 {
518 this->ControlCommand::validateResponse(parameters);
519
520 if (parameters.getFaceId() == 0) {
521 throw ArgumentError("FaceId must not be zero");
522 }
523 }
524};
525
526
Junxiao Shi5ec80222014-03-25 20:08:05 -0700527} // namespace nfd
528} // namespace ndn
529
530#endif // NDN_MANAGEMENT_NFD_CONTROL_COMMAND_HPP