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