blob: e19c11db34267b6d204a0d59a90d86e496b6498a [file] [log] [blame]
Alexander Afanasyev01065fb2014-10-02 13:01:46 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi51742322017-08-13 17:04:52 +00002/*
Eric Newberryb555b002017-05-17 00:30:44 -07003 * Copyright (c) 2013-2017 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"
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070025
26namespace ndn {
27
Shock Jiangca7ea702014-10-02 11:23:25 -070028BOOST_CONCEPT_ASSERT((boost::EqualityComparable<MetaInfo>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070029BOOST_CONCEPT_ASSERT((WireEncodable<MetaInfo>));
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070030BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<MetaInfo>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070031BOOST_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)
Eric Newberryb555b002017-05-17 00:30:44 -070037 , m_freshnessPeriod(DEFAULT_FRESHNESS_PERIOD)
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070038{
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&
Eric Newberryb555b002017-05-17 00:30:44 -070055MetaInfo::setFreshnessPeriod(time::milliseconds freshnessPeriod)
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070056{
Eric Newberryb555b002017-05-17 00:30:44 -070057 if (freshnessPeriod < time::milliseconds::zero()) {
58 BOOST_THROW_EXCEPTION(std::invalid_argument("FreshnessPeriod must be >= 0"));
59 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070060 m_wire.reset();
61 m_freshnessPeriod = freshnessPeriod;
62 return *this;
63}
64
65MetaInfo&
66MetaInfo::setFinalBlockId(const name::Component& finalBlockId)
67{
68 m_wire.reset();
69 m_finalBlockId = finalBlockId;
70 return *this;
71}
72
Shock Jiangca7ea702014-10-02 11:23:25 -070073const std::list<Block>&
74MetaInfo::getAppMetaInfo() const
75{
76 return m_appMetaInfo;
77}
78
79MetaInfo&
80MetaInfo::setAppMetaInfo(const std::list<Block>& info)
81{
82 for (std::list<Block>::const_iterator i = info.begin(); i != info.end(); ++i) {
83 if (!(128 <= i->type() && i->type() <= 252))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -070084 BOOST_THROW_EXCEPTION(Error("AppMetaInfo block has type outside the application range "
85 "[128, 252]"));
Shock Jiangca7ea702014-10-02 11:23:25 -070086 }
87
88 m_wire.reset();
89 m_appMetaInfo = info;
90 return *this;
91}
92
93MetaInfo&
94MetaInfo::addAppMetaInfo(const Block& block)
95{
96 if (!(128 <= block.type() && block.type() <= 252))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -070097 BOOST_THROW_EXCEPTION(Error("AppMetaInfo block has type outside the application range "
98 "[128, 252]"));
Shock Jiangca7ea702014-10-02 11:23:25 -070099
100 m_wire.reset();
101 m_appMetaInfo.push_back(block);
102 return *this;
103}
104
105bool
106MetaInfo::removeAppMetaInfo(uint32_t tlvType)
107{
108 for (std::list<Block>::iterator iter = m_appMetaInfo.begin();
109 iter != m_appMetaInfo.end(); ++iter) {
110 if (iter->type() == tlvType) {
111 m_wire.reset();
112 m_appMetaInfo.erase(iter);
113 return true;
114 }
115 }
116 return false;
117}
118
119const Block*
120MetaInfo::findAppMetaInfo(uint32_t tlvType) const
121{
122 for (std::list<Block>::const_iterator iter = m_appMetaInfo.begin();
123 iter != m_appMetaInfo.end(); ++iter) {
124 if (iter->type() == tlvType) {
125 return &*iter;
126 }
127 }
128 return 0;
129}
130
Alexander Afanasyev74633892015-02-08 18:08:46 -0800131template<encoding::Tag TAG>
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700132size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800133MetaInfo::wireEncode(EncodingImpl<TAG>& encoder) const
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700134{
135 // MetaInfo ::= META-INFO-TYPE TLV-LENGTH
136 // ContentType?
137 // FreshnessPeriod?
138 // FinalBlockId?
Shock Jiangca7ea702014-10-02 11:23:25 -0700139 // AppMetaInfo*
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700140
141 size_t totalLength = 0;
142
Shock Jiangca7ea702014-10-02 11:23:25 -0700143 for (std::list<Block>::const_reverse_iterator appMetaInfoItem = m_appMetaInfo.rbegin();
144 appMetaInfoItem != m_appMetaInfo.rend(); ++appMetaInfoItem) {
Alexander Afanasyev74633892015-02-08 18:08:46 -0800145 totalLength += encoder.prependBlock(*appMetaInfoItem);
Shock Jiangca7ea702014-10-02 11:23:25 -0700146 }
147
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700148 // FinalBlockId
Eric Newberryb555b002017-05-17 00:30:44 -0700149 if (!m_finalBlockId.empty()) {
150 totalLength += prependNestedBlock(encoder, tlv::FinalBlockId, m_finalBlockId);
151 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700152
153 // FreshnessPeriod
Eric Newberryb555b002017-05-17 00:30:44 -0700154 if (m_freshnessPeriod != DEFAULT_FRESHNESS_PERIOD) {
Davide Pesavento88a0d812017-08-19 21:31:42 -0400155 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::FreshnessPeriod, m_freshnessPeriod.count());
Eric Newberryb555b002017-05-17 00:30:44 -0700156 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700157
158 // ContentType
Eric Newberryb555b002017-05-17 00:30:44 -0700159 if (m_type != tlv::ContentType_Blob) {
160 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::ContentType, m_type);
161 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700162
Alexander Afanasyev74633892015-02-08 18:08:46 -0800163 totalLength += encoder.prependVarNumber(totalLength);
164 totalLength += encoder.prependVarNumber(tlv::MetaInfo);
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700165 return totalLength;
166}
167
Davide Pesavento88a0d812017-08-19 21:31:42 -0400168NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(MetaInfo);
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700169
170const Block&
171MetaInfo::wireEncode() const
172{
173 if (m_wire.hasWire())
174 return m_wire;
175
176 EncodingEstimator estimator;
177 size_t estimatedSize = wireEncode(estimator);
178
179 EncodingBuffer buffer(estimatedSize, 0);
180 wireEncode(buffer);
181
182 m_wire = buffer.block();
183 return m_wire;
184}
185
186void
187MetaInfo::wireDecode(const Block& wire)
188{
189 m_wire = wire;
190 m_wire.parse();
191
192 // MetaInfo ::= META-INFO-TYPE TLV-LENGTH
193 // ContentType?
194 // FreshnessPeriod?
Shock Jiangca7ea702014-10-02 11:23:25 -0700195 // FinalBlockId?
196 // AppMetaInfo*
197
198
199 Block::element_const_iterator val = m_wire.elements_begin();
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700200
201 // ContentType
Shock Jiangca7ea702014-10-02 11:23:25 -0700202 if (val != m_wire.elements_end() && val->type() == tlv::ContentType) {
Junxiao Shi51742322017-08-13 17:04:52 +0000203 m_type = readNonNegativeIntegerAs<uint32_t>(*val);
Shock Jiangca7ea702014-10-02 11:23:25 -0700204 ++val;
205 }
206 else {
Junxiao Shia464b922014-11-12 21:13:06 -0700207 m_type = tlv::ContentType_Blob;
Shock Jiangca7ea702014-10-02 11:23:25 -0700208 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700209
210 // FreshnessPeriod
Shock Jiangca7ea702014-10-02 11:23:25 -0700211 if (val != m_wire.elements_end() && val->type() == tlv::FreshnessPeriod) {
212 m_freshnessPeriod = time::milliseconds(readNonNegativeInteger(*val));
213 ++val;
214 }
215 else {
Eric Newberryb555b002017-05-17 00:30:44 -0700216 m_freshnessPeriod = DEFAULT_FRESHNESS_PERIOD;
Shock Jiangca7ea702014-10-02 11:23:25 -0700217 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700218
219 // FinalBlockId
Shock Jiangca7ea702014-10-02 11:23:25 -0700220 if (val != m_wire.elements_end() && val->type() == tlv::FinalBlockId) {
221 m_finalBlockId = val->blockFromValue();
222 if (m_finalBlockId.type() != tlv::NameComponent)
223 {
224 /// @todo May or may not throw exception later...
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000225 m_finalBlockId = name::Component();
Shock Jiangca7ea702014-10-02 11:23:25 -0700226 }
227 ++val;
228 }
229 else {
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000230 m_finalBlockId = name::Component();
Shock Jiangca7ea702014-10-02 11:23:25 -0700231 }
232
233 // AppMetaInfo (if any)
234 for (; val != m_wire.elements().end(); ++val) {
235 m_appMetaInfo.push_back(*val);
236 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700237}
238
239std::ostream&
240operator<<(std::ostream& os, const MetaInfo& info)
241{
242 // ContentType
243 os << "ContentType: " << info.getType();
244
245 // FreshnessPeriod
Eric Newberryb555b002017-05-17 00:30:44 -0700246 if (info.getFreshnessPeriod() > time::milliseconds::zero()) {
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700247 os << ", FreshnessPeriod: " << info.getFreshnessPeriod();
248 }
249
Shock Jiangca7ea702014-10-02 11:23:25 -0700250 // FinalBlockId
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700251 if (!info.getFinalBlockId().empty()) {
252 os << ", FinalBlockId: ";
253 info.getFinalBlockId().toUri(os);
254 }
Shock Jiangca7ea702014-10-02 11:23:25 -0700255
256 // App-defined MetaInfo items
257 for (std::list<Block>::const_iterator iter = info.getAppMetaInfo().begin();
258 iter != info.getAppMetaInfo().end(); ++iter) {
259 os << ", AppMetaInfoTlvType: " << iter->type();
260 }
261
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700262 return os;
263}
264
265} // namespace ndn