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-2018 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 #include "ndn-cxx/util/sha256.hpp"
25 
26 namespace ndn {
27 
28 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Data>));
29 BOOST_CONCEPT_ASSERT((WireEncodable<Data>));
30 BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Data>));
31 BOOST_CONCEPT_ASSERT((WireDecodable<Data>));
32 static_assert(std::is_base_of<tlv::Error, Data::Error>::value,
33  "Data::Error must inherit from tlv::Error");
34 
36  : m_name(name)
37  , m_content(tlv::Content)
38 {
39 }
40 
41 Data::Data(const Block& wire)
42 {
43  wireDecode(wire);
44 }
45 
46 template<encoding::Tag TAG>
47 size_t
48 Data::wireEncode(EncodingImpl<TAG>& encoder, bool wantUnsignedPortionOnly) const
49 {
50  // Data ::= DATA-TLV TLV-LENGTH
51  // Name
52  // MetaInfo?
53  // Content?
54  // SignatureInfo
55  // SignatureValue
56 
57  size_t totalLength = 0;
58 
59  // SignatureValue
60  if (!wantUnsignedPortionOnly) {
61  if (!m_signature) {
62  BOOST_THROW_EXCEPTION(Error("Requested wire format, but Data has not been signed"));
63  }
64  totalLength += encoder.prependBlock(m_signature.getValue());
65  }
66 
67  // SignatureInfo
68  totalLength += encoder.prependBlock(m_signature.getInfo());
69 
70  // Content
71  totalLength += encoder.prependBlock(getContent());
72 
73  // MetaInfo
74  totalLength += getMetaInfo().wireEncode(encoder);
75 
76  // Name
77  totalLength += getName().wireEncode(encoder);
78 
79  if (!wantUnsignedPortionOnly) {
80  totalLength += encoder.prependVarNumber(totalLength);
81  totalLength += encoder.prependVarNumber(tlv::Data);
82  }
83  return totalLength;
84 }
85 
86 template size_t
87 Data::wireEncode<encoding::EncoderTag>(EncodingBuffer&, bool) const;
88 
89 template size_t
90 Data::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, bool) const;
91 
92 const Block&
93 Data::wireEncode(EncodingBuffer& encoder, const Block& signatureValue) const
94 {
95  size_t totalLength = encoder.size();
96  totalLength += encoder.appendBlock(signatureValue);
97 
98  encoder.prependVarNumber(totalLength);
99  encoder.prependVarNumber(tlv::Data);
100 
101  const_cast<Data*>(this)->wireDecode(encoder.block());
102  return m_wire;
103 }
104 
105 const Block&
107 {
108  if (m_wire.hasWire())
109  return m_wire;
110 
111  EncodingEstimator estimator;
112  size_t estimatedSize = wireEncode(estimator);
113 
114  EncodingBuffer buffer(estimatedSize, 0);
115  wireEncode(buffer);
116 
117  const_cast<Data*>(this)->wireDecode(buffer.block());
118  return m_wire;
119 }
120 
121 void
123 {
124  // Data ::= DATA-TLV TLV-LENGTH
125  // Name
126  // MetaInfo?
127  // Content?
128  // SignatureInfo
129  // SignatureValue
130 
131  m_wire = wire;
132  m_wire.parse();
133 
134  auto element = m_wire.elements_begin();
135  if (element == m_wire.elements_end() || element->type() != tlv::Name) {
136  BOOST_THROW_EXCEPTION(Error("Name element is missing or out of order"));
137  }
138  m_name.wireDecode(*element);
139  int lastElement = 1; // last recognized element index, in spec order
140 
141  m_metaInfo = MetaInfo();
142  m_content = Block(tlv::Content);
143  m_signature = Signature();
144  m_fullName.clear();
145 
146  for (++element; element != m_wire.elements_end(); ++element) {
147  switch (element->type()) {
148  case tlv::MetaInfo: {
149  if (lastElement >= 2) {
150  BOOST_THROW_EXCEPTION(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  BOOST_THROW_EXCEPTION(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  BOOST_THROW_EXCEPTION(Error("SignatureInfo element is out of order"));
167  }
168  m_signature.setInfo(*element);
169  lastElement = 4;
170  break;
171  }
172  case tlv::SignatureValue: {
173  if (lastElement >= 5) {
174  BOOST_THROW_EXCEPTION(Error("SignatureValue element is out of order"));
175  }
176  m_signature.setValue(*element);
177  lastElement = 5;
178  break;
179  }
180  default: {
181  if (tlv::isCriticalType(element->type())) {
182  BOOST_THROW_EXCEPTION(Error("unrecognized element of critical type " +
183  to_string(element->type())));
184  }
185  break;
186  }
187  }
188  }
189 
190  if (!m_signature) {
191  BOOST_THROW_EXCEPTION(Error("SignatureInfo element is missing"));
192  }
193 }
194 
195 const Name&
197 {
198  if (m_fullName.empty()) {
199  if (!m_wire.hasWire()) {
200  BOOST_THROW_EXCEPTION(Error("Cannot compute full name because Data has no wire encoding (not signed)"));
201  }
202  m_fullName = m_name;
203  m_fullName.appendImplicitSha256Digest(util::Sha256::computeDigest(m_wire.wire(), m_wire.size()));
204  }
205 
206  return m_fullName;
207 }
208 
209 void
211 {
212  m_wire.reset();
213  m_fullName.clear();
214 }
215 
216 Data&
218 {
219  resetWire();
220  m_name = name;
221  return *this;
222 }
223 
224 Data&
225 Data::setMetaInfo(const MetaInfo& metaInfo)
226 {
227  resetWire();
228  m_metaInfo = metaInfo;
229  return *this;
230 }
231 
232 const Block&
234 {
235  if (!m_content.hasWire()) {
236  const_cast<Block&>(m_content).encode();
237  }
238  return m_content;
239 }
240 
241 Data&
242 Data::setContent(const Block& block)
243 {
244  resetWire();
245 
246  if (block.type() == tlv::Content) {
247  m_content = block;
248  }
249  else {
250  m_content = Block(tlv::Content, block);
251  }
252 
253  return *this;
254 }
255 
256 Data&
257 Data::setContent(const uint8_t* value, size_t valueSize)
258 {
259  resetWire();
260  m_content = makeBinaryBlock(tlv::Content, value, valueSize);
261  return *this;
262 }
263 
264 Data&
266 {
267  resetWire();
268  m_content = Block(tlv::Content, std::move(value));
269  return *this;
270 }
271 
272 Data&
273 Data::setSignature(const Signature& signature)
274 {
275  resetWire();
276  m_signature = signature;
277  return *this;
278 }
279 
280 Data&
282 {
283  resetWire();
284  m_signature.setValue(value);
285  return *this;
286 }
287 
288 Data&
289 Data::setContentType(uint32_t type)
290 {
291  resetWire();
292  m_metaInfo.setType(type);
293  return *this;
294 }
295 
296 Data&
297 Data::setFreshnessPeriod(time::milliseconds freshnessPeriod)
298 {
299  resetWire();
300  m_metaInfo.setFreshnessPeriod(freshnessPeriod);
301  return *this;
302 }
303 
304 Data&
305 Data::setFinalBlock(optional<name::Component> finalBlockId)
306 {
307  resetWire();
308  m_metaInfo.setFinalBlock(std::move(finalBlockId));
309  return *this;
310 }
311 
312 bool
313 operator==(const Data& lhs, const Data& rhs)
314 {
315  return lhs.getName() == rhs.getName() &&
316  lhs.getMetaInfo() == rhs.getMetaInfo() &&
317  lhs.getContent() == rhs.getContent() &&
318  lhs.getSignature() == rhs.getSignature();
319 }
320 
321 std::ostream&
322 operator<<(std::ostream& os, const Data& data)
323 {
324  os << "Name: " << data.getName() << "\n";
325  os << "MetaInfo: " << data.getMetaInfo() << "\n";
326  os << "Content: (size: " << data.getContent().value_size() << ")\n";
327  os << "Signature: (type: " << data.getSignature().getType()
328  << ", value_length: "<< data.getSignature().getValue().value_size() << ")";
329  os << std::endl;
330 
331  return os;
332 }
333 
334 } // namespace ndn
const Block & wireEncode() const
Encode to a Block.
Definition: data.cpp:106
bool hasWire() const
Check if the Block has fully encoded wire.
Definition: block.cpp:249
Data & setContentType(uint32_t type)
Definition: data.cpp:289
Copyright (c) 2011-2015 Regents of the University of California.
const Name & getName() const
Get name.
Definition: data.hpp:124
void wireDecode(const Block &wire)
Decode from wire in NDN Packet Format v0.2 or v0.3.
Definition: data.cpp:122
const Block & getContent() const
Get Content.
Definition: data.cpp:233
Data & setSignature(const Signature &signature)
Set Signature.
Definition: data.cpp:273
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:171
Data & setName(const Name &name)
Set name.
Definition: data.cpp:217
size_t value_size() const
Get size of TLV-VALUE aka TLV-LENGTH.
Definition: block.cpp:316
Name & appendImplicitSha256Digest(ConstBufferPtr digest)
Append an ImplicitSha256Digest component.
Definition: name.hpp:408
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition: data.cpp:322
void setInfo(const Block &info)
Decode SignatureInfo from wire format.
Definition: signature.cpp:53
Data(const Name &name=Name())
Construct an unsigned Data packet with given name and empty Content.
Definition: data.cpp:35
Data & setContent(const Block &block)
Set Content from a block.
Definition: data.cpp:242
const uint8_t * wire() const
Get pointer to encoded wire.
Definition: block.cpp:289
void parse() const
Parse TLV-VALUE into sub elements.
Definition: block.cpp:333
void resetWire()
Clear wire encoding and cached FullName.
Definition: data.cpp:210
Represents a TLV element of NDN packet format.
Definition: block.hpp:42
element_const_iterator elements_begin() const
Equivalent to elements().begin()
Definition: block.hpp:369
MetaInfo & setFreshnessPeriod(time::milliseconds freshnessPeriod)
set FreshnessPeriod
Definition: meta-info.cpp:55
tlv::SignatureTypeValue getType() const
Get SignatureType.
Definition: signature.cpp:44
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:60
size_t size() const
Get size of encoded wire, including Type-Length-Value.
Definition: block.cpp:298
element_const_iterator elements_end() const
Equivalent to elements().end()
Definition: block.hpp:377
Data & setSignatureValue(const Block &value)
Set SignatureValue.
Definition: data.cpp:281
const Signature & getSignature() const
Get Signature.
Definition: data.hpp:185
MetaInfo & setType(uint32_t type)
set ContentType
Definition: meta-info.cpp:47
void setValue(const Block &value)
Set SignatureValue.
Definition: signature.cpp:59
Block makeBinaryBlock(uint32_t type, const uint8_t *value, size_t length)
Create a TLV block copying TLV-VALUE from raw buffer.
const Block & getInfo() const
Get SignatureInfo as wire format.
Definition: signature.hpp:73
const Block & getValue() const
Get SignatureValue.
Definition: signature.hpp:95
A MetaInfo holds the meta info which is signed inside the data packet.
Definition: meta-info.hpp:58
void reset()
Reset wire buffer of the element.
Definition: block.cpp:255
Represents an absolute name.
Definition: name.hpp:43
const Name & getFullName() const
Get full name including implicit digest.
Definition: data.cpp:196
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Definition: meta-info.cpp:127
Data & setFreshnessPeriod(time::milliseconds freshnessPeriod)
Definition: data.cpp:297
void encode()
Encode sub elements into TLV-VALUE.
Definition: block.cpp:361
Data & setFinalBlock(optional< name::Component > finalBlockId)
Definition: data.cpp:305
const MetaInfo & getMetaInfo() const
Get MetaInfo.
Definition: data.hpp:138
bool empty() const
Check if name is empty.
Definition: name.hpp:139
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:313
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:125
std::string to_string(const V &v)
Definition: backports.hpp:67
Data & setMetaInfo(const MetaInfo &metaInfo)
Set MetaInfo.
Definition: data.cpp:225
void wireDecode(const Block &wire)
Decode name from wire encoding.
Definition: name.cpp:158
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:44
Represents a Data packet.
Definition: data.hpp:35
a concept check for TLV abstraction with .wireDecode method and constructible from Block
Definition: concepts.hpp:80
void clear()
Remove all components.
Definition: name.hpp:443
EncodingImpl< EncoderTag > EncodingBuffer
uint32_t type() const
Get TLV-TYPE.
Definition: block.hpp:249
EncodingImpl< EstimatorTag > EncodingEstimator
Holds SignatureInfo and SignatureValue in a Data packet.
Definition: signature.hpp:37
void wireDecode(const Block &wire)
Definition: meta-info.cpp:181
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:126