blob: 77fc3c97c626143175624a34d46154945e6b0a95 [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
Alexander Afanasyev15f67312014-07-22 15:11:09 -070087
88template size_t
89Data::wireEncode<true>(EncodingImpl<true>& block, bool unsignedPortion) const;
90
91template size_t
92Data::wireEncode<false>(EncodingImpl<false>& block, bool unsignedPortion) const;
93
94
Alexander Afanasyev197e5652014-06-13 16:56:31 -070095const Block&
96Data::wireEncode(EncodingBuffer& encoder, const Block& signatureValue) const
97{
98 size_t totalLength = encoder.size();
99 totalLength += encoder.appendBlock(signatureValue);
100
101 totalLength += encoder.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600102 encoder.prependVarNumber(tlv::Data);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700103
104 const_cast<Data*>(this)->wireDecode(encoder.block());
105 return m_wire;
106}
107
108const Block&
109Data::wireEncode() const
110{
111 if (m_wire.hasWire())
112 return m_wire;
113
114 EncodingEstimator estimator;
115 size_t estimatedSize = wireEncode(estimator);
116
117 EncodingBuffer buffer(estimatedSize, 0);
118 wireEncode(buffer);
119
120 const_cast<Data*>(this)->wireDecode(buffer.block());
121 return m_wire;
122}
123
124void
125Data::wireDecode(const Block& wire)
126{
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700127 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700128 m_wire = wire;
129 m_wire.parse();
130
131 // Data ::= DATA-TLV TLV-LENGTH
132 // Name
133 // MetaInfo
134 // Content
135 // Signature
136
137 // Name
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600138 m_name.wireDecode(m_wire.get(tlv::Name));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700139
140 // MetaInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600141 m_metaInfo.wireDecode(m_wire.get(tlv::MetaInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700142
143 // Content
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600144 m_content = m_wire.get(tlv::Content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700145
146 ///////////////
147 // Signature //
148 ///////////////
149
150 // SignatureInfo
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600151 m_signature.setInfo(m_wire.get(tlv::SignatureInfo));
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700152
153 // SignatureValue
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600154 Block::element_const_iterator val = m_wire.find(tlv::SignatureValue);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700155 if (val != m_wire.elements_end())
156 m_signature.setValue(*val);
157}
158
159Data&
160Data::setName(const Name& name)
161{
162 onChanged();
163 m_name = name;
164
165 return *this;
166}
167
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700168const Name&
169Data::getFullName() const
170{
171 if (m_fullName.empty()) {
172 if (!m_wire.hasWire()) {
173 throw Error("Full name requested, but Data packet does not have wire format "
174 "(e.g., not signed)");
175 }
176 m_fullName = m_name;
177 m_fullName.append(name::Component(crypto::sha256(m_wire.wire(), m_wire.size())));
178 }
179
180 return m_fullName;
181}
182
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700183Data&
184Data::setMetaInfo(const MetaInfo& metaInfo)
185{
186 onChanged();
187 m_metaInfo = metaInfo;
188
189 return *this;
190}
191
192Data&
193Data::setContentType(uint32_t type)
194{
195 onChanged();
196 m_metaInfo.setType(type);
197
198 return *this;
199}
200
201Data&
202Data::setFreshnessPeriod(const time::milliseconds& freshnessPeriod)
203{
204 onChanged();
205 m_metaInfo.setFreshnessPeriod(freshnessPeriod);
206
207 return *this;
208}
209
210Data&
211Data::setFinalBlockId(const name::Component& finalBlockId)
212{
213 onChanged();
214 m_metaInfo.setFinalBlockId(finalBlockId);
215
216 return *this;
217}
218
219const Block&
220Data::getContent() const
221{
222 if (m_content.empty())
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600223 m_content = dataBlock(tlv::Content, reinterpret_cast<const uint8_t*>(0), 0);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700224
225 if (!m_content.hasWire())
226 m_content.encode();
227 return m_content;
228}
229
230Data&
231Data::setContent(const uint8_t* content, size_t contentLength)
232{
233 onChanged();
234
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600235 m_content = dataBlock(tlv::Content, content, contentLength);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700236
237 return *this;
238}
239
240Data&
241Data::setContent(const ConstBufferPtr& contentValue)
242{
243 onChanged();
244
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600245 m_content = Block(tlv::Content, contentValue); // not a real wire encoding yet
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700246
247 return *this;
248}
249
250Data&
251Data::setContent(const Block& content)
252{
253 onChanged();
254
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600255 if (content.type() == tlv::Content)
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700256 m_content = content;
257 else {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600258 m_content = Block(tlv::Content, content);
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700259 }
260
261 return *this;
262}
263
264Data&
265Data::setSignature(const Signature& signature)
266{
267 onChanged();
268 m_signature = signature;
269
270 return *this;
271}
272
273Data&
274Data::setSignatureValue(const Block& value)
275{
276 onChanged();
277 m_signature.setValue(value);
278
279 return *this;
280}
281
282//
283
284Data&
285Data::setIncomingFaceId(uint64_t incomingFaceId)
286{
287 getLocalControlHeader().setIncomingFaceId(incomingFaceId);
288 // ! do not reset Data's wire !
289
290 return *this;
291}
292
293void
294Data::onChanged()
295{
296 // The values have changed, so the wire format is invalidated
297
298 // !!!Note!!! Signature is not invalidated and it is responsibility of
299 // the application to do proper re-signing if necessary
300
301 m_wire.reset();
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700302 m_fullName.clear();
Alexander Afanasyev197e5652014-06-13 16:56:31 -0700303}
304
305bool
306Data::operator==(const Data& other) const
307{
308 return getName() == other.getName() &&
309 getMetaInfo() == other.getMetaInfo() &&
310 getContent() == other.getContent() &&
311 getSignature() == other.getSignature();
312}
313
314bool
315Data::operator!=(const Data& other) const
316{
317 return !(*this == other);
318}
319
320std::ostream&
321operator<<(std::ostream& os, const Data& data)
322{
323 os << "Name: " << data.getName() << "\n";
324 os << "MetaInfo: " << data.getMetaInfo() << "\n";
325 os << "Content: (size: " << data.getContent().value_size() << ")\n";
326 os << "Signature: (type: " << data.getSignature().getType() <<
327 ", value_length: "<< data.getSignature().getValue().value_size() << ")";
328 os << std::endl;
329
330 return os;
331}
332
333} // namespace ndn