blob: 168daec02f9162dd1a3b2d4fc2e878f439c83159 [file] [log] [blame]
Junxiao Shi5ec80222014-03-25 20:08:05 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * See COPYING for copyright and distribution information.
5 */
6
7#ifndef NDN_MANAGEMENT_NFD_CONTROL_COMMAND_HPP
8#define NDN_MANAGEMENT_NFD_CONTROL_COMMAND_HPP
9
10#include "nfd-control-parameters.hpp"
11#include "../util/command-interest-generator.hpp"
12
13namespace ndn {
14namespace nfd {
15
16/** \brief base class of NFD ControlCommand
17 * \sa http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
18 */
Junxiao Shi7b6b79d2014-03-26 20:59:35 -070019class ControlCommand : noncopyable
Junxiao Shi5ec80222014-03-25 20:08:05 -070020{
21public:
22 /** \brief represents an error in ControlParameters
23 */
24 class ArgumentError : public std::invalid_argument
25 {
26 public:
27 explicit
28 ArgumentError(const std::string& what)
29 : std::invalid_argument(what)
30 {
31 }
32 };
33
34 /** \return Name prefix of this ControlCommand
35 */
36 const Name&
37 getPrefix() const
38 {
39 return m_prefix;
40 }
41
42 /** \brief make a Command Interest from parameters
43 */
44 Interest
45 makeCommandInterest(const ControlParameters& parameters,
46 CommandInterestGenerator& commandInterestGenerator) const
47 {
48 this->validateRequest(parameters);
49
50 Name name = m_prefix;
51 name.append(parameters.wireEncode());
52 Interest commandInterest(name);
53 commandInterestGenerator.generate(commandInterest);
54 return commandInterest;
55 }
56
57 /** \brief validate request parameters
58 * \throw ArgumentError
59 */
60 virtual void
61 validateRequest(const ControlParameters& parameters) const
62 {
63 m_requestValidator.validate(parameters);
64 }
65
66 /** \brief apply default values to missing fields in request
67 */
68 virtual void
69 applyDefaultsToRequest(ControlParameters& parameters) const
70 {
71 }
72
73 /** \brief validate response parameters
74 * \throw ArgumentError
75 */
76 virtual void
77 validateResponse(const ControlParameters& parameters) const
78 {
79 m_responseValidator.validate(parameters);
80 }
81
82 /** \brief apply default values to missing fields in response
83 */
84 virtual void
85 applyDefaultsToResponse(ControlParameters& parameters) const
86 {
87 }
88
89protected:
90 ControlCommand(const std::string& module, const std::string& verb)
91 : m_prefix("ndn:/localhost/nfd")
92 {
93 m_prefix.append(module).append(verb);
94 }
95
96 class FieldValidator
97 {
98 public:
99 FieldValidator()
100 {
101 m_required.resize(CONTROL_PARAMETER_UBOUND);
102 m_optional.resize(CONTROL_PARAMETER_UBOUND);
103 }
104
105 /** \brief declare a required field
106 */
107 FieldValidator&
108 required(ControlParameterField field)
109 {
110 m_required[field] = true;
111 return *this;
112 }
113
114 /** \brief declare an optional field
115 */
116 FieldValidator&
117 optional(ControlParameterField field)
118 {
119 m_optional[field] = true;
120 return *this;
121 }
122
123 /** \brief verify that all required fields are present,
124 * and all present fields are either required or optional
125 * \throw ArgumentError
126 */
127 void
128 validate(const ControlParameters& parameters) const
129 {
130 const std::vector<bool>& presentFields = parameters.getPresentFields();
131
132 for (size_t i = 0; i < CONTROL_PARAMETER_UBOUND; ++i) {
133 bool isPresent = presentFields[i];
134 if (m_required[i]) {
135 if (!isPresent) {
136 throw ArgumentError(CONTROL_PARAMETER_FIELD[i] + " is required but missing");
137 }
138 }
139 else if (isPresent && !m_optional[i]) {
140 throw ArgumentError(CONTROL_PARAMETER_FIELD[i] + " is forbidden but present");
141 }
142 }
143 }
144
145 private:
146 std::vector<bool> m_required;
147 std::vector<bool> m_optional;
148 };
149
150protected:
151 /** \brief FieldValidator for request ControlParameters
152 *
153 * Constructor of subclass should populate this validator.
154 */
155 FieldValidator m_requestValidator;
156 /** \brief FieldValidator for response ControlParameters
157 *
158 * Constructor of subclass should populate this validator.
159 */
160 FieldValidator m_responseValidator;
161
162private:
163 Name m_prefix;
164};
165
166
167/** \brief represents a faces/create command
168 * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Create-a-face
169 */
170class FaceCreateCommand : public ControlCommand
171{
172public:
173 FaceCreateCommand()
174 : ControlCommand("faces", "create")
175 {
176 m_requestValidator
177 .required(CONTROL_PARAMETER_URI);
178 m_responseValidator
179 .required(CONTROL_PARAMETER_URI)
180 .required(CONTROL_PARAMETER_FACE_ID);
181 }
182
183 virtual void
184 validateResponse(const ControlParameters& parameters) const
185 {
186 this->ControlCommand::validateResponse(parameters);
187
188 if (parameters.getFaceId() == 0) {
189 throw ArgumentError("FaceId must not be zero");
190 }
191 }
192};
193
194
195/** \brief represents a faces/destroy command
196 * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Destroy-a-face
197 */
198class FaceDestroyCommand : public ControlCommand
199{
200public:
201 FaceDestroyCommand()
202 : ControlCommand("faces", "destroy")
203 {
204 m_requestValidator
205 .required(CONTROL_PARAMETER_FACE_ID);
206 m_responseValidator = m_requestValidator;
207 }
208
209 virtual void
210 validateRequest(const ControlParameters& parameters) const
211 {
212 this->ControlCommand::validateRequest(parameters);
213
214 if (parameters.getFaceId() == 0) {
215 throw ArgumentError("FaceId must not be zero");
216 }
217 }
218
219 virtual void
220 validateResponse(const ControlParameters& parameters) const
221 {
222 this->validateRequest(parameters);
223 }
224};
225
226
227class FaceLocalControlCommand : public ControlCommand
228{
229protected:
230 explicit
231 FaceLocalControlCommand(const std::string& verb)
232 : ControlCommand("faces", verb)
233 {
234 m_requestValidator
235 .required(CONTROL_PARAMETER_LOCAL_CONTROL_FEATURE);
236 m_responseValidator = m_requestValidator;
237 }
238};
239
240
241/** \brief represents a faces/enable-local-control command
242 * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Enable-a-LocalControlHeader-feature
243 */
244class FaceEnableLocalControlCommand : public FaceLocalControlCommand
245{
246public:
247 FaceEnableLocalControlCommand()
248 : FaceLocalControlCommand("enable-local-control")
249 {
250 }
251};
252
253
254/** \brief represents a faces/disable-local-control command
255 * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Disable-a-LocalControlHeader-feature
256 */
257class FaceDisableLocalControlCommand : public FaceLocalControlCommand
258{
259public:
260 FaceDisableLocalControlCommand()
261 : FaceLocalControlCommand("disable-local-control")
262 {
263 }
264};
265
266
267/** \brief represents a fib/add-nexthop command
268 * \sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#Add-a-nexthop
269 */
270class FibAddNextHopCommand : public ControlCommand
271{
272public:
273 FibAddNextHopCommand()
274 : ControlCommand("fib", "add-nexthop")
275 {
276 m_requestValidator
277 .required(CONTROL_PARAMETER_NAME)
278 .required(CONTROL_PARAMETER_FACE_ID)
279 .optional(CONTROL_PARAMETER_COST);
280 m_responseValidator
281 .required(CONTROL_PARAMETER_NAME)
282 .required(CONTROL_PARAMETER_FACE_ID)
283 .required(CONTROL_PARAMETER_COST);
284 }
285
286 virtual void
287 applyDefaultsToRequest(ControlParameters& parameters) const
288 {
289 if (!parameters.hasCost()) {
290 parameters.setCost(0);
291 }
292 }
293
294 virtual void
295 validateResponse(const ControlParameters& parameters) const
296 {
297 this->ControlCommand::validateResponse(parameters);
298
299 if (parameters.getFaceId() == 0) {
300 throw ArgumentError("FaceId must not be zero");
301 }
302 }
303};
304
305
306/** \brief represents a fib/remove-nexthop command
307 * \sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#Remove-a-nexthop
308 */
309class FibRemoveNextHopCommand : public ControlCommand
310{
311public:
312 FibRemoveNextHopCommand()
313 : ControlCommand("fib", "remove-nexthop")
314 {
315 m_requestValidator
316 .required(CONTROL_PARAMETER_NAME)
317 .required(CONTROL_PARAMETER_FACE_ID);
318 m_responseValidator
319 .required(CONTROL_PARAMETER_NAME)
320 .required(CONTROL_PARAMETER_FACE_ID);
321 }
322
323 virtual void
324 validateResponse(const ControlParameters& parameters) const
325 {
326 this->ControlCommand::validateResponse(parameters);
327
328 if (parameters.getFaceId() == 0) {
329 throw ArgumentError("FaceId must not be zero");
330 }
331 }
332};
333
334
335/** \brief represents a strategy-choice/set command
336 * \sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Set-the-strategy-for-a-namespace
337 */
338class StrategyChoiceSetCommand : public ControlCommand
339{
340public:
341 StrategyChoiceSetCommand()
342 : ControlCommand("strategy-choice", "set")
343 {
344 m_requestValidator
345 .required(CONTROL_PARAMETER_NAME)
346 .required(CONTROL_PARAMETER_STRATEGY);
347 m_responseValidator = m_requestValidator;
348 }
349};
350
351
352/** \brief represents a strategy-choice/set command
353 * \sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Unset-the-strategy-for-a-namespace
354 */
355class StrategyChoiceUnsetCommand : public ControlCommand
356{
357public:
358 StrategyChoiceUnsetCommand()
359 : ControlCommand("strategy-choice", "unset")
360 {
361 m_requestValidator
362 .required(CONTROL_PARAMETER_NAME);
363 m_responseValidator = m_requestValidator;
364 }
365
366 virtual void
367 validateRequest(const ControlParameters& parameters) const
368 {
369 this->ControlCommand::validateRequest(parameters);
370
371 if (parameters.getName().size() == 0) {
372 throw ArgumentError("Name must not be ndn:/");
373 }
374 }
375
376 virtual void
377 validateResponse(const ControlParameters& parameters) const
378 {
379 this->validateRequest(parameters);
380 }
381};
382
383} // namespace nfd
384} // namespace ndn
385
386#endif // NDN_MANAGEMENT_NFD_CONTROL_COMMAND_HPP