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