blob: 054c975f41a47af7df03c620cbbfad170502e1b7 [file] [log] [blame]
Alexander Afanasyev197e5652014-06-13 16:56:31 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev2fa59392016-07-29 17:24:23 -07003 * Copyright (c) 2013-2016 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"
25
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()
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 {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -070066 BOOST_THROW_EXCEPTION(Error("Requested wire format, but data packet has not been signed yet"));
Alexander Afanasyev197e5652014-06-13 16:56:31 -070067 }
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 Afanasyevd5c48e02015-06-24 11:58:14 -070097Data::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder,
Alexander Afanasyev74633892015-02-08 18:08:46 -080098 bool unsignedPortion) const;
Alexander Afanasyev15f67312014-07-22 15:11:09 -070099
100template size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700101Data::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder,
Alexander Afanasyev74633892015-02-08 18:08:46 -0800102 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()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700183 BOOST_THROW_EXCEPTION(Error("Full name requested, but Data packet does not have wire format "
184 "(e.g., not signed)"));
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700185 }
186 m_fullName = m_name;
Alexander Afanasyev2fa59392016-07-29 17:24:23 -0700187 m_fullName.appendImplicitSha256Digest(crypto::computeSha256Digest(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())
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700233 m_content = makeEmptyBlock(tlv::Content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700234
235 if (!m_content.hasWire())
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700236 m_content.encode();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700237 return m_content;
238}
239
240Data&
241Data::setContent(const uint8_t* content, size_t contentLength)
242{
243 onChanged();
244
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700245 m_content = makeBinaryBlock(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
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700292void
293Data::onChanged()
294{
295 // The values have changed, so the wire format is invalidated
296
297 // !!!Note!!! Signature is not invalidated and it is responsibility of
298 // the application to do proper re-signing if necessary
299
300 m_wire.reset();
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700301 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700302}
303
304bool
305Data::operator==(const Data& other) const
306{
307 return getName() == other.getName() &&
308 getMetaInfo() == other.getMetaInfo() &&
309 getContent() == other.getContent() &&
310 getSignature() == other.getSignature();
311}
312
313bool
314Data::operator!=(const Data& other) const
315{
316 return !(*this == other);
317}
318
319std::ostream&
320operator<<(std::ostream& os, const Data& data)
321{
322 os << "Name: " << data.getName() << "\n";
323 os << "MetaInfo: " << data.getMetaInfo() << "\n";
324 os << "Content: (size: " << data.getContent().value_size() << ")\n";
325 os << "Signature: (type: " << data.getSignature().getType() <<
326 ", value_length: "<< data.getSignature().getValue().value_size() << ")";
327 os << std::endl;
328
329 return os;
330}
331
Junxiao Shi4b469982015-12-03 18:20:19 +0000332#ifdef NDN_LP_KEEP_LOCAL_CONTROL_HEADER
333
334// Permit deprecated usage for gcc only.
335// clang allows deprecated usage in deprecated functions, so it doesn't need this directive.
336#pragma GCC diagnostic push
337#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
338
339lp::LocalControlHeaderFacade
340Data::getLocalControlHeader()
341{
342 return lp::LocalControlHeaderFacade(*this);
343}
344
345const lp::LocalControlHeaderFacade
346Data::getLocalControlHeader() const
347{
348 return lp::LocalControlHeaderFacade(const_cast<Data&>(*this));
349}
350
351uint64_t
352Data::getIncomingFaceId() const
353{
354 return getLocalControlHeader().getIncomingFaceId();
355}
356
357Data&
358Data::setIncomingFaceId(uint64_t incomingFaceId)
359{
360 getLocalControlHeader().setIncomingFaceId(incomingFaceId);
361 return *this;
362}
363
364lp::LocalControlHeaderFacade::CachingPolicy
365Data::getCachingPolicy() const
366{
367 return getLocalControlHeader().getCachingPolicy();
368}
369
370Data&
371Data::setCachingPolicy(lp::LocalControlHeaderFacade::CachingPolicy cachingPolicy)
372{
373 getLocalControlHeader().setCachingPolicy(cachingPolicy);
374 return *this;
375}
376
377#pragma GCC diagnostic pop
378
379#endif // NDN_LP_KEEP_LOCAL_CONTROL_HEADER
380
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700381} // namespace ndn