blob: e982700a2ba8af344633643f4c20d8f12090f38a [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
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070087Data::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder,
Junxiao Shi81206d52017-07-23 12:43:22 +000088 bool wantUnsignedPortionOnly) const;
Alexander Afanasyev15f67312014-07-22 15:11:09 -070089
90template size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070091Data::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder,
Junxiao Shi81206d52017-07-23 12:43:22 +000092 bool wantUnsignedPortionOnly) const;
Alexander Afanasyev15f67312014-07-22 15:11:09 -070093
Alexander Afanasyev197e5652014-06-13 16:56:31 -070094const Block&
95Data::wireEncode(EncodingBuffer& encoder, const Block& signatureValue) const
96{
97 size_t totalLength = encoder.size();
98 totalLength += encoder.appendBlock(signatureValue);
99
Davide Pesavento9bd4d982015-05-13 14:31:19 +0200100 encoder.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600101 encoder.prependVarNumber(tlv::Data);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700102
103 const_cast<Data*>(this)->wireDecode(encoder.block());
104 return m_wire;
105}
106
107const Block&
108Data::wireEncode() const
109{
110 if (m_wire.hasWire())
111 return m_wire;
112
113 EncodingEstimator estimator;
114 size_t estimatedSize = wireEncode(estimator);
115
116 EncodingBuffer buffer(estimatedSize, 0);
117 wireEncode(buffer);
118
119 const_cast<Data*>(this)->wireDecode(buffer.block());
120 return m_wire;
121}
122
123void
124Data::wireDecode(const Block& wire)
125{
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700126 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700127 m_wire = wire;
128 m_wire.parse();
129
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700130 // Name
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600131 m_name.wireDecode(m_wire.get(tlv::Name));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700132
133 // MetaInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600134 m_metaInfo.wireDecode(m_wire.get(tlv::MetaInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700135
136 // Content
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600137 m_content = m_wire.get(tlv::Content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700138
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700139 // SignatureInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600140 m_signature.setInfo(m_wire.get(tlv::SignatureInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700141
142 // SignatureValue
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600143 Block::element_const_iterator val = m_wire.find(tlv::SignatureValue);
Junxiao Shi81206d52017-07-23 12:43:22 +0000144 if (val != m_wire.elements_end()) {
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700145 m_signature.setValue(*val);
Junxiao Shi81206d52017-07-23 12:43:22 +0000146 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700147}
148
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700149const Name&
150Data::getFullName() const
151{
152 if (m_fullName.empty()) {
153 if (!m_wire.hasWire()) {
Junxiao Shi81206d52017-07-23 12:43:22 +0000154 BOOST_THROW_EXCEPTION(Error("Cannot compute full name because Data has no wire encoding (not signed)"));
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700155 }
156 m_fullName = m_name;
Davide Pesavento10b24be2017-07-12 23:23:46 -0400157 m_fullName.appendImplicitSha256Digest(util::Sha256::computeDigest(m_wire.wire(), m_wire.size()));
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700158 }
159
160 return m_fullName;
161}
162
Junxiao Shi81206d52017-07-23 12:43:22 +0000163void
164Data::resetWire()
165{
166 m_wire.reset();
167 m_fullName.clear();
168}
169
170Data&
171Data::setName(const Name& name)
172{
173 resetWire();
174 m_name = name;
175 return *this;
176}
177
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700178Data&
179Data::setMetaInfo(const MetaInfo& metaInfo)
180{
Junxiao Shi81206d52017-07-23 12:43:22 +0000181 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700182 m_metaInfo = metaInfo;
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700183 return *this;
184}
185
186const Block&
187Data::getContent() const
188{
Junxiao Shi81206d52017-07-23 12:43:22 +0000189 if (!m_content.hasWire()) {
190 const_cast<Block&>(m_content).encode();
191 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700192 return m_content;
193}
194
195Data&
Junxiao Shi81206d52017-07-23 12:43:22 +0000196Data::setContent(const Block& block)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700197{
Junxiao Shi81206d52017-07-23 12:43:22 +0000198 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700199
Junxiao Shi81206d52017-07-23 12:43:22 +0000200 if (block.type() == tlv::Content) {
201 m_content = block;
202 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700203 else {
Junxiao Shi81206d52017-07-23 12:43:22 +0000204 m_content = Block(tlv::Content, block);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700205 }
206
207 return *this;
208}
209
210Data&
Junxiao Shi81206d52017-07-23 12:43:22 +0000211Data::setContent(const uint8_t* value, size_t valueSize)
212{
213 resetWire();
214 m_content = makeBinaryBlock(tlv::Content, value, valueSize);
215 return *this;
216}
217
218Data&
219Data::setContent(const ConstBufferPtr& value)
220{
221 resetWire();
222 m_content = Block(tlv::Content, value);
223 return *this;
224}
225
226Data&
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700227Data::setSignature(const Signature& signature)
228{
Junxiao Shi81206d52017-07-23 12:43:22 +0000229 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700230 m_signature = signature;
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700231 return *this;
232}
233
234Data&
235Data::setSignatureValue(const Block& value)
236{
Junxiao Shi81206d52017-07-23 12:43:22 +0000237 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700238 m_signature.setValue(value);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700239 return *this;
240}
241
Junxiao Shi81206d52017-07-23 12:43:22 +0000242Data&
243Data::setContentType(uint32_t type)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700244{
Junxiao Shi81206d52017-07-23 12:43:22 +0000245 resetWire();
246 m_metaInfo.setType(type);
247 return *this;
248}
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700249
Junxiao Shi81206d52017-07-23 12:43:22 +0000250Data&
251Data::setFreshnessPeriod(const time::milliseconds& freshnessPeriod)
252{
253 resetWire();
254 m_metaInfo.setFreshnessPeriod(freshnessPeriod);
255 return *this;
256}
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700257
Junxiao Shi81206d52017-07-23 12:43:22 +0000258Data&
259Data::setFinalBlockId(const name::Component& finalBlockId)
260{
261 resetWire();
262 m_metaInfo.setFinalBlockId(finalBlockId);
263 return *this;
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700264}
265
266bool
Junxiao Shi81206d52017-07-23 12:43:22 +0000267operator==(const Data& lhs, const Data& rhs)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700268{
Junxiao Shi81206d52017-07-23 12:43:22 +0000269 return lhs.getName() == rhs.getName() &&
270 lhs.getMetaInfo() == rhs.getMetaInfo() &&
271 lhs.getContent() == rhs.getContent() &&
272 lhs.getSignature() == rhs.getSignature();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700273}
274
275std::ostream&
276operator<<(std::ostream& os, const Data& data)
277{
278 os << "Name: " << data.getName() << "\n";
279 os << "MetaInfo: " << data.getMetaInfo() << "\n";
280 os << "Content: (size: " << data.getContent().value_size() << ")\n";
Junxiao Shi81206d52017-07-23 12:43:22 +0000281 os << "Signature: (type: " << data.getSignature().getType()
282 << ", value_length: "<< data.getSignature().getValue().value_size() << ")";
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700283 os << std::endl;
284
285 return os;
286}
287
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700288} // namespace ndn