blob: 9a5908999c60983bd9272ee9704920f902787540 [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/*
3 * Copyright (c) 2013-2017 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
52 // 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{
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700124 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700125 m_wire = wire;
126 m_wire.parse();
127
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700128 // Name
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600129 m_name.wireDecode(m_wire.get(tlv::Name));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700130
131 // MetaInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600132 m_metaInfo.wireDecode(m_wire.get(tlv::MetaInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700133
134 // Content
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600135 m_content = m_wire.get(tlv::Content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700136
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700137 // SignatureInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600138 m_signature.setInfo(m_wire.get(tlv::SignatureInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700139
140 // SignatureValue
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600141 Block::element_const_iterator val = m_wire.find(tlv::SignatureValue);
Junxiao Shi81206d52017-07-23 12:43:22 +0000142 if (val != m_wire.elements_end()) {
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700143 m_signature.setValue(*val);
Junxiao Shi81206d52017-07-23 12:43:22 +0000144 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700145}
146
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700147const Name&
148Data::getFullName() const
149{
150 if (m_fullName.empty()) {
151 if (!m_wire.hasWire()) {
Junxiao Shi81206d52017-07-23 12:43:22 +0000152 BOOST_THROW_EXCEPTION(Error("Cannot compute full name because Data has no wire encoding (not signed)"));
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700153 }
154 m_fullName = m_name;
Davide Pesavento10b24be2017-07-12 23:23:46 -0400155 m_fullName.appendImplicitSha256Digest(util::Sha256::computeDigest(m_wire.wire(), m_wire.size()));
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700156 }
157
158 return m_fullName;
159}
160
Junxiao Shi81206d52017-07-23 12:43:22 +0000161void
162Data::resetWire()
163{
164 m_wire.reset();
165 m_fullName.clear();
166}
167
168Data&
169Data::setName(const Name& name)
170{
171 resetWire();
172 m_name = name;
173 return *this;
174}
175
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700176Data&
177Data::setMetaInfo(const MetaInfo& metaInfo)
178{
Junxiao Shi81206d52017-07-23 12:43:22 +0000179 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700180 m_metaInfo = metaInfo;
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700181 return *this;
182}
183
184const Block&
185Data::getContent() const
186{
Junxiao Shi81206d52017-07-23 12:43:22 +0000187 if (!m_content.hasWire()) {
188 const_cast<Block&>(m_content).encode();
189 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700190 return m_content;
191}
192
193Data&
Junxiao Shi81206d52017-07-23 12:43:22 +0000194Data::setContent(const Block& block)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700195{
Junxiao Shi81206d52017-07-23 12:43:22 +0000196 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700197
Junxiao Shi81206d52017-07-23 12:43:22 +0000198 if (block.type() == tlv::Content) {
199 m_content = block;
200 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700201 else {
Junxiao Shi81206d52017-07-23 12:43:22 +0000202 m_content = Block(tlv::Content, block);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700203 }
204
205 return *this;
206}
207
208Data&
Junxiao Shi81206d52017-07-23 12:43:22 +0000209Data::setContent(const uint8_t* value, size_t valueSize)
210{
211 resetWire();
212 m_content = makeBinaryBlock(tlv::Content, value, valueSize);
213 return *this;
214}
215
216Data&
217Data::setContent(const ConstBufferPtr& value)
218{
219 resetWire();
220 m_content = Block(tlv::Content, value);
221 return *this;
222}
223
224Data&
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700225Data::setSignature(const Signature& signature)
226{
Junxiao Shi81206d52017-07-23 12:43:22 +0000227 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700228 m_signature = signature;
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700229 return *this;
230}
231
232Data&
233Data::setSignatureValue(const Block& value)
234{
Junxiao Shi81206d52017-07-23 12:43:22 +0000235 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700236 m_signature.setValue(value);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700237 return *this;
238}
239
Junxiao Shi81206d52017-07-23 12:43:22 +0000240Data&
241Data::setContentType(uint32_t type)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700242{
Junxiao Shi81206d52017-07-23 12:43:22 +0000243 resetWire();
244 m_metaInfo.setType(type);
245 return *this;
246}
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700247
Junxiao Shi81206d52017-07-23 12:43:22 +0000248Data&
249Data::setFreshnessPeriod(const time::milliseconds& freshnessPeriod)
250{
251 resetWire();
252 m_metaInfo.setFreshnessPeriod(freshnessPeriod);
253 return *this;
254}
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700255
Junxiao Shi81206d52017-07-23 12:43:22 +0000256Data&
257Data::setFinalBlockId(const name::Component& finalBlockId)
258{
259 resetWire();
260 m_metaInfo.setFinalBlockId(finalBlockId);
261 return *this;
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700262}
263
264bool
Junxiao Shi81206d52017-07-23 12:43:22 +0000265operator==(const Data& lhs, const Data& rhs)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700266{
Junxiao Shi81206d52017-07-23 12:43:22 +0000267 return lhs.getName() == rhs.getName() &&
268 lhs.getMetaInfo() == rhs.getMetaInfo() &&
269 lhs.getContent() == rhs.getContent() &&
270 lhs.getSignature() == rhs.getSignature();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700271}
272
273std::ostream&
274operator<<(std::ostream& os, const Data& data)
275{
276 os << "Name: " << data.getName() << "\n";
277 os << "MetaInfo: " << data.getMetaInfo() << "\n";
278 os << "Content: (size: " << data.getContent().value_size() << ")\n";
Junxiao Shi81206d52017-07-23 12:43:22 +0000279 os << "Signature: (type: " << data.getSignature().getType()
280 << ", value_length: "<< data.getSignature().getValue().value_size() << ")";
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700281 os << std::endl;
282
283 return os;
284}
285
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700286} // namespace ndn