blob: f0d15a7a303c4b3e8179565d386148c4d0d7cf9b [file] [log] [blame]
Shuo Chenba793e92014-03-17 17:17:16 -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 REPO_HELPERS_REPO_COMMAND_RESPONSE_HPP
8#define REPO_HELPERS_REPO_COMMAND_RESPONSE_HPP
9
Alexander Afanasyeve291caf2014-04-25 11:17:36 -070010#include <ndn-cxx/encoding/block.hpp>
11#include <ndn-cxx/encoding/encoding-buffer.hpp>
12#include <ndn-cxx/encoding/tlv-nfd.hpp>
Shuo Chenba793e92014-03-17 17:17:16 -070013#include "repo-tlv.hpp"
14
15namespace repo {
16
17using ndn::Block;
18using ndn::EncodingImpl;
19using ndn::EncodingEstimator;
20using ndn::EncodingBuffer;
21
22/**
23* @brief Class defining abstraction of Response for NDN Repo Protocol
24* @sa link http://redmine.named-data.net/projects/repo-ng/wiki/Repo_Protocol_Specification#Repo-Command-Response
25*/
26class RepoCommandResponse
27{
28public:
29 class Error : public ndn::Tlv::Error
30 {
31 public:
32 explicit
33 Error(const std::string& what)
34 : ndn::Tlv::Error(what)
35 {
36 }
37 };
38
39 RepoCommandResponse()
40 : m_hasStartBlockId(false)
41 , m_hasEndBlockId(false)
42 , m_hasProcessId(false)
43 , m_hasInsertNum(false)
44 , m_hasDeleteNum(false)
45 , m_hasStatusCode(false)
46 {
47 }
48
49 explicit
50 RepoCommandResponse(const Block& block)
51 {
52 wireDecode(block);
53 }
54
55 uint64_t
56 getStartBlockId() const
57 {
58 return m_startBlockId;
59 }
60
61 RepoCommandResponse&
62 setStartBlockId(uint64_t startBlockId)
63 {
64 m_startBlockId = startBlockId;
65 m_hasStartBlockId = true;
66 m_wire.reset();
67 return *this;
68 }
69
70 bool
71 hasStartBlockId() const
72 {
73 return m_hasStartBlockId;
74 }
75
76 uint64_t
77 getEndBlockId() const
78 {
79 assert(hasEndBlockId());
80 return m_endBlockId;
81 }
82
83 RepoCommandResponse&
84 setEndBlockId(uint64_t endBlockId)
85 {
86 m_endBlockId = endBlockId;
87 m_hasEndBlockId = true;
88 m_wire.reset();
89 return *this;
90 }
91
92 bool
93 hasEndBlockId() const
94 {
95 return m_hasEndBlockId;
96 }
97
98
99 uint64_t
100 getProcessId() const
101 {
102 return m_processId;
103 }
104
105 RepoCommandResponse&
106 setProcessId(uint64_t processId)
107 {
108 m_processId = processId;
109 m_hasProcessId = true;
110 m_wire.reset();
111 return *this;
112 }
113
114 bool
115 hasProcessId() const
116 {
117 return m_hasProcessId;
118 }
119
120 uint64_t
121 getStatusCode() const
122 {
123 return m_statusCode;
124 }
125
126 RepoCommandResponse&
127 setStatusCode(uint64_t statusCode)
128 {
129 m_statusCode = statusCode;
130 m_hasStatusCode = true;
131 m_wire.reset();
132 return *this;
133 }
134
135 bool
136 hasStatusCode() const
137 {
138 return m_hasStatusCode;
139 }
140
141 uint64_t
142 getInsertNum() const
143 {
144 return m_insertNum;
145 }
146
147 RepoCommandResponse&
148 setInsertNum(uint64_t insertNum)
149 {
150 m_insertNum = insertNum;
151 m_hasInsertNum = true;
152 m_wire.reset();
153 return *this;
154 }
155
156 bool
157 hasInsertNum() const
158 {
159 return m_hasInsertNum;
160 }
161
162 uint64_t
163 getDeleteNum() const
164 {
165 return m_deleteNum;
166 }
167
168 RepoCommandResponse&
169 setDeleteNum(uint64_t deleteNum)
170 {
171 m_deleteNum = deleteNum;
172 m_hasDeleteNum = true;
173 m_wire.reset();
174 return *this;
175 }
176
177 bool
178 hasDeleteNum() const
179 {
180 return m_hasDeleteNum;
181 }
182
183 template<bool T>
184 size_t
185 wireEncode(EncodingImpl<T>& block) const;
186
187 const Block&
188 wireEncode() const;
189
190 void
191 wireDecode(const Block& wire);
192
193private:
194 uint64_t m_statusCode;
195 uint64_t m_startBlockId;
196 uint64_t m_endBlockId;
197 uint64_t m_processId;
198 uint64_t m_insertNum;
199 uint64_t m_deleteNum;
200
201 bool m_hasStartBlockId;
202 bool m_hasEndBlockId;
203 bool m_hasProcessId;
204 bool m_hasInsertNum;
205 bool m_hasDeleteNum;
206 bool m_hasStatusCode;
207
208 mutable Block m_wire;
209};
210
211template<bool T>
212inline size_t
213RepoCommandResponse::wireEncode(EncodingImpl<T>& encoder) const
214{
215 size_t totalLength = 0;
216 size_t variableLength = 0;
217
218 if (m_hasDeleteNum) {
219 variableLength = encoder.prependNonNegativeInteger(m_deleteNum);
220 totalLength += variableLength;
221 totalLength += encoder.prependVarNumber(variableLength);
222 totalLength += encoder.prependVarNumber(tlv::DeleteNum);
223 }
224
225 if (m_hasInsertNum) {
226 variableLength = encoder.prependNonNegativeInteger(m_insertNum);
227 totalLength += variableLength;
228 totalLength += encoder.prependVarNumber(variableLength);
229 totalLength += encoder.prependVarNumber(tlv::InsertNum);
230 }
231
232 if (m_hasEndBlockId) {
233 variableLength = encoder.prependNonNegativeInteger(m_endBlockId);
234 totalLength += variableLength;
235 totalLength += encoder.prependVarNumber(variableLength);
236 totalLength += encoder.prependVarNumber(tlv::EndBlockId);
237 }
238
239 if (m_hasStartBlockId) {
240 variableLength = encoder.prependNonNegativeInteger(m_startBlockId);
241 totalLength += variableLength;
242 totalLength += encoder.prependVarNumber(variableLength);
243 totalLength += encoder.prependVarNumber(repo::tlv::StartBlockId);
244 }
245
246 if (m_hasStatusCode) {
247 variableLength = encoder.prependNonNegativeInteger(m_statusCode);
248 totalLength += variableLength;
249 totalLength += encoder.prependVarNumber(variableLength);
250 totalLength += encoder.prependVarNumber(tlv::StatusCode);
251 } else {
252 throw Error("required field StatusCode is missing");
253 }
254
255 if (m_hasProcessId) {
256 variableLength = encoder.prependNonNegativeInteger(m_processId);
257 totalLength += variableLength;
258 totalLength += encoder.prependVarNumber(variableLength);
259 totalLength += encoder.prependVarNumber(tlv::ProcessId);
260 }
261
262 totalLength += encoder.prependVarNumber(totalLength);
263 totalLength += encoder.prependVarNumber(tlv::RepoCommandResponse);
264 return totalLength;
265}
266
267inline const Block&
268RepoCommandResponse::wireEncode() const
269{
270 if (m_wire.hasWire())
271 return m_wire;
272
273 EncodingEstimator estimator;
274 size_t estimatedSize = wireEncode(estimator);
275
276 EncodingBuffer buffer(estimatedSize, 0);
277 wireEncode(buffer);
278
279 m_wire = buffer.block();
280 return m_wire;
281}
282
283inline void
284RepoCommandResponse::wireDecode(const Block& wire)
285{
286 m_hasStartBlockId = false;
287 m_hasEndBlockId = false;
288 m_hasProcessId = false;
289 m_hasStatusCode = false;
290 m_hasInsertNum = false;
291 m_hasDeleteNum = false;
292
293 m_wire = wire;
294
295 m_wire.parse();
296
297 Block::element_const_iterator val;
298
299 if (m_wire.type() != tlv::RepoCommandResponse)
300 throw Error("RepoCommandResponse malformed");
301
302 // StartBlockId
303 val = m_wire.find(tlv::StartBlockId);
304 if (val != m_wire.elements_end())
305 {
306 m_hasStartBlockId = true;
307 m_startBlockId = readNonNegativeInteger(*val);
308 }
309
310 // EndBlockId
311 val = m_wire.find(tlv::EndBlockId);
312 if (val != m_wire.elements_end())
313 {
314 m_hasEndBlockId = true;
315 m_endBlockId = readNonNegativeInteger(*val);
316 }
317
318 // ProcessId
319 val = m_wire.find(tlv::ProcessId);
320 if (val != m_wire.elements_end())
321 {
322 m_hasProcessId = true;
323 m_processId = readNonNegativeInteger(*val);
324 }
325
326 // StatusCode
327 val = m_wire.find(tlv::StatusCode);
328 if (val != m_wire.elements_end())
329 {
330 m_hasStatusCode = true;
331 m_statusCode = readNonNegativeInteger(*val);
332
333 } else {
334 throw Error("required field StatusCode is missing");
335 }
336
337 // InsertNum
338 val = m_wire.find(tlv::InsertNum);
339 if (val != m_wire.elements_end())
340 {
341 m_hasInsertNum = true;
342 m_insertNum = readNonNegativeInteger(*val);
343 }
344
345 // DeleteNum
346 val = m_wire.find(tlv::DeleteNum);
347 if (val != m_wire.elements_end())
348 {
349 m_hasDeleteNum = true;
350 m_deleteNum = readNonNegativeInteger(*val);
351 }
352}
353
354inline std::ostream&
355operator<<(std::ostream& os, const RepoCommandResponse& repoCommandResponse)
356{
357 os << "RepoCommandResponse(";
358
359 if (repoCommandResponse.hasProcessId()) {
360 os << " ProcessId: " << repoCommandResponse.getProcessId();
361 }
362 if (repoCommandResponse.hasStatusCode()) {
363 os << " StatusCode: " << repoCommandResponse.getStatusCode();
364 }
365 if (repoCommandResponse.hasStartBlockId()) {
366 os << " StartBlockId: " << repoCommandResponse.getStartBlockId();
367 }
368 if (repoCommandResponse.hasEndBlockId()) {
369 os << " EndBlockId: " << repoCommandResponse.getEndBlockId();
370 }
371 if (repoCommandResponse.hasInsertNum()) {
372 os << " InsertNum: " << repoCommandResponse.getInsertNum();
373 }
374 if (repoCommandResponse.hasDeleteNum()) {
375 os << " DeleteNum: " << repoCommandResponse.getDeleteNum();
376
377 }
378 os << " )";
379 return os;
380}
381} //namespace repo
382#endif