blob: 84dbbd6547e03287ce241a718b81761afbefbde9 [file] [log] [blame]
Alexander Afanasyev197e5652014-06-13 16:56:31 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev74633892015-02-08 18:08:46 -08003 * Copyright (c) 2013-2015 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"
Alexander Afanasyev197e5652014-06-13 16:56:31 -070024#include "util/crypto.hpp"
Junxiao Shic2b8d242014-11-04 08:35:29 -070025#include "util/concepts.hpp"
Alexander Afanasyev197e5652014-06-13 16:56:31 -070026
27namespace ndn {
28
Junxiao Shic2b8d242014-11-04 08:35:29 -070029BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Data>));
30BOOST_CONCEPT_ASSERT((WireEncodable<Data>));
31BOOST_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()
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060036 : m_content(tlv::Content) // empty content
Alexander Afanasyev197e5652014-06-13 16:56:31 -070037{
38}
39
40Data::Data(const Name& name)
41 : m_name(name)
42{
43}
44
45Data::Data(const Block& wire)
46{
47 wireDecode(wire);
48}
49
Alexander Afanasyev74633892015-02-08 18:08:46 -080050template<encoding::Tag TAG>
Alexander Afanasyev197e5652014-06-13 16:56:31 -070051size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -080052Data::wireEncode(EncodingImpl<TAG>& encoder, bool unsignedPortion/* = false*/) const
Alexander Afanasyev197e5652014-06-13 16:56:31 -070053{
54 size_t totalLength = 0;
55
56 // Data ::= DATA-TLV TLV-LENGTH
57 // Name
58 // MetaInfo
59 // Content
60 // Signature
61
62 // (reverse encoding)
63
64 if (!unsignedPortion && !m_signature)
65 {
66 throw Error("Requested wire format, but data packet has not been signed yet");
67 }
68
69 if (!unsignedPortion)
70 {
71 // SignatureValue
Alexander Afanasyev74633892015-02-08 18:08:46 -080072 totalLength += encoder.prependBlock(m_signature.getValue());
Alexander Afanasyev197e5652014-06-13 16:56:31 -070073 }
74
75 // SignatureInfo
Alexander Afanasyev74633892015-02-08 18:08:46 -080076 totalLength += encoder.prependBlock(m_signature.getInfo());
Alexander Afanasyev197e5652014-06-13 16:56:31 -070077
78 // Content
Alexander Afanasyev74633892015-02-08 18:08:46 -080079 totalLength += encoder.prependBlock(getContent());
Alexander Afanasyev197e5652014-06-13 16:56:31 -070080
81 // MetaInfo
Alexander Afanasyev74633892015-02-08 18:08:46 -080082 totalLength += getMetaInfo().wireEncode(encoder);
Alexander Afanasyev197e5652014-06-13 16:56:31 -070083
84 // Name
Alexander Afanasyev74633892015-02-08 18:08:46 -080085 totalLength += getName().wireEncode(encoder);
Alexander Afanasyev197e5652014-06-13 16:56:31 -070086
87 if (!unsignedPortion)
88 {
Alexander Afanasyev74633892015-02-08 18:08:46 -080089 totalLength += encoder.prependVarNumber(totalLength);
90 totalLength += encoder.prependVarNumber(tlv::Data);
Alexander Afanasyev197e5652014-06-13 16:56:31 -070091 }
92 return totalLength;
93}
94
Alexander Afanasyev15f67312014-07-22 15:11:09 -070095
96template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -080097Data::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block,
98 bool unsignedPortion) const;
Alexander Afanasyev15f67312014-07-22 15:11:09 -070099
100template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800101Data::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block,
102 bool unsignedPortion) const;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700103
104
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700105const Block&
106Data::wireEncode(EncodingBuffer& encoder, const Block& signatureValue) const
107{
108 size_t totalLength = encoder.size();
109 totalLength += encoder.appendBlock(signatureValue);
110
Davide Pesavento9bd4d982015-05-13 14:31:19 +0200111 encoder.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600112 encoder.prependVarNumber(tlv::Data);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700113
114 const_cast<Data*>(this)->wireDecode(encoder.block());
115 return m_wire;
116}
117
118const Block&
119Data::wireEncode() const
120{
121 if (m_wire.hasWire())
122 return m_wire;
123
124 EncodingEstimator estimator;
125 size_t estimatedSize = wireEncode(estimator);
126
127 EncodingBuffer buffer(estimatedSize, 0);
128 wireEncode(buffer);
129
130 const_cast<Data*>(this)->wireDecode(buffer.block());
131 return m_wire;
132}
133
134void
135Data::wireDecode(const Block& wire)
136{
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700137 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700138 m_wire = wire;
139 m_wire.parse();
140
141 // Data ::= DATA-TLV TLV-LENGTH
142 // Name
143 // MetaInfo
144 // Content
145 // Signature
146
147 // Name
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600148 m_name.wireDecode(m_wire.get(tlv::Name));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700149
150 // MetaInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600151 m_metaInfo.wireDecode(m_wire.get(tlv::MetaInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700152
153 // Content
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600154 m_content = m_wire.get(tlv::Content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700155
156 ///////////////
157 // Signature //
158 ///////////////
159
160 // SignatureInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600161 m_signature.setInfo(m_wire.get(tlv::SignatureInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700162
163 // SignatureValue
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600164 Block::element_const_iterator val = m_wire.find(tlv::SignatureValue);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700165 if (val != m_wire.elements_end())
166 m_signature.setValue(*val);
167}
168
169Data&
170Data::setName(const Name& name)
171{
172 onChanged();
173 m_name = name;
174
175 return *this;
176}
177
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700178const Name&
179Data::getFullName() const
180{
181 if (m_fullName.empty()) {
182 if (!m_wire.hasWire()) {
183 throw Error("Full name requested, but Data packet does not have wire format "
184 "(e.g., not signed)");
185 }
186 m_fullName = m_name;
Alexander Afanasyevafee0a52014-11-07 11:15:34 -0800187 m_fullName.appendImplicitSha256Digest(crypto::sha256(m_wire.wire(), m_wire.size()));
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700188 }
189
190 return m_fullName;
191}
192
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700193Data&
194Data::setMetaInfo(const MetaInfo& metaInfo)
195{
196 onChanged();
197 m_metaInfo = metaInfo;
198
199 return *this;
200}
201
202Data&
203Data::setContentType(uint32_t type)
204{
205 onChanged();
206 m_metaInfo.setType(type);
207
208 return *this;
209}
210
211Data&
212Data::setFreshnessPeriod(const time::milliseconds& freshnessPeriod)
213{
214 onChanged();
215 m_metaInfo.setFreshnessPeriod(freshnessPeriod);
216
217 return *this;
218}
219
220Data&
221Data::setFinalBlockId(const name::Component& finalBlockId)
222{
223 onChanged();
224 m_metaInfo.setFinalBlockId(finalBlockId);
225
226 return *this;
227}
228
229const Block&
230Data::getContent() const
231{
232 if (m_content.empty())
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600233 m_content = dataBlock(tlv::Content, reinterpret_cast<const uint8_t*>(0), 0);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700234
235 if (!m_content.hasWire())
236 m_content.encode();
237 return m_content;
238}
239
240Data&
241Data::setContent(const uint8_t* content, size_t contentLength)
242{
243 onChanged();
244
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600245 m_content = dataBlock(tlv::Content, content, contentLength);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700246
247 return *this;
248}
249
250Data&
251Data::setContent(const ConstBufferPtr& contentValue)
252{
253 onChanged();
254
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600255 m_content = Block(tlv::Content, contentValue); // not a real wire encoding yet
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700256
257 return *this;
258}
259
260Data&
261Data::setContent(const Block& content)
262{
263 onChanged();
264
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600265 if (content.type() == tlv::Content)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700266 m_content = content;
267 else {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600268 m_content = Block(tlv::Content, content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700269 }
270
271 return *this;
272}
273
274Data&
275Data::setSignature(const Signature& signature)
276{
277 onChanged();
278 m_signature = signature;
279
280 return *this;
281}
282
283Data&
284Data::setSignatureValue(const Block& value)
285{
286 onChanged();
287 m_signature.setValue(value);
288
289 return *this;
290}
291
292//
293
294Data&
295Data::setIncomingFaceId(uint64_t incomingFaceId)
296{
297 getLocalControlHeader().setIncomingFaceId(incomingFaceId);
298 // ! do not reset Data's wire !
299
300 return *this;
301}
302
Jiewen Tanc759a202015-01-29 23:31:09 -0800303Data&
304Data::setCachingPolicy(nfd::LocalControlHeader::CachingPolicy cachingPolicy)
305{
306 getLocalControlHeader().setCachingPolicy(cachingPolicy);
307 // ! do not reset Data's wire !
308
309 return *this;
310}
311
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700312void
313Data::onChanged()
314{
315 // The values have changed, so the wire format is invalidated
316
317 // !!!Note!!! Signature is not invalidated and it is responsibility of
318 // the application to do proper re-signing if necessary
319
320 m_wire.reset();
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700321 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700322}
323
324bool
325Data::operator==(const Data& other) const
326{
327 return getName() == other.getName() &&
328 getMetaInfo() == other.getMetaInfo() &&
329 getContent() == other.getContent() &&
330 getSignature() == other.getSignature();
331}
332
333bool
334Data::operator!=(const Data& other) const
335{
336 return !(*this == other);
337}
338
339std::ostream&
340operator<<(std::ostream& os, const Data& data)
341{
342 os << "Name: " << data.getName() << "\n";
343 os << "MetaInfo: " << data.getMetaInfo() << "\n";
344 os << "Content: (size: " << data.getContent().value_size() << ")\n";
345 os << "Signature: (type: " << data.getSignature().getType() <<
346 ", value_length: "<< data.getSignature().getValue().value_size() << ")";
347 os << std::endl;
348
349 return os;
350}
351
352} // namespace ndn