blob: 8ce8f4cdc930e37f5623babbf97dae2091e70f7b [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()
28 : m_content(Tlv::Content) // empty content
29{
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);
82 totalLength += block.prependVarNumber(Tlv::Data);
83 }
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);
94 encoder.prependVarNumber(Tlv::Data);
95
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{
119 m_wire = wire;
120 m_wire.parse();
121
122 // Data ::= DATA-TLV TLV-LENGTH
123 // Name
124 // MetaInfo
125 // Content
126 // Signature
127
128 // Name
129 m_name.wireDecode(m_wire.get(Tlv::Name));
130
131 // MetaInfo
132 m_metaInfo.wireDecode(m_wire.get(Tlv::MetaInfo));
133
134 // Content
135 m_content = m_wire.get(Tlv::Content);
136
137 ///////////////
138 // Signature //
139 ///////////////
140
141 // SignatureInfo
142 m_signature.setInfo(m_wire.get(Tlv::SignatureInfo));
143
144 // SignatureValue
145 Block::element_const_iterator val = m_wire.find(Tlv::SignatureValue);
146 if (val != m_wire.elements_end())
147 m_signature.setValue(*val);
148}
149
150Data&
151Data::setName(const Name& name)
152{
153 onChanged();
154 m_name = name;
155
156 return *this;
157}
158
159Data&
160Data::setMetaInfo(const MetaInfo& metaInfo)
161{
162 onChanged();
163 m_metaInfo = metaInfo;
164
165 return *this;
166}
167
168Data&
169Data::setContentType(uint32_t type)
170{
171 onChanged();
172 m_metaInfo.setType(type);
173
174 return *this;
175}
176
177Data&
178Data::setFreshnessPeriod(const time::milliseconds& freshnessPeriod)
179{
180 onChanged();
181 m_metaInfo.setFreshnessPeriod(freshnessPeriod);
182
183 return *this;
184}
185
186Data&
187Data::setFinalBlockId(const name::Component& finalBlockId)
188{
189 onChanged();
190 m_metaInfo.setFinalBlockId(finalBlockId);
191
192 return *this;
193}
194
195const Block&
196Data::getContent() const
197{
198 if (m_content.empty())
199 m_content = dataBlock(Tlv::Content, reinterpret_cast<const uint8_t*>(0), 0);
200
201 if (!m_content.hasWire())
202 m_content.encode();
203 return m_content;
204}
205
206Data&
207Data::setContent(const uint8_t* content, size_t contentLength)
208{
209 onChanged();
210
211 m_content = dataBlock(Tlv::Content, content, contentLength);
212
213 return *this;
214}
215
216Data&
217Data::setContent(const ConstBufferPtr& contentValue)
218{
219 onChanged();
220
221 m_content = Block(Tlv::Content, contentValue); // not a real wire encoding yet
222
223 return *this;
224}
225
226Data&
227Data::setContent(const Block& content)
228{
229 onChanged();
230
231 if (content.type() == Tlv::Content)
232 m_content = content;
233 else {
234 m_content = Block(Tlv::Content, content);
235 }
236
237 return *this;
238}
239
240Data&
241Data::setSignature(const Signature& signature)
242{
243 onChanged();
244 m_signature = signature;
245
246 return *this;
247}
248
249Data&
250Data::setSignatureValue(const Block& value)
251{
252 onChanged();
253 m_signature.setValue(value);
254
255 return *this;
256}
257
258//
259
260Data&
261Data::setIncomingFaceId(uint64_t incomingFaceId)
262{
263 getLocalControlHeader().setIncomingFaceId(incomingFaceId);
264 // ! do not reset Data's wire !
265
266 return *this;
267}
268
269void
270Data::onChanged()
271{
272 // The values have changed, so the wire format is invalidated
273
274 // !!!Note!!! Signature is not invalidated and it is responsibility of
275 // the application to do proper re-signing if necessary
276
277 m_wire.reset();
278}
279
280bool
281Data::operator==(const Data& other) const
282{
283 return getName() == other.getName() &&
284 getMetaInfo() == other.getMetaInfo() &&
285 getContent() == other.getContent() &&
286 getSignature() == other.getSignature();
287}
288
289bool
290Data::operator!=(const Data& other) const
291{
292 return !(*this == other);
293}
294
295std::ostream&
296operator<<(std::ostream& os, const Data& data)
297{
298 os << "Name: " << data.getName() << "\n";
299 os << "MetaInfo: " << data.getMetaInfo() << "\n";
300 os << "Content: (size: " << data.getContent().value_size() << ")\n";
301 os << "Signature: (type: " << data.getSignature().getType() <<
302 ", value_length: "<< data.getSignature().getValue().value_size() << ")";
303 os << std::endl;
304
305 return os;
306}
307
308} // namespace ndn