blob: e3ba2befd7e1e8fc5afd85138abaa9a73cbcc25f [file] [log] [blame]
Alexander Afanasyev01065fb2014-10-02 13:01:46 -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 "meta-info.hpp"
23#include "encoding/block-helpers.hpp"
24#include "encoding/encoding-buffer.hpp"
Shock Jiangca7ea702014-10-02 11:23:25 -070025
26#include <boost/concept_check.hpp>
27#include <boost/type_traits.hpp>
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070028
29namespace ndn {
30
Shock Jiangca7ea702014-10-02 11:23:25 -070031BOOST_CONCEPT_ASSERT((boost::EqualityComparable<MetaInfo>));
32BOOST_STATIC_ASSERT((boost::is_base_of<tlv::Error, MetaInfo::Error>::value));
33
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070034MetaInfo::MetaInfo()
35 : m_type(TYPE_DEFAULT)
36 , m_freshnessPeriod(-1)
37{
38}
39
40MetaInfo::MetaInfo(const Block& block)
41{
42 wireDecode(block);
43}
44
45MetaInfo&
46MetaInfo::setType(uint32_t type)
47{
48 m_wire.reset();
49 m_type = type;
50 return *this;
51}
52
53MetaInfo&
54MetaInfo::setFreshnessPeriod(const time::milliseconds& freshnessPeriod)
55{
56 m_wire.reset();
57 m_freshnessPeriod = freshnessPeriod;
58 return *this;
59}
60
61MetaInfo&
62MetaInfo::setFinalBlockId(const name::Component& finalBlockId)
63{
64 m_wire.reset();
65 m_finalBlockId = finalBlockId;
66 return *this;
67}
68
Shock Jiangca7ea702014-10-02 11:23:25 -070069const std::list<Block>&
70MetaInfo::getAppMetaInfo() const
71{
72 return m_appMetaInfo;
73}
74
75MetaInfo&
76MetaInfo::setAppMetaInfo(const std::list<Block>& info)
77{
78 for (std::list<Block>::const_iterator i = info.begin(); i != info.end(); ++i) {
79 if (!(128 <= i->type() && i->type() <= 252))
80 throw Error("AppMetaInfo block has type outside the application range [128, 252]");
81 }
82
83 m_wire.reset();
84 m_appMetaInfo = info;
85 return *this;
86}
87
88MetaInfo&
89MetaInfo::addAppMetaInfo(const Block& block)
90{
91 if (!(128 <= block.type() && block.type() <= 252))
92 throw Error("AppMetaInfo block has type outside the application range [128, 252]");
93
94 m_wire.reset();
95 m_appMetaInfo.push_back(block);
96 return *this;
97}
98
99bool
100MetaInfo::removeAppMetaInfo(uint32_t tlvType)
101{
102 for (std::list<Block>::iterator iter = m_appMetaInfo.begin();
103 iter != m_appMetaInfo.end(); ++iter) {
104 if (iter->type() == tlvType) {
105 m_wire.reset();
106 m_appMetaInfo.erase(iter);
107 return true;
108 }
109 }
110 return false;
111}
112
113const Block*
114MetaInfo::findAppMetaInfo(uint32_t tlvType) const
115{
116 for (std::list<Block>::const_iterator iter = m_appMetaInfo.begin();
117 iter != m_appMetaInfo.end(); ++iter) {
118 if (iter->type() == tlvType) {
119 return &*iter;
120 }
121 }
122 return 0;
123}
124
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700125template<bool T>
126size_t
127MetaInfo::wireEncode(EncodingImpl<T>& blk) const
128{
129 // MetaInfo ::= META-INFO-TYPE TLV-LENGTH
130 // ContentType?
131 // FreshnessPeriod?
132 // FinalBlockId?
Shock Jiangca7ea702014-10-02 11:23:25 -0700133 // AppMetaInfo*
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700134
135 size_t totalLength = 0;
136
Shock Jiangca7ea702014-10-02 11:23:25 -0700137 for (std::list<Block>::const_reverse_iterator appMetaInfoItem = m_appMetaInfo.rbegin();
138 appMetaInfoItem != m_appMetaInfo.rend(); ++appMetaInfoItem) {
139 totalLength += prependBlock(blk, *appMetaInfoItem);
140 }
141
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700142 // FinalBlockId
143 if (!m_finalBlockId.empty())
144 {
145 totalLength += prependNestedBlock(blk, tlv::FinalBlockId, m_finalBlockId);
146 }
147
148 // FreshnessPeriod
149 if (m_freshnessPeriod >= time::milliseconds::zero())
150 {
151 totalLength += prependNonNegativeIntegerBlock(blk, tlv::FreshnessPeriod,
152 m_freshnessPeriod.count());
153 }
154
155 // ContentType
156 if (m_type != TYPE_DEFAULT)
157 {
158 totalLength += prependNonNegativeIntegerBlock(blk, tlv::ContentType, m_type);
159 }
160
161 totalLength += blk.prependVarNumber(totalLength);
162 totalLength += blk.prependVarNumber(tlv::MetaInfo);
163 return totalLength;
164}
165
166template size_t
167MetaInfo::wireEncode<true>(EncodingImpl<true>& block) const;
168
169template size_t
170MetaInfo::wireEncode<false>(EncodingImpl<false>& block) const;
171
172const Block&
173MetaInfo::wireEncode() const
174{
175 if (m_wire.hasWire())
176 return m_wire;
177
178 EncodingEstimator estimator;
179 size_t estimatedSize = wireEncode(estimator);
180
181 EncodingBuffer buffer(estimatedSize, 0);
182 wireEncode(buffer);
183
184 m_wire = buffer.block();
185 return m_wire;
186}
187
188void
189MetaInfo::wireDecode(const Block& wire)
190{
191 m_wire = wire;
192 m_wire.parse();
193
194 // MetaInfo ::= META-INFO-TYPE TLV-LENGTH
195 // ContentType?
196 // FreshnessPeriod?
Shock Jiangca7ea702014-10-02 11:23:25 -0700197 // FinalBlockId?
198 // AppMetaInfo*
199
200
201 Block::element_const_iterator val = m_wire.elements_begin();
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700202
203 // ContentType
Shock Jiangca7ea702014-10-02 11:23:25 -0700204 if (val != m_wire.elements_end() && val->type() == tlv::ContentType) {
205 m_type = readNonNegativeInteger(*val);
206 ++val;
207 }
208 else {
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700209 m_type = TYPE_DEFAULT;
Shock Jiangca7ea702014-10-02 11:23:25 -0700210 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700211
212 // FreshnessPeriod
Shock Jiangca7ea702014-10-02 11:23:25 -0700213 if (val != m_wire.elements_end() && val->type() == tlv::FreshnessPeriod) {
214 m_freshnessPeriod = time::milliseconds(readNonNegativeInteger(*val));
215 ++val;
216 }
217 else {
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700218 m_freshnessPeriod = time::milliseconds::min();
Shock Jiangca7ea702014-10-02 11:23:25 -0700219 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700220
221 // FinalBlockId
Shock Jiangca7ea702014-10-02 11:23:25 -0700222 if (val != m_wire.elements_end() && val->type() == tlv::FinalBlockId) {
223 m_finalBlockId = val->blockFromValue();
224 if (m_finalBlockId.type() != tlv::NameComponent)
225 {
226 /// @todo May or may not throw exception later...
227 m_finalBlockId.reset();
228 }
229 ++val;
230 }
231 else {
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700232 m_finalBlockId.reset();
Shock Jiangca7ea702014-10-02 11:23:25 -0700233 }
234
235 // AppMetaInfo (if any)
236 for (; val != m_wire.elements().end(); ++val) {
237 m_appMetaInfo.push_back(*val);
238 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700239}
240
241std::ostream&
242operator<<(std::ostream& os, const MetaInfo& info)
243{
244 // ContentType
245 os << "ContentType: " << info.getType();
246
247 // FreshnessPeriod
248 if (info.getFreshnessPeriod() >= time::milliseconds::zero()) {
249 os << ", FreshnessPeriod: " << info.getFreshnessPeriod();
250 }
251
Shock Jiangca7ea702014-10-02 11:23:25 -0700252 // FinalBlockId
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700253 if (!info.getFinalBlockId().empty()) {
254 os << ", FinalBlockId: ";
255 info.getFinalBlockId().toUri(os);
256 }
Shock Jiangca7ea702014-10-02 11:23:25 -0700257
258 // App-defined MetaInfo items
259 for (std::list<Block>::const_iterator iter = info.getAppMetaInfo().begin();
260 iter != info.getAppMetaInfo().end(); ++iter) {
261 os << ", AppMetaInfoTlvType: " << iter->type();
262 }
263
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700264 return os;
265}
266
267} // namespace ndn