ndn-cxx: NDN C++ Library 0.9.0-33-g832ea91d
Loading...
Searching...
No Matches
data.cpp
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2013-2023 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "ndn-cxx/data.hpp"
24
25namespace ndn {
26
27Data::Data(const Name& name)
28 : m_name(name)
29{
30}
31
32Data::Data(const Block& wire)
33{
34 wireDecode(wire);
35}
36
37template<encoding::Tag TAG>
38size_t
39Data::wireEncode(EncodingImpl<TAG>& encoder, bool wantUnsignedPortionOnly) const
40{
41 // Data = DATA-TYPE TLV-LENGTH
42 // Name
43 // [MetaInfo]
44 // [Content]
45 // SignatureInfo
46 // SignatureValue
47 // (elements are encoded in reverse order)
48
49 size_t totalLength = 0;
50
51 // SignatureValue
52 if (!wantUnsignedPortionOnly) {
53 if (!m_signatureInfo) {
54 NDN_THROW(Error("Requested wire format, but Data has not been signed"));
55 }
56 totalLength += prependBlock(encoder, m_signatureValue);
57 }
58
59 // SignatureInfo
60 totalLength += m_signatureInfo.wireEncode(encoder, SignatureInfo::Type::Data);
61
62 // Content
63 if (hasContent()) {
64 totalLength += prependBlock(encoder, m_content);
65 }
66
67 // MetaInfo
68 totalLength += m_metaInfo.wireEncode(encoder);
69
70 // Name
71 totalLength += m_name.wireEncode(encoder);
72
73 if (!wantUnsignedPortionOnly) {
74 totalLength += encoder.prependVarNumber(totalLength);
75 totalLength += encoder.prependVarNumber(tlv::Data);
76 }
77 return totalLength;
78}
79
80template size_t
81Data::wireEncode<encoding::EncoderTag>(EncodingBuffer&, bool) const;
82
83template size_t
84Data::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, bool) const;
85
86const Block&
87Data::wireEncode(EncodingBuffer& encoder, span<const uint8_t> signature) const
88{
89 size_t totalLength = encoder.size();
90 totalLength += encoder.appendVarNumber(tlv::SignatureValue);
91 totalLength += encoder.appendVarNumber(signature.size());
92 totalLength += encoder.appendBytes(signature);
93
94 encoder.prependVarNumber(totalLength);
95 encoder.prependVarNumber(tlv::Data);
96
97 const_cast<Data*>(this)->wireDecode(encoder.block());
98 return m_wire;
99}
100
101const Block&
103{
104 if (m_wire.hasWire())
105 return m_wire;
106
107 EncodingEstimator estimator;
108 size_t estimatedSize = wireEncode(estimator);
109
110 EncodingBuffer buffer(estimatedSize, 0);
111 wireEncode(buffer);
112
113 const_cast<Data*>(this)->wireDecode(buffer.block());
114 return m_wire;
115}
116
117void
119{
120 if (wire.type() != tlv::Data) {
121 NDN_THROW(Error("Data", wire.type()));
122 }
123 m_wire = wire;
124 m_wire.parse();
125
126 // Data = DATA-TYPE TLV-LENGTH
127 // Name
128 // [MetaInfo]
129 // [Content]
130 // SignatureInfo
131 // SignatureValue
132
133 auto element = m_wire.elements_begin();
134 if (element == m_wire.elements_end() || element->type() != tlv::Name) {
135 NDN_THROW(Error("Name element is missing or out of order"));
136 }
137 m_name.wireDecode(*element);
138
139 m_metaInfo = {};
140 m_content = {};
141 m_signatureInfo = {};
142 m_signatureValue = {};
143 m_fullName.clear();
144
145 int lastElement = 1; // last recognized element index, in spec order
146 for (++element; element != m_wire.elements_end(); ++element) {
147 switch (element->type()) {
148 case tlv::MetaInfo: {
149 if (lastElement >= 2) {
150 NDN_THROW(Error("MetaInfo element is out of order"));
151 }
152 m_metaInfo.wireDecode(*element);
153 lastElement = 2;
154 break;
155 }
156 case tlv::Content: {
157 if (lastElement >= 3) {
158 NDN_THROW(Error("Content element is out of order"));
159 }
160 m_content = *element;
161 lastElement = 3;
162 break;
163 }
164 case tlv::SignatureInfo: {
165 if (lastElement >= 4) {
166 NDN_THROW(Error("SignatureInfo element is out of order"));
167 }
168 m_signatureInfo.wireDecode(*element);
169 lastElement = 4;
170 break;
171 }
172 case tlv::SignatureValue: {
173 if (lastElement >= 5) {
174 NDN_THROW(Error("SignatureValue element is out of order"));
175 }
176 m_signatureValue = *element;
177 lastElement = 5;
178 break;
179 }
180 default: { // unrecognized element
181 // if the TLV-TYPE is critical, abort decoding
182 if (tlv::isCriticalType(element->type())) {
183 NDN_THROW(Error("Unrecognized element of critical type " + to_string(element->type())));
184 }
185 // otherwise, ignore it
186 break;
187 }
188 }
189 }
190
191 if (!m_signatureInfo) {
192 NDN_THROW(Error("SignatureInfo element is missing"));
193 }
194 if (!m_signatureValue.isValid()) {
195 NDN_THROW(Error("SignatureValue element is missing"));
196 }
197}
198
199const Name&
201{
202 if (m_fullName.empty()) {
203 if (!m_wire.hasWire()) {
204 NDN_THROW(Error("Cannot compute full name because Data has no wire encoding (not signed)"));
205 }
206 m_fullName = m_name;
208 }
209
210 return m_fullName;
211}
212
213void
215{
216 m_wire.reset();
217 m_fullName.clear();
218}
219
220Data&
221Data::setName(const Name& name)
222{
223 if (name != m_name) {
224 m_name = name;
225 resetWire();
226 }
227 return *this;
228}
229
230Data&
232{
233 m_metaInfo = metaInfo;
234 resetWire();
235 return *this;
236}
237
238Data&
240{
241 if (!block.isValid()) {
242 NDN_THROW(std::invalid_argument("Content block must be valid"));
243 }
244
245 if (block.type() == tlv::Content) {
246 m_content = block;
247 }
248 else {
249 m_content = Block(tlv::Content, block);
250 }
251 m_content.encode();
252 resetWire();
253 return *this;
254}
255
256Data&
257Data::setContent(span<const uint8_t> value)
258{
259 m_content = makeBinaryBlock(tlv::Content, value);
260 resetWire();
261 return *this;
262}
263
264Data&
265Data::setContent(std::string_view value)
266{
267 m_content = makeStringBlock(tlv::Content, value);
268 resetWire();
269 return *this;
270}
271
272Data&
274{
275 if (!value) {
276 NDN_THROW(std::invalid_argument("Content buffer cannot be null"));
277 }
278
279 m_content = Block(tlv::Content, std::move(value));
280 resetWire();
281 return *this;
282}
283
284Data&
286{
287 if (m_content.isValid()) {
288 m_content = {};
289 resetWire();
290 }
291 return *this;
292}
293
294Data&
296{
297 m_signatureInfo = info;
298 resetWire();
299 return *this;
300}
301
302Data&
303Data::setSignatureValue(span<const uint8_t> value)
304{
305 m_signatureValue = makeBinaryBlock(tlv::SignatureValue, value);
306 resetWire();
307 return *this;
308}
309
310Data&
312{
313 if (!value) {
314 NDN_THROW(std::invalid_argument("SignatureValue buffer cannot be null"));
315 }
316
317 m_signatureValue = Block(tlv::SignatureValue, std::move(value));
318 resetWire();
319 return *this;
320}
321
322InputBuffers
324{
325 InputBuffers bufs;
326 bufs.reserve(1); // One range containing data value up to, but not including, SignatureValue
327
328 wireEncode();
329 auto lastSignedIt = std::prev(m_wire.find(tlv::SignatureValue));
330 // Note: we assume that both iterators point to the same underlying buffer
331 bufs.emplace_back(m_wire.value_begin(), lastSignedIt->end());
332
333 return bufs;
334}
335
336Data&
338{
339 if (type != m_metaInfo.getType()) {
340 m_metaInfo.setType(type);
341 resetWire();
342 }
343 return *this;
344}
345
346Data&
348{
349 if (freshnessPeriod != m_metaInfo.getFreshnessPeriod()) {
350 m_metaInfo.setFreshnessPeriod(freshnessPeriod);
351 resetWire();
352 }
353 return *this;
354}
355
356Data&
357Data::setFinalBlock(std::optional<name::Component> finalBlockId)
358{
359 if (finalBlockId != m_metaInfo.getFinalBlock()) {
360 m_metaInfo.setFinalBlock(std::move(finalBlockId));
361 resetWire();
362 }
363 return *this;
364}
365
366bool
367operator==(const Data& lhs, const Data& rhs)
368{
369 return lhs.getName() == rhs.getName() &&
370 lhs.getMetaInfo().wireEncode() == rhs.getMetaInfo().wireEncode() &&
371 lhs.getContent() == rhs.getContent() &&
372 lhs.getSignatureInfo() == rhs.getSignatureInfo() &&
374}
375
376std::ostream&
377operator<<(std::ostream& os, const Data& data)
378{
379 os << "Name: " << data.getName() << "\n"
380 << "MetaInfo: [" << data.getMetaInfo() << "]\n";
381
382 if (data.hasContent()) {
383 os << "Content: [" << data.getContent().value_size() << " bytes]\n";
384 }
385
386 os << "Signature: [type: " << static_cast<tlv::SignatureTypeValue>(data.getSignatureType())
387 << ", length: "<< data.getSignatureValue().value_size() << "]\n";
388
389 return os;
390}
391
392} // namespace ndn
Represents a TLV element of the NDN packet format.
Definition block.hpp:45
element_const_iterator elements_begin() const noexcept
Equivalent to elements().begin().
Definition block.hpp:433
element_const_iterator find(uint32_t type) const
Find the first sub-element of the specified TLV-TYPE.
Definition block.cpp:425
size_t size() const
Returns the size of the encoded wire, i.e., of the whole TLV.
Definition block.cpp:265
element_const_iterator elements_end() const noexcept
Equivalent to elements().end().
Definition block.hpp:442
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
Definition block.hpp:205
bool isValid() const noexcept
Check if the Block is valid.
Definition block.hpp:193
void encode()
Encode sub-elements into TLV-VALUE.
Definition block.cpp:353
uint32_t type() const noexcept
Return the TLV-TYPE of the Block.
Definition block.hpp:275
void reset() noexcept
Reset the Block to a default-constructed state.
Definition block.cpp:293
void parse() const
Parse TLV-VALUE into sub-elements.
Definition block.cpp:326
const_iterator value_begin() const noexcept
Get begin iterator of TLV-VALUE.
Definition block.hpp:328
size_t value_size() const noexcept
Return the size of TLV-VALUE, i.e., the TLV-LENGTH.
Definition block.hpp:299
Represents a Data packet.
Definition data.hpp:39
int32_t getSignatureType() const noexcept
Get the SignatureType.
Definition data.hpp:358
const Block & getSignatureValue() const noexcept
Get the SignatureValue element.
Definition data.hpp:265
void wireDecode(const Block &wire)
Decode from wire.
Definition data.cpp:118
InputBuffers extractSignedRanges() const
Extract ranges of Data covered by the signature.
Definition data.cpp:323
Data & setContent(const Block &block)
Set Content from a Block.
Definition data.cpp:239
Data(const Name &name=Name())
Construct an unsigned Data packet with given name and empty Content.
Definition data.cpp:27
const Name & getName() const noexcept
Get the Data name.
Definition data.hpp:137
void resetWire()
Clear wire encoding and cached FullName.
Definition data.cpp:214
Data & setFreshnessPeriod(time::milliseconds freshnessPeriod)
Set the FreshnessPeriod.
Definition data.cpp:347
const Block & getContent() const noexcept
Get the Content element.
Definition data.hpp:188
const Block & wireEncode() const
Encode into a Block.
Definition data.cpp:102
const Name & getFullName() const
Get the full name (including implicit digest).
Definition data.cpp:200
bool hasContent() const noexcept
Return whether this Data has a Content element.
Definition data.hpp:169
Data & setFinalBlock(std::optional< name::Component > finalBlockId)
Set the FinalBlockId.
Definition data.cpp:357
Data & setSignatureValue(span< const uint8_t > value)
Set SignatureValue by copying from a contiguous sequence of bytes.
Definition data.cpp:303
Data & setSignatureInfo(const SignatureInfo &info)
Set the SignatureInfo element.
Definition data.cpp:295
const MetaInfo & getMetaInfo() const noexcept
Get the MetaInfo element.
Definition data.hpp:153
const SignatureInfo & getSignatureInfo() const noexcept
Get the SignatureInfo element.
Definition data.hpp:243
Data & setName(const Name &name)
Set the Data name.
Definition data.cpp:221
Data & setContentType(uint32_t type)
Set the ContentType.
Definition data.cpp:337
Data & setMetaInfo(const MetaInfo &metaInfo)
Set the MetaInfo element.
Definition data.cpp:231
Data & unsetContent()
Remove the Content element.
Definition data.cpp:285
A MetaInfo holds the meta info which is signed inside the Data packet.
Definition meta-info.hpp:62
uint32_t getType() const noexcept
Return the value of ContentType.
Definition meta-info.hpp:95
void wireDecode(const Block &wire)
MetaInfo & setFinalBlock(std::optional< name::Component > finalBlockId)
Set the FinalBlockId.
Definition meta-info.cpp:66
MetaInfo & setType(uint32_t type)
Set the ContentType.
Definition meta-info.cpp:38
const std::optional< name::Component > & getFinalBlock() const noexcept
Return the value of FinalBlockId.
time::milliseconds getFreshnessPeriod() const noexcept
Return the value of FreshnessPeriod.
Definition meta-info.cpp:46
MetaInfo & setFreshnessPeriod(time::milliseconds freshnessPeriod)
Set the FreshnessPeriod.
Definition meta-info.cpp:55
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Represents an absolute name.
Definition name.hpp:45
bool empty() const noexcept
Checks if the name is empty, i.e., has no components.
Definition name.hpp:171
void clear()
Remove all components.
Definition name.cpp:256
Name & appendImplicitSha256Digest(ConstBufferPtr digest)
Append an ImplicitSha256Digest component.
Definition name.hpp:486
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Prepend wire encoding to encoder.
Definition name.cpp:92
void wireDecode(const Block &wire)
Decode name from wire encoding.
Definition name.cpp:125
Represents a SignatureInfo or InterestSignatureInfo TLV element.
size_t wireEncode(EncodingImpl< TAG > &encoder, Type type=Type::Data) const
Fast encoding or block size estimation.
void wireDecode(const Block &wire, Type type=Type::Data)
Decode from wire format.
ConstBufferPtr computeDigest()
Finalize and return the digest based on all previously supplied inputs.
Definition sha256.cpp:61
#define NDN_THROW(e)
Definition exception.hpp:56
::boost::chrono::milliseconds milliseconds
Definition time.hpp:52
@ Name
Definition tlv.hpp:71
@ SignatureInfo
Definition tlv.hpp:94
@ Data
Definition tlv.hpp:69
@ Content
Definition tlv.hpp:93
@ MetaInfo
Definition tlv.hpp:92
@ SignatureValue
Definition tlv.hpp:95
constexpr bool isCriticalType(uint32_t type) noexcept
Determine whether a TLV-TYPE is "critical" for evolvability purpose.
Definition tlv.hpp:162
SignatureTypeValue
SignatureType values.
Definition tlv.hpp:127
Definition data.cpp:25
bool operator==(const Data &lhs, const Data &rhs)
Definition data.cpp:367
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition data.cpp:377
std::shared_ptr< const Buffer > ConstBufferPtr
Definition buffer.hpp:140
InputBuffers bufs
SignatureInfo info