blob: 0a2e3fb738c6c18148470ef71e25f2d51e139e84 [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"
25
26namespace ndn {
27
28Data::Data()
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060029 : m_content(tlv::Content) // empty content
Alexander Afanasyev197e5652014-06-13 16:56:31 -070030{
31}
32
33Data::Data(const Name& name)
34 : m_name(name)
35{
36}
37
38Data::Data(const Block& wire)
39{
40 wireDecode(wire);
41}
42
43template<bool T>
44size_t
45Data::wireEncode(EncodingImpl<T>& block, bool unsignedPortion/* = false*/) const
46{
47 size_t totalLength = 0;
48
49 // Data ::= DATA-TLV TLV-LENGTH
50 // Name
51 // MetaInfo
52 // Content
53 // Signature
54
55 // (reverse encoding)
56
57 if (!unsignedPortion && !m_signature)
58 {
59 throw Error("Requested wire format, but data packet has not been signed yet");
60 }
61
62 if (!unsignedPortion)
63 {
64 // SignatureValue
65 totalLength += prependBlock(block, m_signature.getValue());
66 }
67
68 // SignatureInfo
69 totalLength += prependBlock(block, m_signature.getInfo());
70
71 // Content
72 totalLength += prependBlock(block, getContent());
73
74 // MetaInfo
75 totalLength += getMetaInfo().wireEncode(block);
76
77 // Name
78 totalLength += getName().wireEncode(block);
79
80 if (!unsignedPortion)
81 {
82 totalLength += block.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060083 totalLength += block.prependVarNumber(tlv::Data);
Alexander Afanasyev197e5652014-06-13 16:56:31 -070084 }
85 return totalLength;
86}
87
Alexander Afanasyev15f67312014-07-22 15:11:09 -070088
89template size_t
90Data::wireEncode<true>(EncodingImpl<true>& block, bool unsignedPortion) const;
91
92template size_t
93Data::wireEncode<false>(EncodingImpl<false>& block, bool unsignedPortion) const;
94
95
Alexander Afanasyev197e5652014-06-13 16:56:31 -070096const Block&
97Data::wireEncode(EncodingBuffer& encoder, const Block& signatureValue) const
98{
99 size_t totalLength = encoder.size();
100 totalLength += encoder.appendBlock(signatureValue);
101
102 totalLength += encoder.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600103 encoder.prependVarNumber(tlv::Data);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700104
105 const_cast<Data*>(this)->wireDecode(encoder.block());
106 return m_wire;
107}
108
109const Block&
110Data::wireEncode() const
111{
112 if (m_wire.hasWire())
113 return m_wire;
114
115 EncodingEstimator estimator;
116 size_t estimatedSize = wireEncode(estimator);
117
118 EncodingBuffer buffer(estimatedSize, 0);
119 wireEncode(buffer);
120
121 const_cast<Data*>(this)->wireDecode(buffer.block());
122 return m_wire;
123}
124
125void
126Data::wireDecode(const Block& wire)
127{
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700128 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700129 m_wire = wire;
130 m_wire.parse();
131
132 // Data ::= DATA-TLV TLV-LENGTH
133 // Name
134 // MetaInfo
135 // Content
136 // Signature
137
138 // Name
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600139 m_name.wireDecode(m_wire.get(tlv::Name));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700140
141 // MetaInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600142 m_metaInfo.wireDecode(m_wire.get(tlv::MetaInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700143
144 // Content
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600145 m_content = m_wire.get(tlv::Content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700146
147 ///////////////
148 // Signature //
149 ///////////////
150
151 // SignatureInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600152 m_signature.setInfo(m_wire.get(tlv::SignatureInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700153
154 // SignatureValue
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600155 Block::element_const_iterator val = m_wire.find(tlv::SignatureValue);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700156 if (val != m_wire.elements_end())
157 m_signature.setValue(*val);
158}
159
160Data&
161Data::setName(const Name& name)
162{
163 onChanged();
164 m_name = name;
165
166 return *this;
167}
168
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700169const Name&
170Data::getFullName() const
171{
172 if (m_fullName.empty()) {
173 if (!m_wire.hasWire()) {
174 throw Error("Full name requested, but Data packet does not have wire format "
175 "(e.g., not signed)");
176 }
177 m_fullName = m_name;
178 m_fullName.append(name::Component(crypto::sha256(m_wire.wire(), m_wire.size())));
179 }
180
181 return m_fullName;
182}
183
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700184Data&
185Data::setMetaInfo(const MetaInfo& metaInfo)
186{
187 onChanged();
188 m_metaInfo = metaInfo;
189
190 return *this;
191}
192
193Data&
194Data::setContentType(uint32_t type)
195{
196 onChanged();
197 m_metaInfo.setType(type);
198
199 return *this;
200}
201
202Data&
203Data::setFreshnessPeriod(const time::milliseconds& freshnessPeriod)
204{
205 onChanged();
206 m_metaInfo.setFreshnessPeriod(freshnessPeriod);
207
208 return *this;
209}
210
211Data&
212Data::setFinalBlockId(const name::Component& finalBlockId)
213{
214 onChanged();
215 m_metaInfo.setFinalBlockId(finalBlockId);
216
217 return *this;
218}
219
220const Block&
221Data::getContent() const
222{
223 if (m_content.empty())
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600224 m_content = dataBlock(tlv::Content, reinterpret_cast<const uint8_t*>(0), 0);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700225
226 if (!m_content.hasWire())
227 m_content.encode();
228 return m_content;
229}
230
231Data&
232Data::setContent(const uint8_t* content, size_t contentLength)
233{
234 onChanged();
235
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600236 m_content = dataBlock(tlv::Content, content, contentLength);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700237
238 return *this;
239}
240
241Data&
242Data::setContent(const ConstBufferPtr& contentValue)
243{
244 onChanged();
245
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600246 m_content = Block(tlv::Content, contentValue); // not a real wire encoding yet
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700247
248 return *this;
249}
250
251Data&
252Data::setContent(const Block& content)
253{
254 onChanged();
255
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600256 if (content.type() == tlv::Content)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700257 m_content = content;
258 else {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600259 m_content = Block(tlv::Content, content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700260 }
261
262 return *this;
263}
264
265Data&
266Data::setSignature(const Signature& signature)
267{
268 onChanged();
269 m_signature = signature;
270
271 return *this;
272}
273
274Data&
275Data::setSignatureValue(const Block& value)
276{
277 onChanged();
278 m_signature.setValue(value);
279
280 return *this;
281}
282
283//
284
285Data&
286Data::setIncomingFaceId(uint64_t incomingFaceId)
287{
288 getLocalControlHeader().setIncomingFaceId(incomingFaceId);
289 // ! do not reset Data's wire !
290
291 return *this;
292}
293
294void
295Data::onChanged()
296{
297 // The values have changed, so the wire format is invalidated
298
299 // !!!Note!!! Signature is not invalidated and it is responsibility of
300 // the application to do proper re-signing if necessary
301
302 m_wire.reset();
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700303 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700304}
305
306bool
307Data::operator==(const Data& other) const
308{
309 return getName() == other.getName() &&
310 getMetaInfo() == other.getMetaInfo() &&
311 getContent() == other.getContent() &&
312 getSignature() == other.getSignature();
313}
314
315bool
316Data::operator!=(const Data& other) const
317{
318 return !(*this == other);
319}
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";
327 os << "Signature: (type: " << data.getSignature().getType() <<
328 ", value_length: "<< data.getSignature().getValue().value_size() << ")";
329 os << std::endl;
330
331 return os;
332}
333
334} // namespace ndn