blob: f46784c9af4c21936c47f44f2a0bbda90b57077e [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/*
Junxiao Shiebfe4a22018-04-01 23:53:40 +00003 * Copyright (c) 2013-2018 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&
Junxiao Shiebfe4a22018-04-01 23:53:40 +000066MetaInfo::setFinalBlock(optional<name::Component> finalBlockId)
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070067{
68 m_wire.reset();
Junxiao Shiebfe4a22018-04-01 23:53:40 +000069 m_finalBlockId = std::move(finalBlockId);
Alexander Afanasyev01065fb2014-10-02 13:01:46 -070070 return *this;
71}
72
Junxiao Shiebfe4a22018-04-01 23:53:40 +000073MetaInfo&
74MetaInfo::setFinalBlockId(const name::Component& finalBlockId)
75{
76 if (finalBlockId.isGeneric() && finalBlockId.empty()) {
77 return setFinalBlock(nullopt);
78 }
79 return setFinalBlock(finalBlockId);
80}
81
Shock Jiangca7ea702014-10-02 11:23:25 -070082const std::list<Block>&
83MetaInfo::getAppMetaInfo() const
84{
85 return m_appMetaInfo;
86}
87
88MetaInfo&
89MetaInfo::setAppMetaInfo(const std::list<Block>& info)
90{
Davide Pesaventodb4da5e2018-06-15 11:37:52 -040091 for (const auto& block : info) {
92 if (block.type() < 128 || block.type() > 252)
93 BOOST_THROW_EXCEPTION(Error("AppMetaInfo block has type outside the application range [128, 252]"));
Shock Jiangca7ea702014-10-02 11:23:25 -070094 }
95
96 m_wire.reset();
97 m_appMetaInfo = info;
98 return *this;
99}
100
101MetaInfo&
102MetaInfo::addAppMetaInfo(const Block& block)
103{
104 if (!(128 <= block.type() && block.type() <= 252))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700105 BOOST_THROW_EXCEPTION(Error("AppMetaInfo block has type outside the application range "
106 "[128, 252]"));
Shock Jiangca7ea702014-10-02 11:23:25 -0700107
108 m_wire.reset();
109 m_appMetaInfo.push_back(block);
110 return *this;
111}
112
113bool
114MetaInfo::removeAppMetaInfo(uint32_t tlvType)
115{
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400116 for (auto it = m_appMetaInfo.begin(); it != m_appMetaInfo.end(); ++it) {
117 if (it->type() == tlvType) {
Shock Jiangca7ea702014-10-02 11:23:25 -0700118 m_wire.reset();
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400119 m_appMetaInfo.erase(it);
Shock Jiangca7ea702014-10-02 11:23:25 -0700120 return true;
121 }
122 }
123 return false;
124}
125
126const Block*
127MetaInfo::findAppMetaInfo(uint32_t tlvType) const
128{
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400129 auto it = std::find_if(m_appMetaInfo.begin(), m_appMetaInfo.end(),
130 [=] (const Block& b) { return b.type() == tlvType; });
131 return it != m_appMetaInfo.end() ? &*it : nullptr;
Shock Jiangca7ea702014-10-02 11:23:25 -0700132}
133
Alexander Afanasyev74633892015-02-08 18:08:46 -0800134template<encoding::Tag TAG>
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700135size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800136MetaInfo::wireEncode(EncodingImpl<TAG>& encoder) const
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700137{
138 // MetaInfo ::= META-INFO-TYPE TLV-LENGTH
139 // ContentType?
140 // FreshnessPeriod?
141 // FinalBlockId?
Shock Jiangca7ea702014-10-02 11:23:25 -0700142 // AppMetaInfo*
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700143
144 size_t totalLength = 0;
145
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400146 for (auto it = m_appMetaInfo.rbegin(); it != m_appMetaInfo.rend(); ++it) {
147 totalLength += encoder.prependBlock(*it);
Shock Jiangca7ea702014-10-02 11:23:25 -0700148 }
149
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700150 // FinalBlockId
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000151 if (m_finalBlockId) {
152 totalLength += prependNestedBlock(encoder, tlv::FinalBlockId, *m_finalBlockId);
Eric Newberryb555b002017-05-17 00:30:44 -0700153 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700154
155 // FreshnessPeriod
Eric Newberryb555b002017-05-17 00:30:44 -0700156 if (m_freshnessPeriod != DEFAULT_FRESHNESS_PERIOD) {
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400157 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::FreshnessPeriod,
158 static_cast<uint64_t>(m_freshnessPeriod.count()));
Eric Newberryb555b002017-05-17 00:30:44 -0700159 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700160
161 // ContentType
Eric Newberryb555b002017-05-17 00:30:44 -0700162 if (m_type != tlv::ContentType_Blob) {
163 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::ContentType, m_type);
164 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700165
Alexander Afanasyev74633892015-02-08 18:08:46 -0800166 totalLength += encoder.prependVarNumber(totalLength);
167 totalLength += encoder.prependVarNumber(tlv::MetaInfo);
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700168 return totalLength;
169}
170
Davide Pesavento88a0d812017-08-19 21:31:42 -0400171NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(MetaInfo);
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
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400201 auto 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) {
Junxiao Shi51742322017-08-13 17:04:52 +0000205 m_type = readNonNegativeIntegerAs<uint32_t>(*val);
Shock Jiangca7ea702014-10-02 11:23:25 -0700206 ++val;
207 }
208 else {
Junxiao Shia464b922014-11-12 21:13:06 -0700209 m_type = tlv::ContentType_Blob;
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 {
Eric Newberryb555b002017-05-17 00:30:44 -0700218 m_freshnessPeriod = DEFAULT_FRESHNESS_PERIOD;
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) {
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000223 m_finalBlockId.emplace(val->blockFromValue());
Shock Jiangca7ea702014-10-02 11:23:25 -0700224 ++val;
225 }
226 else {
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000227 m_finalBlockId = nullopt;
Shock Jiangca7ea702014-10-02 11:23:25 -0700228 }
229
230 // AppMetaInfo (if any)
231 for (; val != m_wire.elements().end(); ++val) {
232 m_appMetaInfo.push_back(*val);
233 }
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700234}
235
236std::ostream&
237operator<<(std::ostream& os, const MetaInfo& info)
238{
239 // ContentType
240 os << "ContentType: " << info.getType();
241
242 // FreshnessPeriod
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400243 if (info.getFreshnessPeriod() > 0_ms) {
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700244 os << ", FreshnessPeriod: " << info.getFreshnessPeriod();
245 }
246
Shock Jiangca7ea702014-10-02 11:23:25 -0700247 // FinalBlockId
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000248 if (info.getFinalBlock()) {
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700249 os << ", FinalBlockId: ";
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000250 info.getFinalBlock()->toUri(os);
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700251 }
Shock Jiangca7ea702014-10-02 11:23:25 -0700252
253 // App-defined MetaInfo items
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400254 for (const auto& block : info.getAppMetaInfo()) {
255 os << ", AppMetaInfoTlvType: " << block.type();
Shock Jiangca7ea702014-10-02 11:23:25 -0700256 }
257
Alexander Afanasyev01065fb2014-10-02 13:01:46 -0700258 return os;
259}
260
261} // namespace ndn