blob: 1ba5f4f00fae9ae14473756bada4fde526dc569b [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/*
Davide Pesavento923ba442019-02-12 22:00:38 -05003 * Copyright (c) 2013-2019 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
Davide Pesavento7e780642018-11-24 15:51:34 -050022#include "ndn-cxx/data.hpp"
23#include "ndn-cxx/encoding/block-helpers.hpp"
24#include "ndn-cxx/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) {
Davide Pesavento923ba442019-02-12 22:00:38 -050062 NDN_THROW(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) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500136 NDN_THROW(Error("Name element is missing or out of order"));
Junxiao Shi8b753a22018-10-24 01:51:40 +0000137 }
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) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500150 NDN_THROW(Error("MetaInfo element is out of order"));
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000151 }
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) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500158 NDN_THROW(Error("Content element is out of order"));
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000159 }
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) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500166 NDN_THROW(Error("SignatureInfo element is out of order"));
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000167 }
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) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500174 NDN_THROW(Error("SignatureValue element is out of order"));
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000175 }
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())) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500182 NDN_THROW(Error("unrecognized element of critical type " + to_string(element->type())));
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000183 }
184 break;
185 }
186 }
187 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700188
Junxiao Shi8b753a22018-10-24 01:51:40 +0000189 if (!m_signature) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500190 NDN_THROW(Error("SignatureInfo element is missing"));
Junxiao Shi81206d52017-07-23 12:43:22 +0000191 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700192}
193
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700194const Name&
195Data::getFullName() const
196{
197 if (m_fullName.empty()) {
198 if (!m_wire.hasWire()) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500199 NDN_THROW(Error("Cannot compute full name because Data has no wire encoding (not signed)"));
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700200 }
201 m_fullName = m_name;
Davide Pesavento10b24be2017-07-12 23:23:46 -0400202 m_fullName.appendImplicitSha256Digest(util::Sha256::computeDigest(m_wire.wire(), m_wire.size()));
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700203 }
204
205 return m_fullName;
206}
207
Junxiao Shi81206d52017-07-23 12:43:22 +0000208void
209Data::resetWire()
210{
211 m_wire.reset();
212 m_fullName.clear();
213}
214
215Data&
216Data::setName(const Name& name)
217{
218 resetWire();
219 m_name = name;
220 return *this;
221}
222
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700223Data&
224Data::setMetaInfo(const MetaInfo& metaInfo)
225{
Junxiao Shi81206d52017-07-23 12:43:22 +0000226 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700227 m_metaInfo = metaInfo;
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700228 return *this;
229}
230
231const Block&
232Data::getContent() const
233{
Junxiao Shi81206d52017-07-23 12:43:22 +0000234 if (!m_content.hasWire()) {
235 const_cast<Block&>(m_content).encode();
236 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700237 return m_content;
238}
239
240Data&
Junxiao Shi81206d52017-07-23 12:43:22 +0000241Data::setContent(const Block& block)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700242{
Junxiao Shi81206d52017-07-23 12:43:22 +0000243 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700244
Junxiao Shi81206d52017-07-23 12:43:22 +0000245 if (block.type() == tlv::Content) {
246 m_content = block;
247 }
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700248 else {
Junxiao Shi81206d52017-07-23 12:43:22 +0000249 m_content = Block(tlv::Content, block);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700250 }
251
252 return *this;
253}
254
255Data&
Junxiao Shi81206d52017-07-23 12:43:22 +0000256Data::setContent(const uint8_t* value, size_t valueSize)
257{
258 resetWire();
259 m_content = makeBinaryBlock(tlv::Content, value, valueSize);
260 return *this;
261}
262
263Data&
Davide Pesavento3b101d02018-07-21 22:44:09 -0400264Data::setContent(ConstBufferPtr value)
Junxiao Shi81206d52017-07-23 12:43:22 +0000265{
266 resetWire();
Davide Pesavento3b101d02018-07-21 22:44:09 -0400267 m_content = Block(tlv::Content, std::move(value));
Junxiao Shi81206d52017-07-23 12:43:22 +0000268 return *this;
269}
270
271Data&
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700272Data::setSignature(const Signature& signature)
273{
Junxiao Shi81206d52017-07-23 12:43:22 +0000274 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700275 m_signature = signature;
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700276 return *this;
277}
278
279Data&
280Data::setSignatureValue(const Block& value)
281{
Junxiao Shi81206d52017-07-23 12:43:22 +0000282 resetWire();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700283 m_signature.setValue(value);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700284 return *this;
285}
286
Junxiao Shi81206d52017-07-23 12:43:22 +0000287Data&
288Data::setContentType(uint32_t type)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700289{
Junxiao Shi81206d52017-07-23 12:43:22 +0000290 resetWire();
291 m_metaInfo.setType(type);
292 return *this;
293}
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700294
Junxiao Shi81206d52017-07-23 12:43:22 +0000295Data&
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000296Data::setFreshnessPeriod(time::milliseconds freshnessPeriod)
Junxiao Shi81206d52017-07-23 12:43:22 +0000297{
298 resetWire();
299 m_metaInfo.setFreshnessPeriod(freshnessPeriod);
300 return *this;
301}
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700302
Junxiao Shi81206d52017-07-23 12:43:22 +0000303Data&
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000304Data::setFinalBlock(optional<name::Component> finalBlockId)
305{
306 resetWire();
307 m_metaInfo.setFinalBlock(std::move(finalBlockId));
308 return *this;
309}
310
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700311bool
Junxiao Shi81206d52017-07-23 12:43:22 +0000312operator==(const Data& lhs, const Data& rhs)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700313{
Junxiao Shi81206d52017-07-23 12:43:22 +0000314 return lhs.getName() == rhs.getName() &&
Davide Pesaventoef654dd2019-07-18 20:02:44 -0400315 lhs.getMetaInfo().wireEncode() == rhs.getMetaInfo().wireEncode() &&
Junxiao Shi81206d52017-07-23 12:43:22 +0000316 lhs.getContent() == rhs.getContent() &&
Davide Pesaventoef654dd2019-07-18 20:02:44 -0400317 lhs.getSignature().getSignatureInfo() == rhs.getSignature().getSignatureInfo() &&
318 lhs.getSignature().getValue() == rhs.getSignature().getValue();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700319}
320
321std::ostream&
322operator<<(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";
Junxiao Shi81206d52017-07-23 12:43:22 +0000327 os << "Signature: (type: " << data.getSignature().getType()
328 << ", value_length: "<< data.getSignature().getValue().value_size() << ")";
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700329 os << std::endl;
330
331 return os;
332}
333
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700334} // namespace ndn