blob: d0953823bae1d44539b115b7c9aa2b9982a914bc [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"
23#include "util/crypto.hpp"
24
25namespace ndn {
26
27Data::Data()
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060028 : m_content(tlv::Content) // empty content
Alexander Afanasyev197e5652014-06-13 16:56:31 -070029{
30}
31
32Data::Data(const Name& name)
33 : m_name(name)
34{
35}
36
37Data::Data(const Block& wire)
38{
39 wireDecode(wire);
40}
41
42template<bool T>
43size_t
44Data::wireEncode(EncodingImpl<T>& block, bool unsignedPortion/* = false*/) const
45{
46 size_t totalLength = 0;
47
48 // Data ::= DATA-TLV TLV-LENGTH
49 // Name
50 // MetaInfo
51 // Content
52 // Signature
53
54 // (reverse encoding)
55
56 if (!unsignedPortion && !m_signature)
57 {
58 throw Error("Requested wire format, but data packet has not been signed yet");
59 }
60
61 if (!unsignedPortion)
62 {
63 // SignatureValue
64 totalLength += prependBlock(block, m_signature.getValue());
65 }
66
67 // SignatureInfo
68 totalLength += prependBlock(block, m_signature.getInfo());
69
70 // Content
71 totalLength += prependBlock(block, getContent());
72
73 // MetaInfo
74 totalLength += getMetaInfo().wireEncode(block);
75
76 // Name
77 totalLength += getName().wireEncode(block);
78
79 if (!unsignedPortion)
80 {
81 totalLength += block.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060082 totalLength += block.prependVarNumber(tlv::Data);
Alexander Afanasyev197e5652014-06-13 16:56:31 -070083 }
84 return totalLength;
85}
86
87const Block&
88Data::wireEncode(EncodingBuffer& encoder, const Block& signatureValue) const
89{
90 size_t totalLength = encoder.size();
91 totalLength += encoder.appendBlock(signatureValue);
92
93 totalLength += encoder.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060094 encoder.prependVarNumber(tlv::Data);
Alexander Afanasyev197e5652014-06-13 16:56:31 -070095
96 const_cast<Data*>(this)->wireDecode(encoder.block());
97 return m_wire;
98}
99
100const Block&
101Data::wireEncode() const
102{
103 if (m_wire.hasWire())
104 return m_wire;
105
106 EncodingEstimator estimator;
107 size_t estimatedSize = wireEncode(estimator);
108
109 EncodingBuffer buffer(estimatedSize, 0);
110 wireEncode(buffer);
111
112 const_cast<Data*>(this)->wireDecode(buffer.block());
113 return m_wire;
114}
115
116void
117Data::wireDecode(const Block& wire)
118{
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700119 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700120 m_wire = wire;
121 m_wire.parse();
122
123 // Data ::= DATA-TLV TLV-LENGTH
124 // Name
125 // MetaInfo
126 // Content
127 // Signature
128
129 // Name
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600130 m_name.wireDecode(m_wire.get(tlv::Name));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700131
132 // MetaInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600133 m_metaInfo.wireDecode(m_wire.get(tlv::MetaInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700134
135 // Content
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600136 m_content = m_wire.get(tlv::Content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700137
138 ///////////////
139 // Signature //
140 ///////////////
141
142 // SignatureInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600143 m_signature.setInfo(m_wire.get(tlv::SignatureInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700144
145 // SignatureValue
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600146 Block::element_const_iterator val = m_wire.find(tlv::SignatureValue);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700147 if (val != m_wire.elements_end())
148 m_signature.setValue(*val);
149}
150
151Data&
152Data::setName(const Name& name)
153{
154 onChanged();
155 m_name = name;
156
157 return *this;
158}
159
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700160const Name&
161Data::getFullName() const
162{
163 if (m_fullName.empty()) {
164 if (!m_wire.hasWire()) {
165 throw Error("Full name requested, but Data packet does not have wire format "
166 "(e.g., not signed)");
167 }
168 m_fullName = m_name;
169 m_fullName.append(name::Component(crypto::sha256(m_wire.wire(), m_wire.size())));
170 }
171
172 return m_fullName;
173}
174
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700175Data&
176Data::setMetaInfo(const MetaInfo& metaInfo)
177{
178 onChanged();
179 m_metaInfo = metaInfo;
180
181 return *this;
182}
183
184Data&
185Data::setContentType(uint32_t type)
186{
187 onChanged();
188 m_metaInfo.setType(type);
189
190 return *this;
191}
192
193Data&
194Data::setFreshnessPeriod(const time::milliseconds& freshnessPeriod)
195{
196 onChanged();
197 m_metaInfo.setFreshnessPeriod(freshnessPeriod);
198
199 return *this;
200}
201
202Data&
203Data::setFinalBlockId(const name::Component& finalBlockId)
204{
205 onChanged();
206 m_metaInfo.setFinalBlockId(finalBlockId);
207
208 return *this;
209}
210
211const Block&
212Data::getContent() const
213{
214 if (m_content.empty())
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600215 m_content = dataBlock(tlv::Content, reinterpret_cast<const uint8_t*>(0), 0);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700216
217 if (!m_content.hasWire())
218 m_content.encode();
219 return m_content;
220}
221
222Data&
223Data::setContent(const uint8_t* content, size_t contentLength)
224{
225 onChanged();
226
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600227 m_content = dataBlock(tlv::Content, content, contentLength);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700228
229 return *this;
230}
231
232Data&
233Data::setContent(const ConstBufferPtr& contentValue)
234{
235 onChanged();
236
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600237 m_content = Block(tlv::Content, contentValue); // not a real wire encoding yet
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700238
239 return *this;
240}
241
242Data&
243Data::setContent(const Block& content)
244{
245 onChanged();
246
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600247 if (content.type() == tlv::Content)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700248 m_content = content;
249 else {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600250 m_content = Block(tlv::Content, content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700251 }
252
253 return *this;
254}
255
256Data&
257Data::setSignature(const Signature& signature)
258{
259 onChanged();
260 m_signature = signature;
261
262 return *this;
263}
264
265Data&
266Data::setSignatureValue(const Block& value)
267{
268 onChanged();
269 m_signature.setValue(value);
270
271 return *this;
272}
273
274//
275
276Data&
277Data::setIncomingFaceId(uint64_t incomingFaceId)
278{
279 getLocalControlHeader().setIncomingFaceId(incomingFaceId);
280 // ! do not reset Data's wire !
281
282 return *this;
283}
284
285void
286Data::onChanged()
287{
288 // The values have changed, so the wire format is invalidated
289
290 // !!!Note!!! Signature is not invalidated and it is responsibility of
291 // the application to do proper re-signing if necessary
292
293 m_wire.reset();
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700294 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700295}
296
297bool
298Data::operator==(const Data& other) const
299{
300 return getName() == other.getName() &&
301 getMetaInfo() == other.getMetaInfo() &&
302 getContent() == other.getContent() &&
303 getSignature() == other.getSignature();
304}
305
306bool
307Data::operator!=(const Data& other) const
308{
309 return !(*this == other);
310}
311
312std::ostream&
313operator<<(std::ostream& os, const Data& data)
314{
315 os << "Name: " << data.getName() << "\n";
316 os << "MetaInfo: " << data.getMetaInfo() << "\n";
317 os << "Content: (size: " << data.getContent().value_size() << ")\n";
318 os << "Signature: (type: " << data.getSignature().getType() <<
319 ", value_length: "<< data.getSignature().getValue().value_size() << ")";
320 os << std::endl;
321
322 return os;
323}
324
325} // namespace ndn