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 "data.hpp"
24 #include "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 
35 Data::Data(const Name& name)
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  m_wire = wire;
125  m_wire.parse();
126  bool hasName = false, hasSigInfo = false;
127  m_name.clear();
128  m_metaInfo = MetaInfo();
129  m_content = Block(tlv::Content);
130  m_signature = Signature();
131  m_fullName.clear();
132 
133  int lastEle = 0; // last recognized element index, in spec order
134  for (const Block& ele : m_wire.elements()) {
135  switch (ele.type()) {
136  case tlv::Name: {
137  if (lastEle >= 1) {
138  BOOST_THROW_EXCEPTION(Error("Name element is out of order"));
139  }
140  hasName = true;
141  m_name.wireDecode(ele);
142  lastEle = 1;
143  break;
144  }
145  case tlv::MetaInfo: {
146  if (lastEle >= 2) {
147  BOOST_THROW_EXCEPTION(Error("MetaInfo element is out of order"));
148  }
149  m_metaInfo.wireDecode(ele);
150  lastEle = 2;
151  break;
152  }
153  case tlv::Content: {
154  if (lastEle >= 3) {
155  BOOST_THROW_EXCEPTION(Error("Content element is out of order"));
156  }
157  m_content = ele;
158  lastEle = 3;
159  break;
160  }
161  case tlv::SignatureInfo: {
162  if (lastEle >= 4) {
163  BOOST_THROW_EXCEPTION(Error("SignatureInfo element is out of order"));
164  }
165  hasSigInfo = true;
166  m_signature.setInfo(ele);
167  lastEle = 4;
168  break;
169  }
170  case tlv::SignatureValue: {
171  if (lastEle >= 5) {
172  BOOST_THROW_EXCEPTION(Error("SignatureValue element is out of order"));
173  }
174  m_signature.setValue(ele);
175  lastEle = 5;
176  break;
177  }
178  default: {
179  if (tlv::isCriticalType(ele.type())) {
180  BOOST_THROW_EXCEPTION(Error("unrecognized element of critical type " +
181  to_string(ele.type())));
182  }
183  break;
184  }
185  }
186  }
187 
188  if (!hasName) {
189  BOOST_THROW_EXCEPTION(Error("Name element is missing"));
190  }
191  if (!hasSigInfo) {
192  BOOST_THROW_EXCEPTION(Error("SignatureInfo element is missing"));
193  }
194 }
195 
196 const Name&
198 {
199  if (m_fullName.empty()) {
200  if (!m_wire.hasWire()) {
201  BOOST_THROW_EXCEPTION(Error("Cannot compute full name because Data has no wire encoding (not signed)"));
202  }
203  m_fullName = m_name;
204  m_fullName.appendImplicitSha256Digest(util::Sha256::computeDigest(m_wire.wire(), m_wire.size()));
205  }
206 
207  return m_fullName;
208 }
209 
210 void
212 {
213  m_wire.reset();
214  m_fullName.clear();
215 }
216 
217 Data&
218 Data::setName(const Name& name)
219 {
220  resetWire();
221  m_name = name;
222  return *this;
223 }
224 
225 Data&
226 Data::setMetaInfo(const MetaInfo& metaInfo)
227 {
228  resetWire();
229  m_metaInfo = metaInfo;
230  return *this;
231 }
232 
233 const Block&
235 {
236  if (!m_content.hasWire()) {
237  const_cast<Block&>(m_content).encode();
238  }
239  return m_content;
240 }
241 
242 Data&
243 Data::setContent(const Block& block)
244 {
245  resetWire();
246 
247  if (block.type() == tlv::Content) {
248  m_content = block;
249  }
250  else {
251  m_content = Block(tlv::Content, block);
252  }
253 
254  return *this;
255 }
256 
257 Data&
258 Data::setContent(const uint8_t* value, size_t valueSize)
259 {
260  resetWire();
261  m_content = makeBinaryBlock(tlv::Content, value, valueSize);
262  return *this;
263 }
264 
265 Data&
267 {
268  resetWire();
269  m_content = Block(tlv::Content, value);
270  return *this;
271 }
272 
273 Data&
274 Data::setSignature(const Signature& signature)
275 {
276  resetWire();
277  m_signature = signature;
278  return *this;
279 }
280 
281 Data&
283 {
284  resetWire();
285  m_signature.setValue(value);
286  return *this;
287 }
288 
289 Data&
290 Data::setContentType(uint32_t type)
291 {
292  resetWire();
293  m_metaInfo.setType(type);
294  return *this;
295 }
296 
297 Data&
298 Data::setFreshnessPeriod(time::milliseconds freshnessPeriod)
299 {
300  resetWire();
301  m_metaInfo.setFreshnessPeriod(freshnessPeriod);
302  return *this;
303 }
304 
305 Data&
307 {
308  resetWire();
309  m_metaInfo.setFinalBlock(std::move(finalBlockId));
310  return *this;
311 }
312 
315 {
316  return m_metaInfo.getFinalBlockId();
317 }
318 
319 Data&
321 {
322  resetWire();
323  m_metaInfo.setFinalBlockId(finalBlockId);
324  return *this;
325 }
326 
327 bool
328 operator==(const Data& lhs, const Data& rhs)
329 {
330  return lhs.getName() == rhs.getName() &&
331  lhs.getMetaInfo() == rhs.getMetaInfo() &&
332  lhs.getContent() == rhs.getContent() &&
333  lhs.getSignature() == rhs.getSignature();
334 }
335 
336 std::ostream&
337 operator<<(std::ostream& os, const Data& data)
338 {
339  os << "Name: " << data.getName() << "\n";
340  os << "MetaInfo: " << data.getMetaInfo() << "\n";
341  os << "Content: (size: " << data.getContent().value_size() << ")\n";
342  os << "Signature: (type: " << data.getSignature().getType()
343  << ", value_length: "<< data.getSignature().getValue().value_size() << ")";
344  os << std::endl;
345 
346  return os;
347 }
348 
349 } // namespace ndn
Data & setContentType(uint32_t type)
Definition: data.cpp:290
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:66
const element_container & elements() const
Get container of sub elements.
Definition: block.hpp:347
void wireDecode(const Block &wire)
Decode from wire in NDN Packet Format v0.2 or v0.3.
Definition: data.cpp:122
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Definition: meta-info.cpp:142
Data & setSignature(const Signature &signature)
Set Signature.
Definition: data.cpp:274
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.
Data & setName(const Name &name)
Set name.
Definition: data.cpp:218
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition: data.cpp:337
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:243
const Signature & getSignature() const
Get Signature.
Definition: data.hpp:189
void resetWire()
Clear wire encoding and cached FullName.
Definition: data.cpp:211
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:126
Represents a TLV element of NDN packet format.
Definition: block.hpp:42
const Block & getValue() const
Get SignatureValue.
Definition: signature.hpp:99
const MetaInfo & getMetaInfo() const
Get MetaInfo.
Definition: data.hpp:142
MetaInfo & setFreshnessPeriod(time::milliseconds freshnessPeriod)
set FreshnessPeriod
Definition: meta-info.cpp:55
size_t size() const
Get size of encoded wire, including Type-Length-Value.
Definition: block.cpp:301
MetaInfo & setFinalBlockId(const name::Component &finalBlockId)
set FinalBlockId
Definition: meta-info.cpp:74
Data & setSignatureValue(const Block &value)
Set SignatureValue.
Definition: data.cpp:282
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.
name::Component getFinalBlockId() const
Definition: data.cpp:314
An MetaInfo holds the meta info which is signed inside the data packet.
Definition: meta-info.hpp:58
name::Component getFinalBlockId() const
return FinalBlockId
Definition: meta-info.hpp:143
void reset()
Reset wire buffer of the element.
Definition: block.cpp:258
Represents an absolute name.
Definition: name.hpp:42
size_t value_size() const
Get size of TLV-VALUE aka TLV-LENGTH.
Definition: block.cpp:319
const Block & wireEncode() const
Encode to a Block.
Definition: data.cpp:106
tlv::SignatureTypeValue getType() const
Get SignatureType.
Definition: signature.cpp:44
void parse() const
Parse TLV-VALUE into sub elements.
Definition: block.cpp:336
uint32_t type() const
Get TLV-TYPE.
Definition: block.hpp:235
const Name & getName() const
Get name.
Definition: data.hpp:128
Represents a name component.
const Block & getInfo() const
Get SignatureInfo as wire format.
Definition: signature.hpp:77
Data & setFreshnessPeriod(time::milliseconds freshnessPeriod)
Definition: data.cpp:298
Data & setFinalBlock(optional< name::Component > finalBlockId)
Definition: data.cpp:306
const Block & getContent() const
Get Content.
Definition: data.cpp:234
const uint8_t * wire() const
Get pointer to encoded wire.
Definition: block.cpp:292
bool empty() const
Check if name is empty.
Definition: name.hpp:146
bool hasWire() const
Check if the Block has fully encoded wire.
Definition: block.cpp:252
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:328
std::string to_string(const V &v)
Definition: backports.hpp:107
Data & setMetaInfo(const MetaInfo &metaInfo)
Set MetaInfo.
Definition: data.cpp:226
const Name & getFullName() const
Get full name including implicit digest.
Definition: data.cpp:197
Data & setFinalBlockId(const name::Component &finalBlockId)
Definition: data.cpp:320
void wireDecode(const Block &wire)
Decode name from wire encoding.
Definition: name.cpp:159
Represents a Data packet.
Definition: data.hpp:35
void clear()
Remove all components.
Definition: name.hpp:470
EncodingImpl< EncoderTag > EncodingBuffer
Name & appendImplicitSha256Digest(const ConstBufferPtr &digest)
Append an ImplicitSha256Digest component.
Definition: name.hpp:435
EncodingImpl< EstimatorTag > EncodingEstimator
Holds SignatureInfo and SignatureValue in a Data packet.
Definition: signature.hpp:37
void wireDecode(const Block &wire)
Definition: meta-info.cpp:196
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:89