blob: 8615c525621b7732718bf9d744bdd518df3b3b70 [file] [log] [blame]
Alexander Afanasyev197e5652014-06-13 16:56:31 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2014 Regents of the University of California.
4 *
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
50template<bool T>
51size_t
52Data::wireEncode(EncodingImpl<T>& block, bool unsignedPortion/* = false*/) const
53{
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
72 totalLength += prependBlock(block, m_signature.getValue());
73 }
74
75 // SignatureInfo
76 totalLength += prependBlock(block, m_signature.getInfo());
77
78 // Content
79 totalLength += prependBlock(block, getContent());
80
81 // MetaInfo
82 totalLength += getMetaInfo().wireEncode(block);
83
84 // Name
85 totalLength += getName().wireEncode(block);
86
87 if (!unsignedPortion)
88 {
89 totalLength += block.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060090 totalLength += block.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
97Data::wireEncode<true>(EncodingImpl<true>& block, bool unsignedPortion) const;
98
99template size_t
100Data::wireEncode<false>(EncodingImpl<false>& block, bool unsignedPortion) const;
101
102
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700103const Block&
104Data::wireEncode(EncodingBuffer& encoder, const Block& signatureValue) const
105{
106 size_t totalLength = encoder.size();
107 totalLength += encoder.appendBlock(signatureValue);
108
109 totalLength += encoder.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600110 encoder.prependVarNumber(tlv::Data);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700111
112 const_cast<Data*>(this)->wireDecode(encoder.block());
113 return m_wire;
114}
115
116const Block&
117Data::wireEncode() const
118{
119 if (m_wire.hasWire())
120 return m_wire;
121
122 EncodingEstimator estimator;
123 size_t estimatedSize = wireEncode(estimator);
124
125 EncodingBuffer buffer(estimatedSize, 0);
126 wireEncode(buffer);
127
128 const_cast<Data*>(this)->wireDecode(buffer.block());
129 return m_wire;
130}
131
132void
133Data::wireDecode(const Block& wire)
134{
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700135 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700136 m_wire = wire;
137 m_wire.parse();
138
139 // Data ::= DATA-TLV TLV-LENGTH
140 // Name
141 // MetaInfo
142 // Content
143 // Signature
144
145 // Name
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600146 m_name.wireDecode(m_wire.get(tlv::Name));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700147
148 // MetaInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600149 m_metaInfo.wireDecode(m_wire.get(tlv::MetaInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700150
151 // Content
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600152 m_content = m_wire.get(tlv::Content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700153
154 ///////////////
155 // Signature //
156 ///////////////
157
158 // SignatureInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600159 m_signature.setInfo(m_wire.get(tlv::SignatureInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700160
161 // SignatureValue
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600162 Block::element_const_iterator val = m_wire.find(tlv::SignatureValue);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700163 if (val != m_wire.elements_end())
164 m_signature.setValue(*val);
165}
166
167Data&
168Data::setName(const Name& name)
169{
170 onChanged();
171 m_name = name;
172
173 return *this;
174}
175
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700176const Name&
177Data::getFullName() const
178{
179 if (m_fullName.empty()) {
180 if (!m_wire.hasWire()) {
181 throw Error("Full name requested, but Data packet does not have wire format "
182 "(e.g., not signed)");
183 }
184 m_fullName = m_name;
Alexander Afanasyevafee0a52014-11-07 11:15:34 -0800185 m_fullName.appendImplicitSha256Digest(crypto::sha256(m_wire.wire(), m_wire.size()));
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700186 }
187
188 return m_fullName;
189}
190
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700191Data&
192Data::setMetaInfo(const MetaInfo& metaInfo)
193{
194 onChanged();
195 m_metaInfo = metaInfo;
196
197 return *this;
198}
199
200Data&
201Data::setContentType(uint32_t type)
202{
203 onChanged();
204 m_metaInfo.setType(type);
205
206 return *this;
207}
208
209Data&
210Data::setFreshnessPeriod(const time::milliseconds& freshnessPeriod)
211{
212 onChanged();
213 m_metaInfo.setFreshnessPeriod(freshnessPeriod);
214
215 return *this;
216}
217
218Data&
219Data::setFinalBlockId(const name::Component& finalBlockId)
220{
221 onChanged();
222 m_metaInfo.setFinalBlockId(finalBlockId);
223
224 return *this;
225}
226
227const Block&
228Data::getContent() const
229{
230 if (m_content.empty())
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600231 m_content = dataBlock(tlv::Content, reinterpret_cast<const uint8_t*>(0), 0);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700232
233 if (!m_content.hasWire())
234 m_content.encode();
235 return m_content;
236}
237
238Data&
239Data::setContent(const uint8_t* content, size_t contentLength)
240{
241 onChanged();
242
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600243 m_content = dataBlock(tlv::Content, content, contentLength);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700244
245 return *this;
246}
247
248Data&
249Data::setContent(const ConstBufferPtr& contentValue)
250{
251 onChanged();
252
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600253 m_content = Block(tlv::Content, contentValue); // not a real wire encoding yet
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700254
255 return *this;
256}
257
258Data&
259Data::setContent(const Block& content)
260{
261 onChanged();
262
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600263 if (content.type() == tlv::Content)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700264 m_content = content;
265 else {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600266 m_content = Block(tlv::Content, content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700267 }
268
269 return *this;
270}
271
272Data&
273Data::setSignature(const Signature& signature)
274{
275 onChanged();
276 m_signature = signature;
277
278 return *this;
279}
280
281Data&
282Data::setSignatureValue(const Block& value)
283{
284 onChanged();
285 m_signature.setValue(value);
286
287 return *this;
288}
289
290//
291
292Data&
293Data::setIncomingFaceId(uint64_t incomingFaceId)
294{
295 getLocalControlHeader().setIncomingFaceId(incomingFaceId);
296 // ! do not reset Data's wire !
297
298 return *this;
299}
300
301void
302Data::onChanged()
303{
304 // The values have changed, so the wire format is invalidated
305
306 // !!!Note!!! Signature is not invalidated and it is responsibility of
307 // the application to do proper re-signing if necessary
308
309 m_wire.reset();
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700310 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700311}
312
313bool
314Data::operator==(const Data& other) const
315{
316 return getName() == other.getName() &&
317 getMetaInfo() == other.getMetaInfo() &&
318 getContent() == other.getContent() &&
319 getSignature() == other.getSignature();
320}
321
322bool
323Data::operator!=(const Data& other) const
324{
325 return !(*this == other);
326}
327
328std::ostream&
329operator<<(std::ostream& os, const Data& data)
330{
331 os << "Name: " << data.getName() << "\n";
332 os << "MetaInfo: " << data.getMetaInfo() << "\n";
333 os << "Content: (size: " << data.getContent().value_size() << ")\n";
334 os << "Signature: (type: " << data.getSignature().getType() <<
335 ", value_length: "<< data.getSignature().getValue().value_size() << ")";
336 os << std::endl;
337
338 return os;
339}
340
341} // namespace ndn