blob: d461cdd3a1772b257618441d6a9766fe68886203 [file] [log] [blame]
Alexander Afanasyeve1e6f2a2014-04-25 11:28:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Shuo Chenba793e92014-03-17 17:17:16 -07002/**
Alexander Afanasyeve1e6f2a2014-04-25 11:28:12 -07003 * Copyright (c) 2014, Regents of the University of California.
4 *
5 * This file is part of NDN repo-ng (Next generation of NDN repository).
6 * See AUTHORS.md for complete list of repo-ng authors and contributors.
7 *
8 * repo-ng is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * repo-ng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Shuo Chenba793e92014-03-17 17:17:16 -070018 */
19
Alexander Afanasyev39d98072014-05-04 12:46:29 -070020#ifndef REPO_REPO_COMMAND_PARAMETER_HPP
21#define REPO_REPO_COMMAND_PARAMETER_HPP
Shuo Chenba793e92014-03-17 17:17:16 -070022
Alexander Afanasyeve291caf2014-04-25 11:17:36 -070023#include <ndn-cxx/encoding/encoding-buffer.hpp>
24#include <ndn-cxx/name.hpp>
25#include <ndn-cxx/selectors.hpp>
Shuo Chenba793e92014-03-17 17:17:16 -070026#include "repo-tlv.hpp"
27
28namespace repo {
29
30using ndn::Name;
31using ndn::Block;
32using ndn::EncodingImpl;
33using ndn::Selectors;
34using ndn::EncodingEstimator;
35using ndn::EncodingBuffer;
Weiqi Shi098f91c2014-07-23 17:41:35 -070036using namespace ndn::time;
Shuo Chenba793e92014-03-17 17:17:16 -070037
38/**
39* @brief Class defining abstraction of parameter of command for NDN Repo Protocol
40* @sa link http://redmine.named-data.net/projects/repo-ng/wiki/Repo_Protocol_Specification#RepoCommandParameter
41**/
42
43class RepoCommandParameter
44{
45public:
Junxiao Shica188d72014-10-19 09:49:40 -070046 class Error : public ndn::tlv::Error
Shuo Chenba793e92014-03-17 17:17:16 -070047 {
48 public:
49 explicit
50 Error(const std::string& what)
Junxiao Shica188d72014-10-19 09:49:40 -070051 : ndn::tlv::Error(what)
Shuo Chenba793e92014-03-17 17:17:16 -070052 {
53 }
54 };
55
56 RepoCommandParameter()
57 : m_hasName(false)
58 , m_hasStartBlockId(false)
59 , m_hasEndBlockId(false)
60 , m_hasProcessId(false)
Weiqi Shi098f91c2014-07-23 17:41:35 -070061 , m_hasMaxInterestNum(false)
62 , m_hasWatchTimeout(false)
63 , m_hasInterestLifetime(false)
Shuo Chenba793e92014-03-17 17:17:16 -070064 {
65 }
66
67 explicit
68 RepoCommandParameter(const Block& block)
69 {
70 wireDecode(block);
71 }
72
73 const Name&
74 getName() const
75 {
76 return m_name;
77 }
78
79 RepoCommandParameter&
80 setName(const Name& name)
81 {
82 m_name = name;
83 m_hasName = true;
84 m_wire.reset();
85 return *this;
86 }
87
88 bool
89 hasName() const
90 {
91 return m_hasName;
92 }
93
94 const Selectors&
95 getSelectors() const
96 {
97 return m_selectors;
98 }
99
100 RepoCommandParameter&
101 setSelectors(const Selectors& selectors)
102 {
103 m_selectors = selectors;
104 m_wire.reset();
105 return *this;
106 }
107
108 bool
109 hasSelectors() const
110 {
111 return !m_selectors.empty();
112 }
113
114 uint64_t
115 getStartBlockId() const
116 {
117 assert(hasStartBlockId());
118 return m_startBlockId;
119 }
120
121 RepoCommandParameter&
122 setStartBlockId(uint64_t startBlockId)
123 {
124 m_startBlockId = startBlockId;
125 m_hasStartBlockId = true;
126 m_wire.reset();
127 return *this;
128 }
129
130 bool
131 hasStartBlockId() const
132 {
133 return m_hasStartBlockId;
134 }
135
136 uint64_t
137 getEndBlockId() const
138 {
139 assert(hasEndBlockId());
140 return m_endBlockId;
141 }
142
143 RepoCommandParameter&
144 setEndBlockId(uint64_t endBlockId)
145 {
146 m_endBlockId = endBlockId;
147 m_hasEndBlockId = true;
148 m_wire.reset();
149 return *this;
150 }
151
152 bool
153 hasEndBlockId() const
154 {
155 return m_hasEndBlockId;
156 }
157
158 uint64_t
159 getProcessId() const
160 {
161 assert(hasProcessId());
162 return m_processId;
163 }
164
Shuo Chenba793e92014-03-17 17:17:16 -0700165 RepoCommandParameter&
166 setProcessId(uint64_t processId)
167 {
168 m_processId = processId;
169 m_hasProcessId = true;
170 m_wire.reset();
171 return *this;
172 }
173
Weiqi Shi098f91c2014-07-23 17:41:35 -0700174 bool
175 hasProcessId() const
176 {
177 return m_hasProcessId;
178 }
179
180 uint64_t
181 getMaxInterestNum() const
182 {
183 assert(hasMaxInterestNum());
184 return m_maxInterestNum;
185 }
186
187 RepoCommandParameter&
188 setMaxInterestNum(uint64_t maxInterestNum)
189 {
190 m_maxInterestNum = maxInterestNum;
191 m_hasMaxInterestNum = true;
192 m_wire.reset();
193 return *this;
194 }
195
196 bool
197 hasMaxInterestNum() const
198 {
199 return m_hasMaxInterestNum;
200 }
201
202 milliseconds
203 getWatchTimeout() const
204 {
205 assert(hasWatchTimeout());
206 return m_watchTimeout;
207 }
208
209 RepoCommandParameter&
210 setWatchTimeout(milliseconds watchTimeout)
211 {
212 m_watchTimeout = watchTimeout;
213 m_hasWatchTimeout = true;
214 m_wire.reset();
215 return *this;
216 }
217
218 bool
219 hasWatchTimeout() const
220 {
221 return m_hasWatchTimeout;
222 }
223
224 milliseconds
225 getInterestLifetime() const
226 {
227 assert(hasInterestLifetime());
228 return m_interestLifetime;
229 }
230
231 RepoCommandParameter&
232 setInterestLifetime(milliseconds interestLifetime)
233 {
234 m_interestLifetime = interestLifetime;
235 m_hasInterestLifetime = true;
236 m_wire.reset();
237 return *this;
238 }
239
240 bool
241 hasInterestLifetime() const
242 {
243 return m_hasInterestLifetime;
244 }
245
Shuo Chenba793e92014-03-17 17:17:16 -0700246 template<bool T>
247 size_t
248 wireEncode(EncodingImpl<T>& block) const;
249
250 const Block&
251 wireEncode() const;
252
253 void
254 wireDecode(const Block& wire);
255
256private:
257
258 Name m_name;
259 Selectors m_selectors;
260 uint64_t m_startBlockId;
261 uint64_t m_endBlockId;
262 uint64_t m_processId;
Weiqi Shi098f91c2014-07-23 17:41:35 -0700263 uint64_t m_maxInterestNum;
264 milliseconds m_watchTimeout;
265 milliseconds m_interestLifetime;
Shuo Chenba793e92014-03-17 17:17:16 -0700266
267 bool m_hasName;
268 bool m_hasStartBlockId;
269 bool m_hasEndBlockId;
270 bool m_hasProcessId;
Weiqi Shi098f91c2014-07-23 17:41:35 -0700271 bool m_hasMaxInterestNum;
272 bool m_hasWatchTimeout;
273 bool m_hasInterestLifetime;
Shuo Chenba793e92014-03-17 17:17:16 -0700274
275 mutable Block m_wire;
276};
277
278template<bool T>
279inline size_t
280RepoCommandParameter::wireEncode(EncodingImpl<T>& encoder) const
281{
282 size_t totalLength = 0;
283 size_t variableLength = 0;
284
285 if (m_hasProcessId) {
286 variableLength = encoder.prependNonNegativeInteger(m_processId);
287 totalLength += variableLength;
288 totalLength += encoder.prependVarNumber(variableLength);
289 totalLength += encoder.prependVarNumber(tlv::ProcessId);
290 }
291
292 if (m_hasEndBlockId) {
293 variableLength = encoder.prependNonNegativeInteger(m_endBlockId);
294 totalLength += variableLength;
295 totalLength += encoder.prependVarNumber(variableLength);
296 totalLength += encoder.prependVarNumber(tlv::EndBlockId);
297 }
298
299 if (m_hasStartBlockId) {
300 variableLength = encoder.prependNonNegativeInteger(m_startBlockId);
301 totalLength += variableLength;
302 totalLength += encoder.prependVarNumber(variableLength);
303 totalLength += encoder.prependVarNumber(tlv::StartBlockId);
304 }
305
Weiqi Shi098f91c2014-07-23 17:41:35 -0700306 if (m_hasMaxInterestNum) {
307 variableLength = encoder.prependNonNegativeInteger(m_maxInterestNum);
308 totalLength += variableLength;
309 totalLength += encoder.prependVarNumber(variableLength);
310 totalLength += encoder.prependVarNumber(tlv::MaxInterestNum);
311 }
312
313 if (m_hasWatchTimeout) {
314 variableLength = encoder.prependNonNegativeInteger(m_watchTimeout.count());
315 totalLength += variableLength;
316 totalLength += encoder.prependVarNumber(variableLength);
317 totalLength += encoder.prependVarNumber(tlv::WatchTimeout);
318 }
319
320 if (m_hasInterestLifetime) {
321 variableLength = encoder.prependNonNegativeInteger(m_interestLifetime.count());
322 totalLength += variableLength;
323 totalLength += encoder.prependVarNumber(variableLength);
324 totalLength += encoder.prependVarNumber(tlv::InterestLifetime);
325 }
326
Shuo Chenba793e92014-03-17 17:17:16 -0700327 if (!getSelectors().empty()) {
328 totalLength += getSelectors().wireEncode(encoder);
329 }
330
331 if (m_hasName) {
332 totalLength += getName().wireEncode(encoder);
333 }
334
335 totalLength += encoder.prependVarNumber(totalLength);
336 totalLength += encoder.prependVarNumber(tlv::RepoCommandParameter);
337 return totalLength;
338}
339
340inline const Block&
341RepoCommandParameter::wireEncode() const
342{
343 if (m_wire.hasWire())
344 return m_wire;
345
346 EncodingEstimator estimator;
347 size_t estimatedSize = wireEncode(estimator);
348
349 EncodingBuffer buffer(estimatedSize, 0);
350 wireEncode(buffer);
351
352 m_wire = buffer.block();
353 return m_wire;
354}
355
356inline void
357RepoCommandParameter::wireDecode(const Block& wire)
358{
359 m_hasName = false;
360 m_hasStartBlockId = false;
361 m_hasEndBlockId = false;
362 m_hasProcessId = false;
Weiqi Shi098f91c2014-07-23 17:41:35 -0700363 m_hasMaxInterestNum = false;
364 m_hasWatchTimeout = false;
365 m_hasInterestLifetime = false;
Shuo Chenba793e92014-03-17 17:17:16 -0700366
367 m_wire = wire;
368
369 m_wire.parse();
370
371 if (m_wire.type() != tlv::RepoCommandParameter)
372 throw Error("Requested decoding of RepoCommandParameter, but Block is of different type");
373
374 // Name
375 Block::element_const_iterator val = m_wire.find(tlv::Name);
376 if (val != m_wire.elements_end())
377 {
378 m_hasName = true;
379 m_name.wireDecode(m_wire.get(tlv::Name));
380 }
381
382 // Selectors
383 val = m_wire.find(tlv::Selectors);
384 if (val != m_wire.elements_end())
385 {
386 m_selectors.wireDecode(*val);
387 }
388 else
389 m_selectors = Selectors();
390
391 // StartBlockId
392 val = m_wire.find(tlv::StartBlockId);
393 if (val != m_wire.elements_end())
394 {
395 m_hasStartBlockId = true;
396 m_startBlockId = readNonNegativeInteger(*val);
397 }
398
399 // EndBlockId
400 val = m_wire.find(tlv::EndBlockId);
401 if (val != m_wire.elements_end())
402 {
403 m_hasEndBlockId = true;
404 m_endBlockId = readNonNegativeInteger(*val);
405 }
406
407 // ProcessId
408 val = m_wire.find(tlv::ProcessId);
409 if (val != m_wire.elements_end())
410 {
411 m_hasProcessId = true;
412 m_processId = readNonNegativeInteger(*val);
413 }
414
Weiqi Shi098f91c2014-07-23 17:41:35 -0700415 // MaxInterestNum
416 val = m_wire.find(tlv::MaxInterestNum);
417 if (val != m_wire.elements_end())
418 {
419 m_hasMaxInterestNum = true;
420 m_maxInterestNum = readNonNegativeInteger(*val);
421 }
422
423 // WatchTimeout
424 val = m_wire.find(tlv::WatchTimeout);
425 if (val != m_wire.elements_end())
426 {
427 m_hasWatchTimeout = true;
428 m_watchTimeout = milliseconds(readNonNegativeInteger(*val));
429 }
430
431 // InterestLiftTime
432 val = m_wire.find(tlv::InterestLifetime);
433 if (val != m_wire.elements_end())
434 {
435 m_hasInterestLifetime = true;
436 m_interestLifetime = milliseconds(readNonNegativeInteger(*val));
437 }
438
439
Shuo Chenba793e92014-03-17 17:17:16 -0700440}
441
442inline std::ostream&
443operator<<(std::ostream& os, const RepoCommandParameter& repoCommandParameter)
444{
445 os << "RepoCommandParameter(";
446
447 // Name
448 if (repoCommandParameter.hasName()) {
449 os << " Name: " << repoCommandParameter.getName();
450 }
451 if (repoCommandParameter.hasStartBlockId()) {
452 // StartBlockId
453 os << " StartBlockId: " << repoCommandParameter.getStartBlockId();
454 }
455 // EndBlockId
456 if (repoCommandParameter.hasEndBlockId()) {
457 os << " EndBlockId: " << repoCommandParameter.getEndBlockId();
458 }
Weiqi Shi098f91c2014-07-23 17:41:35 -0700459 // ProcessId
Shuo Chenba793e92014-03-17 17:17:16 -0700460 if (repoCommandParameter.hasProcessId()) {
461 os << " ProcessId: " << repoCommandParameter.getProcessId();
462 }
Weiqi Shi098f91c2014-07-23 17:41:35 -0700463 // MaxInterestNum
464 if (repoCommandParameter.hasMaxInterestNum()) {
465 os << " MaxInterestNum: " << repoCommandParameter.getMaxInterestNum();
466 }
467 // WatchTimeout
468 if (repoCommandParameter.hasProcessId()) {
469 os << " WatchTimeout: " << repoCommandParameter.getWatchTimeout();
470 }
471 // InterestLifetime
472 if (repoCommandParameter.hasProcessId()) {
473 os << " InterestLifetime: " << repoCommandParameter.getInterestLifetime();
474 }
Shuo Chenba793e92014-03-17 17:17:16 -0700475 os << " )";
476 return os;
477}
478
Alexander Afanasyev39d98072014-05-04 12:46:29 -0700479} // namespace repo
Shuo Chenba793e92014-03-17 17:17:16 -0700480
Alexander Afanasyev39d98072014-05-04 12:46:29 -0700481#endif // REPO_REPO_COMMAND_PARAMETER_HPP