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