blob: 3a70b0d676f5d9f49c052d30d640b5604338dd55 [file] [log] [blame]
Alexander Afanasyev01065fb2014-10-02 13:01:46 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev74633892015-02-08 18:08:46 -08003 * Copyright (c) 2013-2015 Regents of the University of California.
Alexander Afanasyev01065fb2014-10-02 13:01:46 -07004 *
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 "meta-info.hpp"
23#include "encoding/block-helpers.hpp"
24#include "encoding/encoding-buffer.hpp"
Junxiao Shic2b8d242014-11-04 08:35:29 -070025#include "util/concepts.hpp"
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070026
27namespace ndn {
28
Shock Jiangca7ea702014-10-02 11:23:25 -070029BOOST_CONCEPT_ASSERT((boost::EqualityComparable<MetaInfo>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070030BOOST_CONCEPT_ASSERT((WireEncodable<MetaInfo>));
31BOOST_CONCEPT_ASSERT((WireDecodable<MetaInfo>));
32static_assert(std::is_base_of<tlv::Error, MetaInfo::Error>::value,
33 "MetaInfo::Error must inherit from tlv::Error");
Shock Jiangca7ea702014-10-02 11:23:25 -070034
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070035MetaInfo::MetaInfo()
Junxiao Shia464b922014-11-12 21:13:06 -070036 : m_type(tlv::ContentType_Blob)
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070037 , m_freshnessPeriod(-1)
38{
39}
40
41MetaInfo::MetaInfo(const Block& block)
42{
43 wireDecode(block);
44}
45
46MetaInfo&
47MetaInfo::setType(uint32_t type)
48{
49 m_wire.reset();
50 m_type = type;
51 return *this;
52}
53
54MetaInfo&
55MetaInfo::setFreshnessPeriod(const time::milliseconds& freshnessPeriod)
56{
57 m_wire.reset();
58 m_freshnessPeriod = freshnessPeriod;
59 return *this;
60}
61
62MetaInfo&
63MetaInfo::setFinalBlockId(const name::Component& finalBlockId)
64{
65 m_wire.reset();
66 m_finalBlockId = finalBlockId;
67 return *this;
68}
69
Shock Jiangca7ea702014-10-02 11:23:25 -070070const std::list<Block>&
71MetaInfo::getAppMetaInfo() const
72{
73 return m_appMetaInfo;
74}
75
76MetaInfo&
77MetaInfo::setAppMetaInfo(const std::list<Block>& info)
78{
79 for (std::list<Block>::const_iterator i = info.begin(); i != info.end(); ++i) {
80 if (!(128 <= i->type() && i->type() <= 252))
81 throw Error("AppMetaInfo block has type outside the application range [128, 252]");
82 }
83
84 m_wire.reset();
85 m_appMetaInfo = info;
86 return *this;
87}
88
89MetaInfo&
90MetaInfo::addAppMetaInfo(const Block& block)
91{
92 if (!(128 <= block.type() && block.type() <= 252))
93 throw Error("AppMetaInfo block has type outside the application range [128, 252]");
94
95 m_wire.reset();
96 m_appMetaInfo.push_back(block);
97 return *this;
98}
99
100bool
101MetaInfo::removeAppMetaInfo(uint32_t tlvType)
102{
103 for (std::list<Block>::iterator iter = m_appMetaInfo.begin();
104 iter != m_appMetaInfo.end(); ++iter) {
105 if (iter->type() == tlvType) {
106 m_wire.reset();
107 m_appMetaInfo.erase(iter);
108 return true;
109 }
110 }
111 return false;
112}
113
114const Block*
115MetaInfo::findAppMetaInfo(uint32_t tlvType) const
116{
117 for (std::list<Block>::const_iterator iter = m_appMetaInfo.begin();
118 iter != m_appMetaInfo.end(); ++iter) {
119 if (iter->type() == tlvType) {
120 return &*iter;
121 }
122 }
123 return 0;
124}
125
Alexander Afanasyev74633892015-02-08 18:08:46 -0800126template<encoding::Tag TAG>
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700127size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800128MetaInfo::wireEncode(EncodingImpl<TAG>& encoder) const
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700129{
130 // MetaInfo ::= META-INFO-TYPE TLV-LENGTH
131 // ContentType?
132 // FreshnessPeriod?
133 // FinalBlockId?
Shock Jiangca7ea702014-10-02 11:23:25 -0700134 // AppMetaInfo*
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700135
136 size_t totalLength = 0;
137
Shock Jiangca7ea702014-10-02 11:23:25 -0700138 for (std::list<Block>::const_reverse_iterator appMetaInfoItem = m_appMetaInfo.rbegin();
139 appMetaInfoItem != m_appMetaInfo.rend(); ++appMetaInfoItem) {
Alexander Afanasyev74633892015-02-08 18:08:46 -0800140 totalLength += encoder.prependBlock(*appMetaInfoItem);
Shock Jiangca7ea702014-10-02 11:23:25 -0700141 }
142
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700143 // FinalBlockId
144 if (!m_finalBlockId.empty())
145 {
Alexander Afanasyev74633892015-02-08 18:08:46 -0800146 totalLength += prependNestedBlock(encoder, tlv::FinalBlockId, m_finalBlockId);
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700147 }
148
149 // FreshnessPeriod
150 if (m_freshnessPeriod >= time::milliseconds::zero())
151 {
Alexander Afanasyev74633892015-02-08 18:08:46 -0800152 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::FreshnessPeriod,
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700153 m_freshnessPeriod.count());
154 }
155
156 // ContentType
Junxiao Shia464b922014-11-12 21:13:06 -0700157 if (m_type != tlv::ContentType_Blob)
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700158 {
Alexander Afanasyev74633892015-02-08 18:08:46 -0800159 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::ContentType, m_type);
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700160 }
161
Alexander Afanasyev74633892015-02-08 18:08:46 -0800162 totalLength += encoder.prependVarNumber(totalLength);
163 totalLength += encoder.prependVarNumber(tlv::MetaInfo);
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700164 return totalLength;
165}
166
167template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800168MetaInfo::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700169
170template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800171MetaInfo::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700172
173const Block&
174MetaInfo::wireEncode() const
175{
176 if (m_wire.hasWire())
177 return m_wire;
178
179 EncodingEstimator estimator;
180 size_t estimatedSize = wireEncode(estimator);
181
182 EncodingBuffer buffer(estimatedSize, 0);
183 wireEncode(buffer);
184
185 m_wire = buffer.block();
186 return m_wire;
187}
188
189void
190MetaInfo::wireDecode(const Block& wire)
191{
192 m_wire = wire;
193 m_wire.parse();
194
195 // MetaInfo ::= META-INFO-TYPE TLV-LENGTH
196 // ContentType?
197 // FreshnessPeriod?
Shock Jiangca7ea702014-10-02 11:23:25 -0700198 // FinalBlockId?
199 // AppMetaInfo*
200
201
202 Block::element_const_iterator val = m_wire.elements_begin();
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700203
204 // ContentType
Shock Jiangca7ea702014-10-02 11:23:25 -0700205 if (val != m_wire.elements_end() && val->type() == tlv::ContentType) {
206 m_type = readNonNegativeInteger(*val);
207 ++val;
208 }
209 else {
Junxiao Shia464b922014-11-12 21:13:06 -0700210 m_type = tlv::ContentType_Blob;
Shock Jiangca7ea702014-10-02 11:23:25 -0700211 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700212
213 // FreshnessPeriod
Shock Jiangca7ea702014-10-02 11:23:25 -0700214 if (val != m_wire.elements_end() && val->type() == tlv::FreshnessPeriod) {
215 m_freshnessPeriod = time::milliseconds(readNonNegativeInteger(*val));
216 ++val;
217 }
218 else {
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700219 m_freshnessPeriod = time::milliseconds::min();
Shock Jiangca7ea702014-10-02 11:23:25 -0700220 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700221
222 // FinalBlockId
Shock Jiangca7ea702014-10-02 11:23:25 -0700223 if (val != m_wire.elements_end() && val->type() == tlv::FinalBlockId) {
224 m_finalBlockId = val->blockFromValue();
225 if (m_finalBlockId.type() != tlv::NameComponent)
226 {
227 /// @todo May or may not throw exception later...
228 m_finalBlockId.reset();
229 }
230 ++val;
231 }
232 else {
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700233 m_finalBlockId.reset();
Shock Jiangca7ea702014-10-02 11:23:25 -0700234 }
235
236 // AppMetaInfo (if any)
237 for (; val != m_wire.elements().end(); ++val) {
238 m_appMetaInfo.push_back(*val);
239 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700240}
241
242std::ostream&
243operator<<(std::ostream& os, const MetaInfo& info)
244{
245 // ContentType
246 os << "ContentType: " << info.getType();
247
248 // FreshnessPeriod
249 if (info.getFreshnessPeriod() >= time::milliseconds::zero()) {
250 os << ", FreshnessPeriod: " << info.getFreshnessPeriod();
251 }
252
Shock Jiangca7ea702014-10-02 11:23:25 -0700253 // FinalBlockId
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700254 if (!info.getFinalBlockId().empty()) {
255 os << ", FinalBlockId: ";
256 info.getFinalBlockId().toUri(os);
257 }
Shock Jiangca7ea702014-10-02 11:23:25 -0700258
259 // App-defined MetaInfo items
260 for (std::list<Block>::const_iterator iter = info.getAppMetaInfo().begin();
261 iter != info.getAppMetaInfo().end(); ++iter) {
262 os << ", AppMetaInfoTlvType: " << iter->type();
263 }
264
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700265 return os;
266}
267
268} // namespace ndn