blob: fb0732911055d2412efeb71fe22b59d663ac4f2b [file] [log] [blame]
Junxiao Shi65f1a712014-11-20 14:59:36 -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.
Junxiao Shi65f1a712014-11-20 14:59:36 -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-fib-entry.hpp"
23#include <sstream>
24#include "encoding/tlv-nfd.hpp"
25#include "encoding/block-helpers.hpp"
26#include "util/concepts.hpp"
27
28namespace ndn {
29namespace nfd {
30
31//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<NextHopRecord>));
32BOOST_CONCEPT_ASSERT((WireEncodable<NextHopRecord>));
33BOOST_CONCEPT_ASSERT((WireDecodable<NextHopRecord>));
34static_assert(std::is_base_of<tlv::Error, NextHopRecord::Error>::value,
35 "NextHopRecord::Error must inherit from tlv::Error");
36
37//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<FibEntry>));
38BOOST_CONCEPT_ASSERT((WireEncodable<FibEntry>));
39BOOST_CONCEPT_ASSERT((WireDecodable<FibEntry>));
40static_assert(std::is_base_of<tlv::Error, FibEntry::Error>::value,
41 "FibEntry::Error must inherit from tlv::Error");
42
43// NextHopRecord := NEXT-HOP-RECORD TLV-LENGTH
44// FaceId
45// Cost
46
47NextHopRecord::NextHopRecord()
48 : m_faceId(std::numeric_limits<uint64_t>::max())
49 , m_cost(0)
50{
51}
52
53NextHopRecord::NextHopRecord(const Block& block)
54{
55 this->wireDecode(block);
56}
57
58NextHopRecord&
59NextHopRecord::setFaceId(uint64_t faceId)
60{
61 m_faceId = faceId;
62 m_wire.reset();
63 return *this;
64}
65
66NextHopRecord&
67NextHopRecord::setCost(uint64_t cost)
68{
69 m_cost = cost;
70 m_wire.reset();
71 return *this;
72}
73
Alexander Afanasyev74633892015-02-08 18:08:46 -080074template<encoding::Tag TAG>
Junxiao Shi65f1a712014-11-20 14:59:36 -070075size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -080076NextHopRecord::wireEncode(EncodingImpl<TAG>& block) const
Junxiao Shi65f1a712014-11-20 14:59:36 -070077{
78 size_t totalLength = 0;
79 totalLength += prependNonNegativeIntegerBlock(block,
80 ndn::tlv::nfd::Cost,
81 m_cost);
82
83 totalLength += prependNonNegativeIntegerBlock(block,
84 ndn::tlv::nfd::FaceId,
85 m_faceId);
86
87 totalLength += block.prependVarNumber(totalLength);
88 totalLength += block.prependVarNumber(ndn::tlv::nfd::NextHopRecord);
89 return totalLength;
90}
91
92template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -080093NextHopRecord::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
Junxiao Shi65f1a712014-11-20 14:59:36 -070094
95template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -080096NextHopRecord::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
Junxiao Shi65f1a712014-11-20 14:59:36 -070097
98const Block&
99NextHopRecord::wireEncode() const
100{
101 if (m_wire.hasWire()) {
102 return m_wire;
103 }
104
105 EncodingEstimator estimator;
106 size_t estimatedSize = wireEncode(estimator);
107
108 EncodingBuffer buffer(estimatedSize, 0);
109 wireEncode(buffer);
110
111 m_wire = buffer.block();
112 return m_wire;
113}
114
115void
116NextHopRecord::wireDecode(const Block& wire)
117{
118 m_faceId = std::numeric_limits<uint64_t>::max();
119 m_cost = 0;
120
121 m_wire = wire;
122
123 if (m_wire.type() != tlv::nfd::NextHopRecord) {
124 std::stringstream error;
125 error << "Requested decoding of NextHopRecord, but Block is of a different type: #"
126 << m_wire.type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700127 BOOST_THROW_EXCEPTION(Error(error.str()));
Junxiao Shi65f1a712014-11-20 14:59:36 -0700128 }
129 m_wire.parse();
130
131 Block::element_const_iterator val = m_wire.elements_begin();
132 if (val == m_wire.elements_end()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700133 BOOST_THROW_EXCEPTION(Error("Unexpected end of NextHopRecord"));
Junxiao Shi65f1a712014-11-20 14:59:36 -0700134 }
135 else if (val->type() != tlv::nfd::FaceId) {
136 std::stringstream error;
137 error << "Expected FaceId, but Block is of a different type: #"
138 << val->type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700139 BOOST_THROW_EXCEPTION(Error(error.str()));
Junxiao Shi65f1a712014-11-20 14:59:36 -0700140 }
141 m_faceId = readNonNegativeInteger(*val);
142 ++val;
143
144 if (val == m_wire.elements_end()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700145 BOOST_THROW_EXCEPTION(Error("Unexpected end of NextHopRecord"));
Junxiao Shi65f1a712014-11-20 14:59:36 -0700146 }
147 else if (val->type() != tlv::nfd::Cost) {
148 std::stringstream error;
149 error << "Expected Cost, but Block is of a different type: #"
150 << m_wire.type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700151 BOOST_THROW_EXCEPTION(Error(error.str()));
Junxiao Shi65f1a712014-11-20 14:59:36 -0700152 }
153 m_cost = readNonNegativeInteger(*val);
154}
155
156// FibEntry := FIB-ENTRY-TYPE TLV-LENGTH
157// Name
158// NextHopRecord*
159
160FibEntry::FibEntry()
161{
162}
163
164FibEntry::FibEntry(const Block& block)
165{
166 this->wireDecode(block);
167}
168
169FibEntry&
170FibEntry::setPrefix(const Name& prefix)
171{
172 m_prefix = prefix;
173 m_wire.reset();
174 return *this;
175}
176
177FibEntry&
178FibEntry::addNextHopRecord(const NextHopRecord& nextHopRecord)
179{
180 m_nextHopRecords.push_back(nextHopRecord);
181 m_wire.reset();
182 return *this;
183}
184
Alexander Afanasyev74633892015-02-08 18:08:46 -0800185template<encoding::Tag TAG>
Junxiao Shi65f1a712014-11-20 14:59:36 -0700186size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800187FibEntry::wireEncode(EncodingImpl<TAG>& block) const
Junxiao Shi65f1a712014-11-20 14:59:36 -0700188{
189 size_t totalLength = 0;
190
191 for (auto i = m_nextHopRecords.rbegin(); i != m_nextHopRecords.rend(); ++i) {
192 totalLength += i->wireEncode(block);
193 }
194
195 totalLength += m_prefix.wireEncode(block);
196 totalLength += block.prependVarNumber(totalLength);
197 totalLength += block.prependVarNumber(tlv::nfd::FibEntry);
198
199 return totalLength;
200}
201
202template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800203FibEntry::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
Junxiao Shi65f1a712014-11-20 14:59:36 -0700204
205template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800206FibEntry::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
Junxiao Shi65f1a712014-11-20 14:59:36 -0700207
208const Block&
209FibEntry::wireEncode() const
210{
211 if (m_wire.hasWire()) {
212 return m_wire;
213 }
214
215 EncodingEstimator estimator;
216 size_t estimatedSize = wireEncode(estimator);
217
218 EncodingBuffer buffer(estimatedSize, 0);
219 wireEncode(buffer);
220
221 m_wire = buffer.block();
222
223 return m_wire;
224}
225
226void
227FibEntry::wireDecode(const Block& wire)
228{
229 m_prefix.clear();
230 m_nextHopRecords.clear();
231
232 m_wire = wire;
233
234 if (m_wire.type() != tlv::nfd::FibEntry) {
235 std::stringstream error;
236 error << "Requested decoding of FibEntry, but Block is of a different type: #"
237 << m_wire.type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700238 BOOST_THROW_EXCEPTION(Error(error.str()));
Junxiao Shi65f1a712014-11-20 14:59:36 -0700239 }
240
241 m_wire.parse();
242
243 Block::element_const_iterator val = m_wire.elements_begin();
244 if (val == m_wire.elements_end()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700245 BOOST_THROW_EXCEPTION(Error("Unexpected end of FibEntry"));
Junxiao Shi65f1a712014-11-20 14:59:36 -0700246 }
247 else if (val->type() != tlv::Name) {
248 std::stringstream error;
249 error << "Expected Name, but Block is of a different type: #"
250 << val->type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700251 BOOST_THROW_EXCEPTION(Error(error.str()));
Junxiao Shi65f1a712014-11-20 14:59:36 -0700252 }
253 m_prefix.wireDecode(*val);
254 ++val;
255
256 for (; val != m_wire.elements_end(); ++val) {
257 if (val->type() != tlv::nfd::NextHopRecord) {
258 std::stringstream error;
259 error << "Expected NextHopRecords, but Block is of a different type: #"
260 << val->type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700261 BOOST_THROW_EXCEPTION(Error(error.str()));
Junxiao Shi65f1a712014-11-20 14:59:36 -0700262 }
263 m_nextHopRecords.push_back(NextHopRecord(*val));
264 }
265}
266
267} // namespace nfd
268} // namespace ndn