blob: f72673f110b15fefd564e35d38726f4eb7d11d2a [file] [log] [blame]
Alexander Afanasyev197e5652014-06-13 16:56:31 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento10b24be2017-07-12 23:23:46 -04002/*
Junxiao Shiebfe4a22018-04-01 23:53:40 +00003 * Copyright (c) 2013-2018 Regents of the University of California.
Alexander Afanasyev197e5652014-06-13 16:56:31 -07004 *
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"
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070023#include "encoding/block-helpers.hpp"
Junxiao Shi6938e342017-07-25 21:56:58 +000024#include "util/sha256.hpp"
Alexander Afanasyev197e5652014-06-13 16:56:31 -070025
26namespace ndn {
27
Junxiao Shic2b8d242014-11-04 08:35:29 -070028BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Data>));
29BOOST_CONCEPT_ASSERT((WireEncodable<Data>));
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070030BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Data>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070031BOOST_CONCEPT_ASSERT((WireDecodable<Data>));
32static_assert(std::is_base_of<tlv::Error, Data::Error>::value,
33 "Data::Error must inherit from tlv::Error");
34
Alexander Afanasyev197e5652014-06-13 16:56:31 -070035Data::Data(const Name& name)
36 : m_name(name)
Junxiao Shi81206d52017-07-23 12:43:22 +000037 , m_content(tlv::Content)
Alexander Afanasyev197e5652014-06-13 16:56:31 -070038{
39}
40
41Data::Data(const Block& wire)
42{
43 wireDecode(wire);
44}
45
Alexander Afanasyev74633892015-02-08 18:08:46 -080046template<encoding::Tag TAG>
Alexander Afanasyev197e5652014-06-13 16:56:31 -070047size_t
Junxiao Shi81206d52017-07-23 12:43:22 +000048Data::wireEncode(EncodingImpl<TAG>& encoder, bool wantUnsignedPortionOnly) const
Alexander Afanasyev197e5652014-06-13 16:56:31 -070049{
Alexander Afanasyev197e5652014-06-13 16:56:31 -070050 // Data ::= DATA-TLV TLV-LENGTH
51 // Name
Junxiao Shi7d9039b2018-04-14 15:56:28 +000052 // MetaInfo?
53 // Content?
Junxiao Shi81206d52017-07-23 12:43:22 +000054 // SignatureInfo
55 // SignatureValue
Alexander Afanasyev197e5652014-06-13 16:56:31 -070056
Junxiao Shi81206d52017-07-23 12:43:22 +000057 size_t totalLength = 0;
Alexander Afanasyev197e5652014-06-13 16:56:31 -070058
Junxiao Shi81206d52017-07-23 12:43:22 +000059 // SignatureValue
60 if (!wantUnsignedPortionOnly) {
61 if (!m_signature) {
62 BOOST_THROW_EXCEPTION(Error("Requested wire format, but Data has not been signed"));
Alexander Afanasyev197e5652014-06-13 16:56:31 -070063 }
Junxiao Shi81206d52017-07-23 12:43:22 +000064 totalLength += encoder.prependBlock(m_signature.getValue());
65 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -070066
67 // SignatureInfo
Alexander Afanasyev74633892015-02-08 18:08:46 -080068 totalLength += encoder.prependBlock(m_signature.getInfo());
Alexander Afanasyev197e5652014-06-13 16:56:31 -070069
70 // Content
Alexander Afanasyev74633892015-02-08 18:08:46 -080071 totalLength += encoder.prependBlock(getContent());
Alexander Afanasyev197e5652014-06-13 16:56:31 -070072
73 // MetaInfo
Alexander Afanasyev74633892015-02-08 18:08:46 -080074 totalLength += getMetaInfo().wireEncode(encoder);
Alexander Afanasyev197e5652014-06-13 16:56:31 -070075
76 // Name
Alexander Afanasyev74633892015-02-08 18:08:46 -080077 totalLength += getName().wireEncode(encoder);
Alexander Afanasyev197e5652014-06-13 16:56:31 -070078
Junxiao Shi81206d52017-07-23 12:43:22 +000079 if (!wantUnsignedPortionOnly) {
80 totalLength += encoder.prependVarNumber(totalLength);
81 totalLength += encoder.prependVarNumber(tlv::Data);
82 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -070083 return totalLength;
84}
85
Alexander Afanasyev15f67312014-07-22 15:11:09 -070086template size_t
Davide Pesavento88a0d812017-08-19 21:31:42 -040087Data::wireEncode<encoding::EncoderTag>(EncodingBuffer&, bool) const;
Alexander Afanasyev15f67312014-07-22 15:11:09 -070088
89template size_t
Davide Pesavento88a0d812017-08-19 21:31:42 -040090Data::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, bool) const;
Alexander Afanasyev15f67312014-07-22 15:11:09 -070091
Alexander Afanasyev197e5652014-06-13 16:56:31 -070092const Block&
93Data::wireEncode(EncodingBuffer& encoder, const Block& signatureValue) const
94{
95 size_t totalLength = encoder.size();
96 totalLength += encoder.appendBlock(signatureValue);
97
Davide Pesavento9bd4d982015-05-13 14:31:19 +020098 encoder.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060099 encoder.prependVarNumber(tlv::Data);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700100
101 const_cast<Data*>(this)->wireDecode(encoder.block());
102 return m_wire;
103}
104
105const Block&
106Data::wireEncode() const
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
121void
122Data::wireDecode(const Block& wire)
123{
Junxiao Shi8b753a22018-10-24 01:51:40 +0000124 // Data ::= DATA-TLV TLV-LENGTH
125 // Name
126 // MetaInfo?
127 // Content?
128 // SignatureInfo
129 // SignatureValue
130
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700131 m_wire = wire;
132 m_wire.parse();
Junxiao Shi8b753a22018-10-24 01:51:40 +0000133
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
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000141 m_metaInfo = MetaInfo();
142 m_content = Block(tlv::Content);
143 m_signature = Signature();
144 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700145
Junxiao Shi8b753a22018-10-24 01:51:40 +0000146 for (++element; element != m_wire.elements_end(); ++element) {
147 switch (element->type()) {
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000148 case tlv::MetaInfo: {
Junxiao Shi8b753a22018-10-24 01:51:40 +0000149 if (lastElement >= 2) {
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000150 BOOST_THROW_EXCEPTION(Error("MetaInfo element is out of order"));
151 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000152 m_metaInfo.wireDecode(*element);
153 lastElement = 2;
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000154 break;
155 }
156 case tlv::Content: {
Junxiao Shi8b753a22018-10-24 01:51:40 +0000157 if (lastElement >= 3) {
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000158 BOOST_THROW_EXCEPTION(Error("Content element is out of order"));
159 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000160 m_content = *element;
161 lastElement = 3;
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000162 break;
163 }
164 case tlv::SignatureInfo: {
Junxiao Shi8b753a22018-10-24 01:51:40 +0000165 if (lastElement >= 4) {
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000166 BOOST_THROW_EXCEPTION(Error("SignatureInfo element is out of order"));
167 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000168 m_signature.setInfo(*element);
169 lastElement = 4;
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000170 break;
171 }
172 case tlv::SignatureValue: {
Junxiao Shi8b753a22018-10-24 01:51:40 +0000173 if (lastElement >= 5) {
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000174 BOOST_THROW_EXCEPTION(Error("SignatureValue element is out of order"));
175 }
Junxiao Shi8b753a22018-10-24 01:51:40 +0000176 m_signature.setValue(*element);
177 lastElement = 5;
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000178 break;
179 }
180 default: {
Junxiao Shi8b753a22018-10-24 01:51:40 +0000181 if (tlv::isCriticalType(element->type())) {
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000182 BOOST_THROW_EXCEPTION(Error("unrecognized element of critical type " +
Junxiao Shi8b753a22018-10-24 01:51:40 +0000183 to_string(element->type())));
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000184 }
185 break;
186 }
187 }
188 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700189
Junxiao Shi8b753a22018-10-24 01:51:40 +0000190 if (!m_signature) {
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000191 BOOST_THROW_EXCEPTION(Error("SignatureInfo element is missing"));
Junxiao Shi81206d52017-07-23 12:43:22 +0000192 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700193}
194
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700195const Name&
196Data::getFullName() const
197{
198 if (m_fullName.empty()) {
199 if (!m_wire.hasWire()) {
Junxiao Shi81206d52017-07-23 12:43:22 +0000200 BOOST_THROW_EXCEPTION(Error("Cannot compute full name because Data has no wire encoding (not signed)"));
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700201 }
202 m_fullName = m_name;
Davide Pesavento10b24be2017-07-12 23:23:46 -0400203 m_fullName.appendImplicitSha256Digest(util::Sha256::computeDigest(m_wire.wire(), m_wire.size()));
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700204 }
205
206 return m_fullName;
207}
208
Junxiao Shi81206d52017-07-23 12:43:22 +0000209void
210Data::resetWire()
211{
212 m_wire.reset();
213 m_fullName.clear();
214}
215
216Data&
217Data::setName(const Name& name)
218{
219 resetWire();
220 m_name = name;
221 return *this;
222}
223
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700224Data&
225Data::setMetaInfo(const MetaInfo& metaInfo)
226{
Junxiao Shi81206d52017-07-23 12:43:22 +0000227 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700228 m_metaInfo = metaInfo;
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700229 return *this;
230}
231
232const Block&
233Data::getContent() const
234{
Junxiao Shi81206d52017-07-23 12:43:22 +0000235 if (!m_content.hasWire()) {
236 const_cast<Block&>(m_content).encode();
237 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700238 return m_content;
239}
240
241Data&
Junxiao Shi81206d52017-07-23 12:43:22 +0000242Data::setContent(const Block& block)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700243{
Junxiao Shi81206d52017-07-23 12:43:22 +0000244 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700245
Junxiao Shi81206d52017-07-23 12:43:22 +0000246 if (block.type() == tlv::Content) {
247 m_content = block;
248 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700249 else {
Junxiao Shi81206d52017-07-23 12:43:22 +0000250 m_content = Block(tlv::Content, block);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700251 }
252
253 return *this;
254}
255
256Data&
Junxiao Shi81206d52017-07-23 12:43:22 +0000257Data::setContent(const uint8_t* value, size_t valueSize)
258{
259 resetWire();
260 m_content = makeBinaryBlock(tlv::Content, value, valueSize);
261 return *this;
262}
263
264Data&
Davide Pesavento3b101d02018-07-21 22:44:09 -0400265Data::setContent(ConstBufferPtr value)
Junxiao Shi81206d52017-07-23 12:43:22 +0000266{
267 resetWire();
Davide Pesavento3b101d02018-07-21 22:44:09 -0400268 m_content = Block(tlv::Content, std::move(value));
Junxiao Shi81206d52017-07-23 12:43:22 +0000269 return *this;
270}
271
272Data&
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700273Data::setSignature(const Signature& signature)
274{
Junxiao Shi81206d52017-07-23 12:43:22 +0000275 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700276 m_signature = signature;
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700277 return *this;
278}
279
280Data&
281Data::setSignatureValue(const Block& value)
282{
Junxiao Shi81206d52017-07-23 12:43:22 +0000283 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700284 m_signature.setValue(value);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700285 return *this;
286}
287
Junxiao Shi81206d52017-07-23 12:43:22 +0000288Data&
289Data::setContentType(uint32_t type)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700290{
Junxiao Shi81206d52017-07-23 12:43:22 +0000291 resetWire();
292 m_metaInfo.setType(type);
293 return *this;
294}
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700295
Junxiao Shi81206d52017-07-23 12:43:22 +0000296Data&
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000297Data::setFreshnessPeriod(time::milliseconds freshnessPeriod)
Junxiao Shi81206d52017-07-23 12:43:22 +0000298{
299 resetWire();
300 m_metaInfo.setFreshnessPeriod(freshnessPeriod);
301 return *this;
302}
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700303
Junxiao Shi81206d52017-07-23 12:43:22 +0000304Data&
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000305Data::setFinalBlock(optional<name::Component> finalBlockId)
306{
307 resetWire();
308 m_metaInfo.setFinalBlock(std::move(finalBlockId));
309 return *this;
310}
311
312name::Component
313Data::getFinalBlockId() const
314{
315 return m_metaInfo.getFinalBlockId();
316}
317
318Data&
Junxiao Shi81206d52017-07-23 12:43:22 +0000319Data::setFinalBlockId(const name::Component& finalBlockId)
320{
321 resetWire();
322 m_metaInfo.setFinalBlockId(finalBlockId);
323 return *this;
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700324}
325
326bool
Junxiao Shi81206d52017-07-23 12:43:22 +0000327operator==(const Data& lhs, const Data& rhs)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700328{
Junxiao Shi81206d52017-07-23 12:43:22 +0000329 return lhs.getName() == rhs.getName() &&
330 lhs.getMetaInfo() == rhs.getMetaInfo() &&
331 lhs.getContent() == rhs.getContent() &&
332 lhs.getSignature() == rhs.getSignature();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700333}
334
335std::ostream&
336operator<<(std::ostream& os, const Data& data)
337{
338 os << "Name: " << data.getName() << "\n";
339 os << "MetaInfo: " << data.getMetaInfo() << "\n";
340 os << "Content: (size: " << data.getContent().value_size() << ")\n";
Junxiao Shi81206d52017-07-23 12:43:22 +0000341 os << "Signature: (type: " << data.getSignature().getType()
342 << ", value_length: "<< data.getSignature().getValue().value_size() << ")";
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700343 os << std::endl;
344
345 return os;
346}
347
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700348} // namespace ndn