blob: 1ed98cf6011493fb6244cbcab079147b43038949 [file] [log] [blame]
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Steve DiBenedetto6d792d72014-03-15 19:01:36 -06002/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060011 */
12
13#ifndef NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP
14#define NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP
15
16#include "../encoding/block.hpp"
17#include "../encoding/encoding-buffer.hpp"
18#include "../encoding/tlv-nfd.hpp"
19#include "../name.hpp"
20
21namespace ndn {
22namespace nfd {
23
24// NextHopRecord := NEXT-HOP-RECORD TLV-LENGTH
25// FaceId
26// Cost
27
28class NextHopRecord
29{
30public:
31 class Error : public Tlv::Error
32 {
33 public:
Alexander Afanasyev1c5a1a92014-03-21 13:32:36 -070034 Error(const std::string& what) : Tlv::Error(what) {}
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060035 };
36
37 NextHopRecord()
38 : m_faceId(std::numeric_limits<uint64_t>::max())
39 , m_cost(0)
40 {
41 }
42
Alexander Afanasyev44b438a2014-03-19 12:51:49 -070043 explicit
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060044 NextHopRecord(const Block& block)
45 {
46 wireDecode(block);
47 }
48
49 uint64_t
50 getFaceId() const
51 {
52 return m_faceId;
53 }
54
55 NextHopRecord&
56 setFaceId(uint64_t faceId)
57 {
58 m_faceId = faceId;
59 m_wire.reset();
60 return *this;
61 }
62
63 uint64_t
64 getCost() const
65 {
66 return m_cost;
67 }
68
69 NextHopRecord&
70 setCost(uint64_t cost)
71 {
72 m_cost = cost;
73 m_wire.reset();
74 return *this;
75 }
76
77 template<bool T>
78 size_t
79 wireEncode(EncodingImpl<T>& block) const
80 {
81 size_t totalLength = 0;
82 totalLength += prependNonNegativeIntegerBlock(block,
83 ndn::tlv::nfd::Cost,
84 m_cost);
85
86 totalLength += prependNonNegativeIntegerBlock(block,
87 ndn::tlv::nfd::FaceId,
88 m_faceId);
89
90 totalLength += block.prependVarNumber(totalLength);
91 totalLength += block.prependVarNumber(ndn::tlv::nfd::NextHopRecord);
92 return totalLength;
93 }
94
95 const Block&
96 wireEncode() const
97 {
98 if (m_wire.hasWire())
99 {
100 return m_wire;
101 }
102
103 EncodingEstimator estimator;
104 size_t estimatedSize = wireEncode(estimator);
105
106 EncodingBuffer buffer(estimatedSize, 0);
107 wireEncode(buffer);
108
109 m_wire = buffer.block();
110 return m_wire;
111 }
112
113 void
114 wireDecode(const Block& wire)
115 {
116 m_faceId = std::numeric_limits<uint64_t>::max();
117 m_cost = 0;
118
119 m_wire = wire;
120
121 if (m_wire.type() != tlv::nfd::NextHopRecord)
122 {
123 std::stringstream error;
124 error << "Requested decoding of NextHopRecord, but Block is of a different type: #"
125 << m_wire.type();
126 throw Error(error.str());
127 }
128 m_wire.parse();
129
130 Block::element_const_iterator val = m_wire.elements_begin();
131 if (val == m_wire.elements_end())
132 {
133 throw Error("Unexpected end of NextHopRecord");
134 }
135 else if (val->type() != tlv::nfd::FaceId)
136 {
137 std::stringstream error;
138 error << "Expected FaceId, but Block is of a different type: #"
139 << val->type();
140 throw Error(error.str());
141 }
142 m_faceId = readNonNegativeInteger(*val);
143 ++val;
144
145 if (val == m_wire.elements_end())
146 {
147 throw Error("Unexpected end of NextHopRecord");
148 }
149 else if (val->type() != tlv::nfd::Cost)
150 {
151 std::stringstream error;
152 error << "Expected Cost, but Block is of a different type: #"
Alexander Afanasyev1c5a1a92014-03-21 13:32:36 -0700153 << m_wire.type();
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600154 throw Error(error.str());
155 }
156 m_cost = readNonNegativeInteger(*val);
157 }
158
159
160private:
161 uint64_t m_faceId;
162 uint64_t m_cost;
163
164 mutable Block m_wire;
165};
166
167
168// FibEntry := FIB-ENTRY-TYPE TLV-LENGTH
169// Name
170// NextHopRecord*
171
172class FibEntry
173{
174public:
175 class Error : public Tlv::Error
176 {
177 public:
178 Error(const std::string& what) : Tlv::Error(what)
179 {
180 }
181 };
182
183 FibEntry()
184 {
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700185 }
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600186
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700187 explicit
188 FibEntry(const Block& block)
189 {
190 wireDecode(block);
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600191 }
192
193 const Name&
194 getPrefix() const
195 {
196 return m_prefix;
197 }
198
199 FibEntry&
200 setPrefix(const Name& prefix)
201 {
202 m_prefix = prefix;
203 m_wire.reset();
204 return *this;
205 }
206
207 const std::list<NextHopRecord>&
208 getNextHopRecords() const
209 {
210 return m_nextHopRecords;
211 }
212
213 FibEntry&
214 addNextHopRecord(const NextHopRecord& nextHopRecord)
215 {
216 m_nextHopRecords.push_back(nextHopRecord);
217 m_wire.reset();
218 return *this;
219 }
220
221 template<typename T>
222 FibEntry&
223 setNextHopRecords(const T& begin, const T& end)
224 {
225 m_nextHopRecords.clear();
226 m_nextHopRecords.assign(begin, end);
227 m_wire.reset();
228 return *this;
229 }
230
231 template<bool T>
232 size_t
233 wireEncode(EncodingImpl<T>& block) const
234 {
235 size_t totalLength = 0;
236
Alexander Afanasyev1c5a1a92014-03-21 13:32:36 -0700237 for (std::list<NextHopRecord>::const_reverse_iterator i = m_nextHopRecords.rbegin();
238 i != m_nextHopRecords.rend();
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600239 ++i)
240 {
241 totalLength += i->wireEncode(block);
242 }
243
244 totalLength += m_prefix.wireEncode(block);
245 totalLength += block.prependVarNumber(totalLength);
246 totalLength += block.prependVarNumber(tlv::nfd::FibEntry);
247
248 return totalLength;
249 }
250
251 const Block&
252 wireEncode() const
253 {
254 if (m_wire.hasWire())
255 {
256 return m_wire;
257 }
258
259 EncodingEstimator estimator;
260 size_t estimatedSize = wireEncode(estimator);
261
262 EncodingBuffer buffer(estimatedSize, 0);
263 wireEncode(buffer);
264
265 m_wire = buffer.block();
266
267 return m_wire;
268 }
269
270 void
271 wireDecode(const Block& wire)
272 {
273 m_prefix.clear();
274 m_nextHopRecords.clear();
275
276 m_wire = wire;
277
278 if (m_wire.type() != tlv::nfd::FibEntry)
279 {
280 std::stringstream error;
281 error << "Requested decoding of FibEntry, but Block is of a different type: #"
282 << m_wire.type();
283 throw Error(error.str());
284 }
285
286 m_wire.parse();
287
288 Block::element_const_iterator val = m_wire.elements_begin();
289 if (val == m_wire.elements_end())
290 {
291 throw Error("Unexpected end of FibEntry");
292 }
293 else if (val->type() != Tlv::Name)
294 {
295 std::stringstream error;
296 error << "Expected Name, but Block is of a different type: #"
297 << val->type();
298 throw Error(error.str());
299 }
300 m_prefix.wireDecode(*val);
301 ++val;
302
303 for (; val != m_wire.elements_end(); ++val)
304 {
305 if (val->type() != tlv::nfd::NextHopRecord)
306 {
307 std::stringstream error;
308 error << "Expected NextHopRecords, but Block is of a different type: #"
309 << val->type();
310 throw Error(error.str());
311 }
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700312 m_nextHopRecords.push_back(NextHopRecord(*val));
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600313 }
314 }
315
316private:
317 Name m_prefix;
318 std::list<NextHopRecord> m_nextHopRecords;
319
320 mutable Block m_wire;
321};
322
323} // namespace nfd
324} // namespace ndn
325
326#endif // NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP