blob: f68ca262a5892d9dc2a7ebd18cb3f654a6fef672 [file] [log] [blame]
Junxiao Shi70911652014-08-12 10:14:24 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Yanbiao Licbdacb22016-08-02 16:02:35 +08003 * Copyright (c) 2013-2016 Regents of the University of California.
Junxiao Shi70911652014-08-12 10:14:24 -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 "nfd-control-parameters.hpp"
Junxiao Shi65f1a712014-11-20 14:59:36 -070023#include "encoding/tlv-nfd.hpp"
24#include "encoding/block-helpers.hpp"
25#include "util/concepts.hpp"
Junxiao Shi70911652014-08-12 10:14:24 -070026
27namespace ndn {
28namespace nfd {
29
Junxiao Shi65f1a712014-11-20 14:59:36 -070030//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<ControlParameters>));
31BOOST_CONCEPT_ASSERT((WireEncodable<ControlParameters>));
32BOOST_CONCEPT_ASSERT((WireDecodable<ControlParameters>));
33static_assert(std::is_base_of<tlv::Error, ControlParameters::Error>::value,
34 "ControlParameters::Error must inherit from tlv::Error");
35
Junxiao Shi70911652014-08-12 10:14:24 -070036ControlParameters::ControlParameters()
37 : m_hasFields(CONTROL_PARAMETER_UBOUND)
38{
39}
40
41ControlParameters::ControlParameters(const Block& block)
42 : m_hasFields(CONTROL_PARAMETER_UBOUND)
43{
44 wireDecode(block);
45}
46
Alexander Afanasyev74633892015-02-08 18:08:46 -080047template<encoding::Tag TAG>
Junxiao Shi70911652014-08-12 10:14:24 -070048size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -080049ControlParameters::wireEncode(EncodingImpl<TAG>& encoder) const
Junxiao Shi70911652014-08-12 10:14:24 -070050{
51 size_t totalLength = 0;
52
Yukai Tud93c5fc2015-08-25 11:37:16 +080053 if (this->hasFacePersistency()) {
54 totalLength += prependNonNegativeIntegerBlock(encoder,
55 tlv::nfd::FacePersistency, m_facePersistency);
56 }
Junxiao Shi70911652014-08-12 10:14:24 -070057 if (this->hasExpirationPeriod()) {
58 totalLength += prependNonNegativeIntegerBlock(encoder,
59 tlv::nfd::ExpirationPeriod, m_expirationPeriod.count());
60 }
61 if (this->hasStrategy()) {
62 totalLength += prependNestedBlock(encoder, tlv::nfd::Strategy, m_strategy);
63 }
Eric Newberryda916d62016-08-11 23:04:34 -070064 if (this->hasMask()) {
65 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::Mask, m_mask);
66 }
Junxiao Shi70911652014-08-12 10:14:24 -070067 if (this->hasFlags()) {
68 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::Flags, m_flags);
69 }
70 if (this->hasCost()) {
71 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::Cost, m_cost);
72 }
73 if (this->hasOrigin()) {
74 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::Origin, m_origin);
75 }
76 if (this->hasLocalControlFeature()) {
77 totalLength += prependNonNegativeIntegerBlock(encoder,
78 tlv::nfd::LocalControlFeature, m_localControlFeature);
79 }
80 if (this->hasUri()) {
81 size_t valLength = encoder.prependByteArray(
82 reinterpret_cast<const uint8_t*>(m_uri.c_str()), m_uri.size());
83 totalLength += valLength;
84 totalLength += encoder.prependVarNumber(valLength);
85 totalLength += encoder.prependVarNumber(tlv::nfd::Uri);
86 }
87 if (this->hasFaceId()) {
88 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::FaceId, m_faceId);
89 }
90 if (this->hasName()) {
91 totalLength += m_name.wireEncode(encoder);
92 }
93
94 totalLength += encoder.prependVarNumber(totalLength);
95 totalLength += encoder.prependVarNumber(tlv::nfd::ControlParameters);
96 return totalLength;
97}
98
99template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800100ControlParameters::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>&) const;
Junxiao Shi70911652014-08-12 10:14:24 -0700101
102template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800103ControlParameters::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>&) const;
Junxiao Shi70911652014-08-12 10:14:24 -0700104
Yanbiao Li8ee37ed2015-05-19 12:44:04 -0700105Block
Junxiao Shi70911652014-08-12 10:14:24 -0700106ControlParameters::wireEncode() const
107{
108 if (m_wire.hasWire())
109 return m_wire;
110
111 EncodingEstimator estimator;
112 size_t estimatedSize = wireEncode(estimator);
113
114 EncodingBuffer buffer(estimatedSize, 0);
115 wireEncode(buffer);
116
117 m_wire = buffer.block();
118 return m_wire;
119}
120
121void
122ControlParameters::wireDecode(const Block& block)
123{
124 if (block.type() != tlv::nfd::ControlParameters) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700125 BOOST_THROW_EXCEPTION(Error("Expecting TLV-TYPE ControlParameters"));
Junxiao Shi70911652014-08-12 10:14:24 -0700126 }
127 m_wire = block;
128 m_wire.parse();
129 Block::element_const_iterator val;
130
131 val = m_wire.find(tlv::Name);
132 m_hasFields[CONTROL_PARAMETER_NAME] = val != m_wire.elements_end();
133 if (this->hasName()) {
134 m_name.wireDecode(*val);
135 }
136
137 val = m_wire.find(tlv::nfd::FaceId);
138 m_hasFields[CONTROL_PARAMETER_FACE_ID] = val != m_wire.elements_end();
139 if (this->hasFaceId()) {
140 m_faceId = static_cast<uint64_t>(readNonNegativeInteger(*val));
141 }
142
143 val = m_wire.find(tlv::nfd::Uri);
144 m_hasFields[CONTROL_PARAMETER_URI] = val != m_wire.elements_end();
145 if (this->hasUri()) {
146 m_uri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
147 }
148
149 val = m_wire.find(tlv::nfd::LocalControlFeature);
150 m_hasFields[CONTROL_PARAMETER_LOCAL_CONTROL_FEATURE] = val != m_wire.elements_end();
151 if (this->hasLocalControlFeature()) {
152 m_localControlFeature = static_cast<LocalControlFeature>(readNonNegativeInteger(*val));
153 }
154
155 val = m_wire.find(tlv::nfd::Origin);
156 m_hasFields[CONTROL_PARAMETER_ORIGIN] = val != m_wire.elements_end();
157 if (this->hasOrigin()) {
158 m_origin = static_cast<uint64_t>(readNonNegativeInteger(*val));
159 }
160
161 val = m_wire.find(tlv::nfd::Cost);
162 m_hasFields[CONTROL_PARAMETER_COST] = val != m_wire.elements_end();
163 if (this->hasCost()) {
164 m_cost = static_cast<uint64_t>(readNonNegativeInteger(*val));
165 }
166
167 val = m_wire.find(tlv::nfd::Flags);
168 m_hasFields[CONTROL_PARAMETER_FLAGS] = val != m_wire.elements_end();
169 if (this->hasFlags()) {
170 m_flags = static_cast<uint64_t>(readNonNegativeInteger(*val));
171 }
172
Eric Newberryda916d62016-08-11 23:04:34 -0700173 val = m_wire.find(tlv::nfd::Mask);
174 m_hasFields[CONTROL_PARAMETER_MASK] = val != m_wire.elements_end();
175 if (this->hasMask()) {
176 m_mask = static_cast<uint64_t>(readNonNegativeInteger(*val));
177 }
178
Junxiao Shi70911652014-08-12 10:14:24 -0700179 val = m_wire.find(tlv::nfd::Strategy);
180 m_hasFields[CONTROL_PARAMETER_STRATEGY] = val != m_wire.elements_end();
181 if (this->hasStrategy()) {
182 val->parse();
183 if (val->elements().empty()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700184 BOOST_THROW_EXCEPTION(Error("Expecting Strategy/Name"));
Junxiao Shi70911652014-08-12 10:14:24 -0700185 }
186 else {
187 m_strategy.wireDecode(*val->elements_begin());
188 }
189 }
190
191 val = m_wire.find(tlv::nfd::ExpirationPeriod);
192 m_hasFields[CONTROL_PARAMETER_EXPIRATION_PERIOD] = val != m_wire.elements_end();
193 if (this->hasExpirationPeriod()) {
194 m_expirationPeriod = time::milliseconds(readNonNegativeInteger(*val));
195 }
Yukai Tud93c5fc2015-08-25 11:37:16 +0800196
197 val = m_wire.find(tlv::nfd::FacePersistency);
198 m_hasFields[CONTROL_PARAMETER_FACE_PERSISTENCY] = val != m_wire.elements_end();
199 if (this->hasFacePersistency()) {
200 m_facePersistency = static_cast<FacePersistency>(readNonNegativeInteger(*val));
201 }
Junxiao Shi70911652014-08-12 10:14:24 -0700202}
203
Eric Newberryda916d62016-08-11 23:04:34 -0700204bool
205ControlParameters::hasFlagBit(size_t bit) const
206{
207 if (bit >= 64) {
208 BOOST_THROW_EXCEPTION(std::out_of_range("bit must be within range [0, 64)"));
209 }
210
211 if (!hasMask()) {
212 return false;
213 }
214
215 return getMask() & (1 << bit);
216}
217
218bool
219ControlParameters::getFlagBit(size_t bit) const
220{
221 if (bit >= 64) {
222 BOOST_THROW_EXCEPTION(std::out_of_range("bit must be within range [0, 64)"));
223 }
224
225 if (!hasFlags()) {
226 return false;
227 }
228
229 return getFlags() & (1 << bit);
230}
231
232ControlParameters&
233ControlParameters::setFlagBit(size_t bit, bool value, bool wantMask/* = true*/)
234{
235 if (bit >= 64) {
236 BOOST_THROW_EXCEPTION(std::out_of_range("bit must be within range [0, 64)"));
237 }
238
239 uint64_t flags = hasFlags() ? getFlags() : 0;
240 if (value) {
241 flags |= (1 << bit);
242 }
243 else {
244 flags &= ~(1 << bit);
245 }
246 setFlags(flags);
247
248 if (wantMask) {
249 uint64_t mask = hasMask() ? getMask() : 0;
250 mask |= (1 << bit);
251 setMask(mask);
252 }
253
254 return *this;
255}
256
257ControlParameters&
258ControlParameters::unsetFlagBit(size_t bit)
259{
260 if (bit >= 64) {
261 BOOST_THROW_EXCEPTION(std::out_of_range("bit must be within range [0, 64)"));
262 }
263
264 uint64_t mask = hasMask() ? getMask() : 0;
265 mask &= ~(1 << bit);
266 if (mask == 0) {
267 unsetMask();
268 unsetFlags();
269 }
270 else {
271 setMask(mask);
272 }
273
274 return *this;
275}
276
Junxiao Shi70911652014-08-12 10:14:24 -0700277std::ostream&
278operator<<(std::ostream& os, const ControlParameters& parameters)
279{
280 os << "ControlParameters(";
281
282 if (parameters.hasName()) {
283 os << "Name: " << parameters.getName() << ", ";
284 }
285
286 if (parameters.hasFaceId()) {
287 os << "FaceId: " << parameters.getFaceId() << ", ";
288 }
289
290 if (parameters.hasUri()) {
291 os << "Uri: " << parameters.getUri() << ", ";
292 }
293
294 if (parameters.hasLocalControlFeature()) {
295 os << "LocalControlFeature: " << parameters.getLocalControlFeature() << ", ";
296 }
297
298 if (parameters.hasOrigin()) {
299 os << "Origin: " << parameters.getOrigin() << ", ";
300 }
301
302 if (parameters.hasCost()) {
303 os << "Cost: " << parameters.getCost() << ", ";
304 }
305
306 if (parameters.hasFlags()) {
Eric Newberryda916d62016-08-11 23:04:34 -0700307 std::ios_base::fmtflags osFlags = os.flags();
308 os << "Flags: " << std::showbase << std::hex << parameters.getFlags() << ", ";
309 os.flags(osFlags);
310 }
311
312 if (parameters.hasMask()) {
313 std::ios_base::fmtflags osFlags = os.flags();
314 os << "Mask: " << std::showbase << std::hex << parameters.getMask() << ", ";
315 os.flags(osFlags);
Junxiao Shi70911652014-08-12 10:14:24 -0700316 }
317
318 if (parameters.hasStrategy()) {
319 os << "Strategy: " << parameters.getStrategy() << ", ";
320 }
321
322 if (parameters.hasExpirationPeriod()) {
323 os << "ExpirationPeriod: " << parameters.getExpirationPeriod() << ", ";
324 }
325
Yanbiao Licbdacb22016-08-02 16:02:35 +0800326 if (parameters.hasFacePersistency()) {
327 os << "FacePersistency: " << parameters.getFacePersistency() << ", ";
328 }
329
Junxiao Shi70911652014-08-12 10:14:24 -0700330 os << ")";
331 return os;
332}
333
334} // namespace nfd
335} // namespace ndn