blob: 97208b6d941cb2fecf101316e8328ae02ddaf2f8 [file] [log] [blame]
Alexander Afanasyeve1e6f2a2014-04-25 11:28:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyevc0e26582017-08-13 21:16:49 -04002/*
Alexander Afanasyev42290b22017-03-09 12:58:29 -08003 * Copyright (c) 2014-2017, Regents of the University of California.
Alexander Afanasyeve1e6f2a2014-04-25 11:28:12 -07004 *
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 Afanasyevc0e26582017-08-13 21:16:49 -040023#include "repo-tlv.hpp"
24
Alexander Afanasyeve291caf2014-04-25 11:17:36 -070025#include <ndn-cxx/encoding/encoding-buffer.hpp>
Alexander Afanasyevd3e9da12014-11-12 11:31:31 -080026#include <ndn-cxx/encoding/block-helpers.hpp>
Alexander Afanasyeve291caf2014-04-25 11:17:36 -070027#include <ndn-cxx/name.hpp>
28#include <ndn-cxx/selectors.hpp>
Shuo Chenba793e92014-03-17 17:17:16 -070029
30namespace repo {
31
32using ndn::Name;
33using ndn::Block;
34using ndn::EncodingImpl;
35using ndn::Selectors;
36using ndn::EncodingEstimator;
37using ndn::EncodingBuffer;
Weiqi Shi098f91c2014-07-23 17:41:35 -070038using namespace ndn::time;
Shuo Chenba793e92014-03-17 17:17:16 -070039
40/**
41* @brief Class defining abstraction of parameter of command for NDN Repo Protocol
Alexander Afanasyev42290b22017-03-09 12:58:29 -080042* @sa link https://redmine.named-data.net/projects/repo-ng/wiki/Repo_Protocol_Specification#RepoCommandParameter
Shuo Chenba793e92014-03-17 17:17:16 -070043**/
44
45class RepoCommandParameter
46{
47public:
Junxiao Shica188d72014-10-19 09:49:40 -070048 class Error : public ndn::tlv::Error
Shuo Chenba793e92014-03-17 17:17:16 -070049 {
50 public:
51 explicit
52 Error(const std::string& what)
Junxiao Shica188d72014-10-19 09:49:40 -070053 : ndn::tlv::Error(what)
Shuo Chenba793e92014-03-17 17:17:16 -070054 {
55 }
56 };
57
58 RepoCommandParameter()
59 : m_hasName(false)
60 , m_hasStartBlockId(false)
61 , m_hasEndBlockId(false)
62 , m_hasProcessId(false)
Weiqi Shi098f91c2014-07-23 17:41:35 -070063 , m_hasMaxInterestNum(false)
64 , m_hasWatchTimeout(false)
65 , m_hasInterestLifetime(false)
Shuo Chenba793e92014-03-17 17:17:16 -070066 {
67 }
68
69 explicit
70 RepoCommandParameter(const Block& block)
71 {
72 wireDecode(block);
73 }
74
75 const Name&
76 getName() const
77 {
78 return m_name;
79 }
80
81 RepoCommandParameter&
82 setName(const Name& name)
83 {
84 m_name = name;
85 m_hasName = true;
86 m_wire.reset();
87 return *this;
88 }
89
90 bool
91 hasName() const
92 {
93 return m_hasName;
94 }
95
96 const Selectors&
97 getSelectors() const
98 {
99 return m_selectors;
100 }
101
102 RepoCommandParameter&
103 setSelectors(const Selectors& selectors)
104 {
105 m_selectors = selectors;
106 m_wire.reset();
107 return *this;
108 }
109
110 bool
111 hasSelectors() const
112 {
113 return !m_selectors.empty();
114 }
115
116 uint64_t
117 getStartBlockId() const
118 {
119 assert(hasStartBlockId());
120 return m_startBlockId;
121 }
122
123 RepoCommandParameter&
124 setStartBlockId(uint64_t startBlockId)
125 {
126 m_startBlockId = startBlockId;
127 m_hasStartBlockId = true;
128 m_wire.reset();
129 return *this;
130 }
131
132 bool
133 hasStartBlockId() const
134 {
135 return m_hasStartBlockId;
136 }
137
138 uint64_t
139 getEndBlockId() const
140 {
141 assert(hasEndBlockId());
142 return m_endBlockId;
143 }
144
145 RepoCommandParameter&
146 setEndBlockId(uint64_t endBlockId)
147 {
148 m_endBlockId = endBlockId;
149 m_hasEndBlockId = true;
150 m_wire.reset();
151 return *this;
152 }
153
154 bool
155 hasEndBlockId() const
156 {
157 return m_hasEndBlockId;
158 }
159
160 uint64_t
161 getProcessId() const
162 {
163 assert(hasProcessId());
164 return m_processId;
165 }
166
Shuo Chenba793e92014-03-17 17:17:16 -0700167 RepoCommandParameter&
168 setProcessId(uint64_t processId)
169 {
170 m_processId = processId;
171 m_hasProcessId = true;
172 m_wire.reset();
173 return *this;
174 }
175
Weiqi Shi098f91c2014-07-23 17:41:35 -0700176 bool
177 hasProcessId() const
178 {
179 return m_hasProcessId;
180 }
181
182 uint64_t
183 getMaxInterestNum() const
184 {
185 assert(hasMaxInterestNum());
186 return m_maxInterestNum;
187 }
188
189 RepoCommandParameter&
190 setMaxInterestNum(uint64_t maxInterestNum)
191 {
192 m_maxInterestNum = maxInterestNum;
193 m_hasMaxInterestNum = true;
194 m_wire.reset();
195 return *this;
196 }
197
198 bool
199 hasMaxInterestNum() const
200 {
201 return m_hasMaxInterestNum;
202 }
203
204 milliseconds
205 getWatchTimeout() const
206 {
207 assert(hasWatchTimeout());
208 return m_watchTimeout;
209 }
210
211 RepoCommandParameter&
212 setWatchTimeout(milliseconds watchTimeout)
213 {
214 m_watchTimeout = watchTimeout;
215 m_hasWatchTimeout = true;
216 m_wire.reset();
217 return *this;
218 }
219
220 bool
221 hasWatchTimeout() const
222 {
223 return m_hasWatchTimeout;
224 }
225
226 milliseconds
227 getInterestLifetime() const
228 {
229 assert(hasInterestLifetime());
230 return m_interestLifetime;
231 }
232
233 RepoCommandParameter&
234 setInterestLifetime(milliseconds interestLifetime)
235 {
236 m_interestLifetime = interestLifetime;
237 m_hasInterestLifetime = true;
238 m_wire.reset();
239 return *this;
240 }
241
242 bool
243 hasInterestLifetime() const
244 {
245 return m_hasInterestLifetime;
246 }
247
Alexander Afanasyevc0e26582017-08-13 21:16:49 -0400248 template<ndn::encoding::Tag T>
Shuo Chenba793e92014-03-17 17:17:16 -0700249 size_t
250 wireEncode(EncodingImpl<T>& block) const;
251
252 const Block&
253 wireEncode() const;
254
255 void
256 wireDecode(const Block& wire);
257
258private:
259
260 Name m_name;
261 Selectors m_selectors;
262 uint64_t m_startBlockId;
263 uint64_t m_endBlockId;
264 uint64_t m_processId;
Weiqi Shi098f91c2014-07-23 17:41:35 -0700265 uint64_t m_maxInterestNum;
266 milliseconds m_watchTimeout;
267 milliseconds m_interestLifetime;
Shuo Chenba793e92014-03-17 17:17:16 -0700268
269 bool m_hasName;
270 bool m_hasStartBlockId;
271 bool m_hasEndBlockId;
272 bool m_hasProcessId;
Weiqi Shi098f91c2014-07-23 17:41:35 -0700273 bool m_hasMaxInterestNum;
274 bool m_hasWatchTimeout;
275 bool m_hasInterestLifetime;
Shuo Chenba793e92014-03-17 17:17:16 -0700276
277 mutable Block m_wire;
278};
279
Alexander Afanasyevc0e26582017-08-13 21:16:49 -0400280template<ndn::encoding::Tag T>
Shuo Chenba793e92014-03-17 17:17:16 -0700281inline size_t
282RepoCommandParameter::wireEncode(EncodingImpl<T>& encoder) const
283{
284 size_t totalLength = 0;
285 size_t variableLength = 0;
286
287 if (m_hasProcessId) {
288 variableLength = encoder.prependNonNegativeInteger(m_processId);
289 totalLength += variableLength;
290 totalLength += encoder.prependVarNumber(variableLength);
291 totalLength += encoder.prependVarNumber(tlv::ProcessId);
292 }
293
294 if (m_hasEndBlockId) {
295 variableLength = encoder.prependNonNegativeInteger(m_endBlockId);
296 totalLength += variableLength;
297 totalLength += encoder.prependVarNumber(variableLength);
298 totalLength += encoder.prependVarNumber(tlv::EndBlockId);
299 }
300
301 if (m_hasStartBlockId) {
302 variableLength = encoder.prependNonNegativeInteger(m_startBlockId);
303 totalLength += variableLength;
304 totalLength += encoder.prependVarNumber(variableLength);
305 totalLength += encoder.prependVarNumber(tlv::StartBlockId);
306 }
307
Weiqi Shi098f91c2014-07-23 17:41:35 -0700308 if (m_hasMaxInterestNum) {
309 variableLength = encoder.prependNonNegativeInteger(m_maxInterestNum);
310 totalLength += variableLength;
311 totalLength += encoder.prependVarNumber(variableLength);
312 totalLength += encoder.prependVarNumber(tlv::MaxInterestNum);
313 }
314
315 if (m_hasWatchTimeout) {
316 variableLength = encoder.prependNonNegativeInteger(m_watchTimeout.count());
317 totalLength += variableLength;
318 totalLength += encoder.prependVarNumber(variableLength);
319 totalLength += encoder.prependVarNumber(tlv::WatchTimeout);
320 }
321
322 if (m_hasInterestLifetime) {
323 variableLength = encoder.prependNonNegativeInteger(m_interestLifetime.count());
324 totalLength += variableLength;
325 totalLength += encoder.prependVarNumber(variableLength);
326 totalLength += encoder.prependVarNumber(tlv::InterestLifetime);
327 }
328
Shuo Chenba793e92014-03-17 17:17:16 -0700329 if (!getSelectors().empty()) {
330 totalLength += getSelectors().wireEncode(encoder);
331 }
332
333 if (m_hasName) {
334 totalLength += getName().wireEncode(encoder);
335 }
336
337 totalLength += encoder.prependVarNumber(totalLength);
338 totalLength += encoder.prependVarNumber(tlv::RepoCommandParameter);
339 return totalLength;
340}
341
342inline const Block&
343RepoCommandParameter::wireEncode() const
344{
345 if (m_wire.hasWire())
346 return m_wire;
347
348 EncodingEstimator estimator;
349 size_t estimatedSize = wireEncode(estimator);
350
351 EncodingBuffer buffer(estimatedSize, 0);
352 wireEncode(buffer);
353
354 m_wire = buffer.block();
355 return m_wire;
356}
357
358inline void
359RepoCommandParameter::wireDecode(const Block& wire)
360{
361 m_hasName = false;
362 m_hasStartBlockId = false;
363 m_hasEndBlockId = false;
364 m_hasProcessId = false;
Weiqi Shi098f91c2014-07-23 17:41:35 -0700365 m_hasMaxInterestNum = false;
366 m_hasWatchTimeout = false;
367 m_hasInterestLifetime = false;
Shuo Chenba793e92014-03-17 17:17:16 -0700368
369 m_wire = wire;
370
371 m_wire.parse();
372
373 if (m_wire.type() != tlv::RepoCommandParameter)
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800374 BOOST_THROW_EXCEPTION(Error("Requested decoding of RepoCommandParameter, but Block is of different type"));
Shuo Chenba793e92014-03-17 17:17:16 -0700375
376 // Name
377 Block::element_const_iterator val = m_wire.find(tlv::Name);
378 if (val != m_wire.elements_end())
379 {
380 m_hasName = true;
381 m_name.wireDecode(m_wire.get(tlv::Name));
382 }
383
384 // Selectors
385 val = m_wire.find(tlv::Selectors);
386 if (val != m_wire.elements_end())
387 {
388 m_selectors.wireDecode(*val);
389 }
390 else
391 m_selectors = Selectors();
392
393 // StartBlockId
394 val = m_wire.find(tlv::StartBlockId);
395 if (val != m_wire.elements_end())
396 {
397 m_hasStartBlockId = true;
398 m_startBlockId = readNonNegativeInteger(*val);
399 }
400
401 // EndBlockId
402 val = m_wire.find(tlv::EndBlockId);
403 if (val != m_wire.elements_end())
404 {
405 m_hasEndBlockId = true;
406 m_endBlockId = readNonNegativeInteger(*val);
407 }
408
409 // ProcessId
410 val = m_wire.find(tlv::ProcessId);
411 if (val != m_wire.elements_end())
412 {
413 m_hasProcessId = true;
414 m_processId = readNonNegativeInteger(*val);
415 }
416
Weiqi Shi098f91c2014-07-23 17:41:35 -0700417 // MaxInterestNum
418 val = m_wire.find(tlv::MaxInterestNum);
419 if (val != m_wire.elements_end())
420 {
421 m_hasMaxInterestNum = true;
422 m_maxInterestNum = readNonNegativeInteger(*val);
423 }
424
425 // WatchTimeout
426 val = m_wire.find(tlv::WatchTimeout);
427 if (val != m_wire.elements_end())
428 {
429 m_hasWatchTimeout = true;
430 m_watchTimeout = milliseconds(readNonNegativeInteger(*val));
431 }
432
433 // InterestLiftTime
434 val = m_wire.find(tlv::InterestLifetime);
435 if (val != m_wire.elements_end())
436 {
437 m_hasInterestLifetime = true;
438 m_interestLifetime = milliseconds(readNonNegativeInteger(*val));
439 }
440
441
Shuo Chenba793e92014-03-17 17:17:16 -0700442}
443
444inline std::ostream&
445operator<<(std::ostream& os, const RepoCommandParameter& repoCommandParameter)
446{
447 os << "RepoCommandParameter(";
448
449 // Name
450 if (repoCommandParameter.hasName()) {
451 os << " Name: " << repoCommandParameter.getName();
452 }
453 if (repoCommandParameter.hasStartBlockId()) {
454 // StartBlockId
455 os << " StartBlockId: " << repoCommandParameter.getStartBlockId();
456 }
457 // EndBlockId
458 if (repoCommandParameter.hasEndBlockId()) {
459 os << " EndBlockId: " << repoCommandParameter.getEndBlockId();
460 }
Weiqi Shi098f91c2014-07-23 17:41:35 -0700461 // ProcessId
Shuo Chenba793e92014-03-17 17:17:16 -0700462 if (repoCommandParameter.hasProcessId()) {
463 os << " ProcessId: " << repoCommandParameter.getProcessId();
464 }
Weiqi Shi098f91c2014-07-23 17:41:35 -0700465 // MaxInterestNum
466 if (repoCommandParameter.hasMaxInterestNum()) {
467 os << " MaxInterestNum: " << repoCommandParameter.getMaxInterestNum();
468 }
469 // WatchTimeout
470 if (repoCommandParameter.hasProcessId()) {
471 os << " WatchTimeout: " << repoCommandParameter.getWatchTimeout();
472 }
473 // InterestLifetime
474 if (repoCommandParameter.hasProcessId()) {
475 os << " InterestLifetime: " << repoCommandParameter.getInterestLifetime();
476 }
Shuo Chenba793e92014-03-17 17:17:16 -0700477 os << " )";
478 return os;
479}
480
Alexander Afanasyev39d98072014-05-04 12:46:29 -0700481} // namespace repo
Shuo Chenba793e92014-03-17 17:17:16 -0700482
Alexander Afanasyev39d98072014-05-04 12:46:29 -0700483#endif // REPO_REPO_COMMAND_PARAMETER_HPP