blob: e447863b0a571380f995093cab3d202b924a54fd [file] [log] [blame]
Jiewen Tan7a56d1c2015-01-26 23:26:51 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
laqinfan35731852017-08-08 06:17:39 -05003 * Copyright (c) 2014-2018, The University of Memphis,
Jiewen Tan7a56d1c2015-01-26 23:26:51 -08004 * Regents of the University of California,
5 * Arizona Board of Regents.
6 *
7 * This file is part of NLSR (Named-data Link State Routing).
8 * See AUTHORS.md for complete list of NLSR authors and contributors.
9 *
10 * NLSR is free software: you can redistribute it and/or modify it under the terms
11 * of the GNU General Public License as published by the Free Software Foundation,
12 * either version 3 of the License, or (at your option) any later version.
13 *
14 * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 * PURPOSE. See the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
20 **/
21
22#include "lsdb-status.hpp"
23#include "tlv-nlsr.hpp"
24
25#include <ndn-cxx/util/concepts.hpp>
26#include <ndn-cxx/encoding/block-helpers.hpp>
27
28namespace nlsr {
laqinfan35731852017-08-08 06:17:39 -050029namespace tlv {
Jiewen Tan7a56d1c2015-01-26 23:26:51 -080030
31BOOST_CONCEPT_ASSERT((ndn::WireEncodable<LsdbStatus>));
32BOOST_CONCEPT_ASSERT((ndn::WireDecodable<LsdbStatus>));
33static_assert(std::is_base_of<ndn::tlv::Error, LsdbStatus::Error>::value,
34 "LsdbStatus::Error must inherit from tlv::Error");
35
36LsdbStatus::LsdbStatus()
37 : m_hasAdjacencyLsas(false)
38 , m_hasCoordinateLsas(false)
39 , m_hasNameLsas(false)
40{
41}
42
43LsdbStatus::LsdbStatus(const ndn::Block& block)
44{
45 wireDecode(block);
46}
47
laqinfan35731852017-08-08 06:17:39 -050048LsdbStatus&
49LsdbStatus::addAdjacencyLsa(const AdjacencyLsa& adjacencyLsa)
50{
51 m_adjacencyLsas.push_back(adjacencyLsa);
52 m_wire.reset();
53 m_hasAdjacencyLsas = true;
54 return *this;
55}
56
57LsdbStatus&
58LsdbStatus::clearAdjacencyLsas()
59{
60 m_adjacencyLsas.clear();
61 m_hasAdjacencyLsas = false;
62 return *this;
63}
64
65LsdbStatus&
66LsdbStatus::addCoordinateLsa(const CoordinateLsa& coordinateLsa)
67{
68 m_coordinateLsas.push_back(coordinateLsa);
69 m_wire.reset();
70 m_hasCoordinateLsas = true;
71 return *this;
72}
73
74LsdbStatus&
75LsdbStatus::clearCoordinateLsas()
76{
77 m_coordinateLsas.clear();
78 m_hasCoordinateLsas = false;
79 return *this;
80}
81
82LsdbStatus&
83LsdbStatus::addNameLsa(const NameLsa& nameLsa)
84{
85 m_nameLsas.push_back(nameLsa);
86 m_wire.reset();
87 m_hasNameLsas = true;
88 return *this;
89}
90
91LsdbStatus&
92LsdbStatus::clearNameLsas()
93{
94 m_nameLsas.clear();
95 m_hasNameLsas = false;
96 return *this;
97}
98
Alexander Afanasyevf9f39102015-12-01 17:43:40 -080099template<ndn::encoding::Tag TAG>
Jiewen Tan7a56d1c2015-01-26 23:26:51 -0800100size_t
Alexander Afanasyevf9f39102015-12-01 17:43:40 -0800101LsdbStatus::wireEncode(ndn::EncodingImpl<TAG>& block) const
Jiewen Tan7a56d1c2015-01-26 23:26:51 -0800102{
103 size_t totalLength = 0;
104
105 for (std::list<NameLsa>::const_reverse_iterator it = m_nameLsas.rbegin();
106 it != m_nameLsas.rend(); ++it) {
107 totalLength += it->wireEncode(block);
108 }
109
110 for (std::list<CoordinateLsa>::const_reverse_iterator it = m_coordinateLsas.rbegin();
111 it != m_coordinateLsas.rend(); ++it) {
112 totalLength += it->wireEncode(block);
113 }
114
115 for (std::list<AdjacencyLsa>::const_reverse_iterator it = m_adjacencyLsas.rbegin();
116 it != m_adjacencyLsas.rend(); ++it) {
117 totalLength += it->wireEncode(block);
118 }
119
120 totalLength += block.prependVarNumber(totalLength);
121 totalLength += block.prependVarNumber(ndn::tlv::nlsr::LsdbStatus);
122
123 return totalLength;
124}
125
laqinfan35731852017-08-08 06:17:39 -0500126NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(LsdbStatus);
127
Jiewen Tan7a56d1c2015-01-26 23:26:51 -0800128template size_t
Alexander Afanasyevf9f39102015-12-01 17:43:40 -0800129LsdbStatus::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>& block) const;
Jiewen Tan7a56d1c2015-01-26 23:26:51 -0800130
131template size_t
Alexander Afanasyevf9f39102015-12-01 17:43:40 -0800132LsdbStatus::wireEncode<ndn::encoding::EstimatorTag>(ndn::EncodingImpl<ndn::encoding::EstimatorTag>& block) const;
Jiewen Tan7a56d1c2015-01-26 23:26:51 -0800133
134const ndn::Block&
135LsdbStatus::wireEncode() const
136{
137 if (m_wire.hasWire()) {
138 return m_wire;
139 }
140
141 ndn::EncodingEstimator estimator;
142 size_t estimatedSize = wireEncode(estimator);
143
144 ndn::EncodingBuffer buffer(estimatedSize, 0);
145 wireEncode(buffer);
146
147 m_wire = buffer.block();
148
149 return m_wire;
150}
151
152void
153LsdbStatus::wireDecode(const ndn::Block& wire)
154{
155 m_adjacencyLsas.clear();
156 m_coordinateLsas.clear();
157 m_nameLsas.clear();
158
159 m_hasAdjacencyLsas = false;
160 m_hasCoordinateLsas = false;
161 m_hasNameLsas = false;
162
163 m_wire = wire;
164
165 if (m_wire.type() != ndn::tlv::nlsr::LsdbStatus) {
166 std::stringstream error;
167 error << "Expected LsdbStatus Block, but Block is of a different type: #"
168 << m_wire.type();
laqinfan35731852017-08-08 06:17:39 -0500169 BOOST_THROW_EXCEPTION(Error(error.str()));
Jiewen Tan7a56d1c2015-01-26 23:26:51 -0800170 }
171
172 m_wire.parse();
173
174 ndn::Block::element_const_iterator val = m_wire.elements_begin();
175
176 for (; val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::AdjacencyLsa; ++val) {
177 m_adjacencyLsas.push_back(AdjacencyLsa(*val));
178 m_hasAdjacencyLsas = true;
179 }
180
181 for (; val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::CoordinateLsa; ++val) {
182 m_coordinateLsas.push_back(CoordinateLsa(*val));
183 m_hasCoordinateLsas = true;
184 }
185
186 for (; val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::NameLsa; ++val) {
187 m_nameLsas.push_back(NameLsa(*val));
188 m_hasNameLsas = true;
189 }
190
191 if (val != m_wire.elements_end()) {
192 std::stringstream error;
193 error << "Expected the end of elements, but Block is of a different type: #"
194 << val->type();
laqinfan35731852017-08-08 06:17:39 -0500195 BOOST_THROW_EXCEPTION(Error(error.str()));
Jiewen Tan7a56d1c2015-01-26 23:26:51 -0800196 }
197}
198
199std::ostream&
200operator<<(std::ostream& os, const LsdbStatus& lsdbStatus)
201{
202 os << "LsdbStatus(";
203
204 bool isFirst = true;
205
206 for (const auto& adjacencyLsa : lsdbStatus.getAdjacencyLsas()) {
207 if (isFirst) {
208 isFirst = false;
209 }
210 else {
211 os << ", ";
212 }
213
214 os << adjacencyLsa;
215 }
216
217 for (const auto& coordinateLsa : lsdbStatus.getCoordinateLsas()) {
218 if (isFirst) {
219 isFirst = false;
220 }
221 else {
222 os << ", ";
223 }
224
225 os << coordinateLsa;
226 }
227
228 for (const auto& nameLsa : lsdbStatus.getNameLsas()) {
229 if (isFirst) {
230 isFirst = false;
231 }
232 else {
233 os << ", ";
234 }
235
236 os << nameLsa;
237 }
238
239 os << ")";
240
241 return os;
242}
243
244} // namespace tlv
245} // namespace nlsr