blob: 0f97568ff20f4f1cbdd4e82df19894a0a47b14d4 [file] [log] [blame]
akmhoque298385a2014-02-13 14:13:09 -06001#include<string>
2#include<iostream>
akmhoque2bb198e2014-02-28 11:46:27 -06003#include<sstream>
akmhoque298385a2014-02-13 14:13:09 -06004#include<algorithm>
5#include<cmath>
6#include<limits>
7
akmhoque2bb198e2014-02-28 11:46:27 -06008#include "nlsr.hpp"
akmhoque298385a2014-02-13 14:13:09 -06009#include "nlsr_lsa.hpp"
10#include "nlsr_npl.hpp"
11#include "nlsr_adjacent.hpp"
akmhoque2bb198e2014-02-28 11:46:27 -060012#include "utility/nlsr_tokenizer.hpp"
akmhoque05d5fcf2014-04-15 14:58:45 -050013#include "utility/nlsr_logger.hpp"
akmhoque2bb198e2014-02-28 11:46:27 -060014
akmhoque05d5fcf2014-04-15 14:58:45 -050015#define THIS_FILE "nlsr_lsa.cpp"
akmhoque298385a2014-02-13 14:13:09 -060016
akmhoque1fd8c1e2014-02-19 19:41:49 -060017namespace nlsr
akmhoque298385a2014-02-13 14:13:09 -060018{
akmhoque298385a2014-02-13 14:13:09 -060019
akmhoque5a44dd42014-03-12 18:11:32 -050020 using namespace std;
akmhoque298385a2014-02-13 14:13:09 -060021
akmhoque298385a2014-02-13 14:13:09 -060022
akmhoque5a44dd42014-03-12 18:11:32 -050023 string
akmhoque05d5fcf2014-04-15 14:58:45 -050024 NameLsa::getKey()
akmhoque5a44dd42014-03-12 18:11:32 -050025 {
26 string key;
akmhoque05d5fcf2014-04-15 14:58:45 -050027 key=m_origRouter + "/" + boost::lexical_cast<std::string>(1);
akmhoque5a44dd42014-03-12 18:11:32 -050028 return key;
29 }
30
31 NameLsa::NameLsa(string origR, uint8_t lst, uint32_t lsn, uint32_t lt, Npl npl)
32 {
akmhoque05d5fcf2014-04-15 14:58:45 -050033 m_origRouter=origR;
34 m_lsType=lst;
35 m_lsSeqNo=lsn;
36 m_lifeTime=lt;
akmhoque5a44dd42014-03-12 18:11:32 -050037 std::list<string> nl=npl.getNameList();
38 for( std::list<string>::iterator it=nl.begin(); it != nl.end(); it++)
akmhoque1fd8c1e2014-02-19 19:41:49 -060039 {
akmhoque05d5fcf2014-04-15 14:58:45 -050040 addName((*it));
akmhoque1fd8c1e2014-02-19 19:41:49 -060041 }
akmhoque5a44dd42014-03-12 18:11:32 -050042 }
akmhoque298385a2014-02-13 14:13:09 -060043
akmhoque5a44dd42014-03-12 18:11:32 -050044 string
akmhoque05d5fcf2014-04-15 14:58:45 -050045 NameLsa::getData()
akmhoque5a44dd42014-03-12 18:11:32 -050046 {
47 string nameLsaData;
akmhoque05d5fcf2014-04-15 14:58:45 -050048 nameLsaData=m_origRouter + "|" + boost::lexical_cast<std::string>(1) + "|"
49 + boost::lexical_cast<std::string>(m_lsSeqNo) + "|"
50 + boost::lexical_cast<std::string>(m_lifeTime);
akmhoque5a44dd42014-03-12 18:11:32 -050051 nameLsaData+="|";
akmhoque05d5fcf2014-04-15 14:58:45 -050052 nameLsaData+=boost::lexical_cast<std::string>(m_npl.getSize());
53 std::list<string> nl=m_npl.getNameList();
akmhoque5a44dd42014-03-12 18:11:32 -050054 for( std::list<string>::iterator it=nl.begin(); it != nl.end(); it++)
akmhoque1fd8c1e2014-02-19 19:41:49 -060055 {
akmhoque5a44dd42014-03-12 18:11:32 -050056 nameLsaData+="|";
57 nameLsaData+=(*it);
akmhoque1fd8c1e2014-02-19 19:41:49 -060058 }
akmhoque5a44dd42014-03-12 18:11:32 -050059 return nameLsaData+"|";
60 }
akmhoque1fd8c1e2014-02-19 19:41:49 -060061
akmhoque5a44dd42014-03-12 18:11:32 -050062 bool
akmhoque05d5fcf2014-04-15 14:58:45 -050063 NameLsa::initializeFromContent(string content)
akmhoque5a44dd42014-03-12 18:11:32 -050064 {
65 uint32_t numName=0;
66 nlsrTokenizer nt(content, "|");
akmhoque05d5fcf2014-04-15 14:58:45 -050067 m_origRouter=nt.getNextToken();
68 if(m_origRouter.empty())
akmhoque1fd8c1e2014-02-19 19:41:49 -060069 {
akmhoque5a44dd42014-03-12 18:11:32 -050070 return false;
akmhoque2bb198e2014-02-28 11:46:27 -060071 }
akmhoque5a44dd42014-03-12 18:11:32 -050072 try
akmhoque2bb198e2014-02-28 11:46:27 -060073 {
akmhoque05d5fcf2014-04-15 14:58:45 -050074 m_lsType=boost::lexical_cast<uint8_t>(nt.getNextToken());
75 m_lsSeqNo=boost::lexical_cast<uint32_t>(nt.getNextToken());
76 m_lifeTime=boost::lexical_cast<uint32_t>(nt.getNextToken());
akmhoque5a44dd42014-03-12 18:11:32 -050077 numName=boost::lexical_cast<uint32_t>(nt.getNextToken());
akmhoque1fd8c1e2014-02-19 19:41:49 -060078 }
akmhoque5a44dd42014-03-12 18:11:32 -050079 catch(std::exception &e)
akmhoque1fd8c1e2014-02-19 19:41:49 -060080 {
akmhoque5a44dd42014-03-12 18:11:32 -050081 return false;
akmhoque1fd8c1e2014-02-19 19:41:49 -060082 }
akmhoque5a44dd42014-03-12 18:11:32 -050083 for(int i=0; i<numName; i++)
akmhoque1fd8c1e2014-02-19 19:41:49 -060084 {
akmhoque5a44dd42014-03-12 18:11:32 -050085 string name=nt.getNextToken();
akmhoque05d5fcf2014-04-15 14:58:45 -050086 addName(name);
akmhoque1fd8c1e2014-02-19 19:41:49 -060087 }
akmhoque5a44dd42014-03-12 18:11:32 -050088 return true;
89 }
akmhoque05d5fcf2014-04-15 14:58:45 -050090
91 void
92 NameLsa::writeLog()
93 {
94 src::logger lg;
95 BOOST_LOG(lg)<<" "<<THIS_FILE<<" "<<__LINE__<<": "<<"Name-LSA";
96 BOOST_LOG(lg)<<" "<<THIS_FILE<<" "<<__LINE__<<": "<<" Origination Router: "
97 <<m_origRouter;
98 BOOST_LOG(lg)<<" "<<THIS_FILE<<" "<<__LINE__<<": "<<" LS Type: "<<m_lsType;
99 BOOST_LOG(lg)<<" "<<THIS_FILE<<" "<<__LINE__<<": "<<" LS Seq: "<<m_lsSeqNo;
100 BOOST_LOG(lg)<<" "<<THIS_FILE<<" "<<__LINE__<<": "<<" LS Lifetime: "<<m_lifeTime;
101 BOOST_LOG(lg)<<" "<<THIS_FILE<<" "<<__LINE__<<": "<<" LS Data: ";
102 int i=1;
103 std::list<string> nl=m_npl.getNameList();
104 for( std::list<string>::iterator it=nl.begin(); it != nl.end(); it++)
105 {
106 BOOST_LOG(lg)<<" "<<THIS_FILE<<" "<<__LINE__<<": "<<" Name "<<i<<": "<<(*it);
107 }
108 BOOST_LOG(lg)<<" "<<THIS_FILE<<" "<<__LINE__<<": "<<"name_lsa_end";
109 }
akmhoque298385a2014-02-13 14:13:09 -0600110
akmhoque5a44dd42014-03-12 18:11:32 -0500111 std::ostream&
112 operator<<(std::ostream& os, NameLsa& nLsa)
113 {
114 os<<"Name Lsa: "<<endl;
115 os<<" Origination Router: "<<nLsa.getOrigRouter()<<endl;
116 os<<" Ls Type: "<<(unsigned short)nLsa.getLsType()<<endl;
117 os<<" Ls Seq No: "<<(unsigned int)nLsa.getLsSeqNo()<<endl;
118 os<<" Ls Lifetime: "<<(unsigned int)nLsa.getLifeTime()<<endl;
119 os<<" Names: "<<endl;
120 int i=1;
121 std::list<string> nl=nLsa.getNpl().getNameList();
122 for( std::list<string>::iterator it=nl.begin(); it != nl.end(); it++)
akmhoque1fd8c1e2014-02-19 19:41:49 -0600123 {
akmhoque5a44dd42014-03-12 18:11:32 -0500124 os<<" Name "<<i<<": "<<(*it)<<endl;
akmhoque1fd8c1e2014-02-19 19:41:49 -0600125 }
akmhoque5a44dd42014-03-12 18:11:32 -0500126 return os;
127 }
akmhoque298385a2014-02-13 14:13:09 -0600128
akmhoque5a44dd42014-03-12 18:11:32 -0500129
130
131 CorLsa::CorLsa(string origR, uint8_t lst, uint32_t lsn, uint32_t lt
132 , double r, double theta)
133 {
akmhoque05d5fcf2014-04-15 14:58:45 -0500134 m_origRouter=origR;
135 m_lsType=lst;
136 m_lsSeqNo=lsn;
137 m_lifeTime=lt;
138 m_corRad=r;
139 m_corTheta=theta;
akmhoque5a44dd42014-03-12 18:11:32 -0500140 }
141
142 string
akmhoque05d5fcf2014-04-15 14:58:45 -0500143 CorLsa::getKey()
akmhoque5a44dd42014-03-12 18:11:32 -0500144 {
145 string key;
akmhoque05d5fcf2014-04-15 14:58:45 -0500146 key=m_origRouter + "/" + boost::lexical_cast<std::string>(3);
akmhoque5a44dd42014-03-12 18:11:32 -0500147 return key;
148 }
149
150 bool
akmhoque05d5fcf2014-04-15 14:58:45 -0500151 CorLsa::isEqual(CorLsa& clsa)
akmhoque5a44dd42014-03-12 18:11:32 -0500152 {
akmhoque05d5fcf2014-04-15 14:58:45 -0500153 return (std::abs(m_corRad - clsa.getCorRadius()) <
akmhoque5a44dd42014-03-12 18:11:32 -0500154 std::numeric_limits<double>::epsilon()) &&
akmhoque05d5fcf2014-04-15 14:58:45 -0500155 (std::abs(m_corTheta - clsa.getCorTheta()) <
akmhoque5a44dd42014-03-12 18:11:32 -0500156 std::numeric_limits<double>::epsilon());
157 }
158
159 string
akmhoque05d5fcf2014-04-15 14:58:45 -0500160 CorLsa::getData()
akmhoque5a44dd42014-03-12 18:11:32 -0500161 {
162 string corLsaData;
akmhoque05d5fcf2014-04-15 14:58:45 -0500163 corLsaData=m_origRouter + "|";
akmhoque5a44dd42014-03-12 18:11:32 -0500164 corLsaData+=(boost::lexical_cast<std::string>(3) + "|");
akmhoque05d5fcf2014-04-15 14:58:45 -0500165 corLsaData+=(boost::lexical_cast<std::string>(m_lsSeqNo) + "|");
166 corLsaData+=(boost::lexical_cast<std::string>(m_lifeTime) + "|");
167 corLsaData+=(boost::lexical_cast<std::string>(m_corRad) + "|");
168 corLsaData+=(boost::lexical_cast<std::string>(m_corTheta) + "|");
akmhoque5a44dd42014-03-12 18:11:32 -0500169 return corLsaData;
170 }
171
172 bool
akmhoque05d5fcf2014-04-15 14:58:45 -0500173 CorLsa::initializeFromContent(string content)
akmhoque5a44dd42014-03-12 18:11:32 -0500174 {
175 nlsrTokenizer nt(content, "|");
akmhoque05d5fcf2014-04-15 14:58:45 -0500176 m_origRouter=nt.getNextToken();
177 if(m_origRouter.empty())
akmhoque1fd8c1e2014-02-19 19:41:49 -0600178 {
akmhoque5a44dd42014-03-12 18:11:32 -0500179 return false;
akmhoque1fd8c1e2014-02-19 19:41:49 -0600180 }
akmhoque5a44dd42014-03-12 18:11:32 -0500181 try
akmhoque1fd8c1e2014-02-19 19:41:49 -0600182 {
akmhoque05d5fcf2014-04-15 14:58:45 -0500183 m_lsType=boost::lexical_cast<uint8_t>(nt.getNextToken());
184 m_lsSeqNo=boost::lexical_cast<uint32_t>(nt.getNextToken());
185 m_lifeTime=boost::lexical_cast<uint32_t>(nt.getNextToken());
186 m_corRad=boost::lexical_cast<double>(nt.getNextToken());
187 m_corTheta=boost::lexical_cast<double>(nt.getNextToken());
akmhoque1fd8c1e2014-02-19 19:41:49 -0600188 }
akmhoque5a44dd42014-03-12 18:11:32 -0500189 catch(std::exception &e)
akmhoque2bb198e2014-02-28 11:46:27 -0600190 {
akmhoque5a44dd42014-03-12 18:11:32 -0500191 return false;
akmhoque2bb198e2014-02-28 11:46:27 -0600192 }
akmhoque5a44dd42014-03-12 18:11:32 -0500193 return true;
194 }
akmhoque2bb198e2014-02-28 11:46:27 -0600195
akmhoque5a44dd42014-03-12 18:11:32 -0500196 std::ostream&
197 operator<<(std::ostream& os, CorLsa& cLsa)
198 {
199 os<<"Cor Lsa: "<<endl;
200 os<<" Origination Router: "<<cLsa.getOrigRouter()<<endl;
201 os<<" Ls Type: "<<(unsigned short)cLsa.getLsType()<<endl;
202 os<<" Ls Seq No: "<<(unsigned int)cLsa.getLsSeqNo()<<endl;
203 os<<" Ls Lifetime: "<<(unsigned int)cLsa.getLifeTime()<<endl;
204 os<<" Hyperbolic Radius: "<<cLsa.getCorRadius()<<endl;
205 os<<" Hyperbolic Theta: "<<cLsa.getCorTheta()<<endl;
206 return os;
207 }
208
209
210 AdjLsa::AdjLsa(string origR, uint8_t lst, uint32_t lsn, uint32_t lt,
211 uint32_t nl ,Adl padl)
212 {
akmhoque05d5fcf2014-04-15 14:58:45 -0500213 m_origRouter=origR;
214 m_lsType=lst;
215 m_lsSeqNo=lsn;
216 m_lifeTime=lt;
217 m_noLink=nl;
akmhoque5a44dd42014-03-12 18:11:32 -0500218 std::list<Adjacent> al=padl.getAdjList();
219 for( std::list<Adjacent>::iterator it=al.begin(); it != al.end(); it++)
akmhoque1fd8c1e2014-02-19 19:41:49 -0600220 {
akmhoque5a44dd42014-03-12 18:11:32 -0500221 if((*it).getStatus()==1)
222 {
akmhoque05d5fcf2014-04-15 14:58:45 -0500223 addAdjacent((*it));
akmhoque5a44dd42014-03-12 18:11:32 -0500224 }
akmhoque1fd8c1e2014-02-19 19:41:49 -0600225 }
akmhoque5a44dd42014-03-12 18:11:32 -0500226 }
227
228 string
akmhoque05d5fcf2014-04-15 14:58:45 -0500229 AdjLsa::getKey()
akmhoque5a44dd42014-03-12 18:11:32 -0500230 {
231 string key;
akmhoque05d5fcf2014-04-15 14:58:45 -0500232 key=m_origRouter + "/" + boost::lexical_cast<std::string>(2);
akmhoque5a44dd42014-03-12 18:11:32 -0500233 return key;
234 }
235
236 bool
akmhoque05d5fcf2014-04-15 14:58:45 -0500237 AdjLsa::isEqual(AdjLsa& alsa)
akmhoque5a44dd42014-03-12 18:11:32 -0500238 {
akmhoque05d5fcf2014-04-15 14:58:45 -0500239 return m_adl.isEqual(alsa.getAdl());
akmhoque5a44dd42014-03-12 18:11:32 -0500240 }
akmhoque298385a2014-02-13 14:13:09 -0600241
242
akmhoque5a44dd42014-03-12 18:11:32 -0500243 string
akmhoque05d5fcf2014-04-15 14:58:45 -0500244 AdjLsa::getData()
akmhoque5a44dd42014-03-12 18:11:32 -0500245 {
246 string adjLsaData;
akmhoque05d5fcf2014-04-15 14:58:45 -0500247 adjLsaData=m_origRouter + "|" + boost::lexical_cast<std::string>(2) + "|"
248 + boost::lexical_cast<std::string>(m_lsSeqNo) + "|"
249 + boost::lexical_cast<std::string>(m_lifeTime);
akmhoque5a44dd42014-03-12 18:11:32 -0500250 adjLsaData+="|";
akmhoque05d5fcf2014-04-15 14:58:45 -0500251 adjLsaData+=boost::lexical_cast<std::string>(m_adl.getSize());
252 std::list<Adjacent> al=m_adl.getAdjList();
akmhoque5a44dd42014-03-12 18:11:32 -0500253 for( std::list<Adjacent>::iterator it=al.begin(); it != al.end(); it++)
akmhoque1fd8c1e2014-02-19 19:41:49 -0600254 {
akmhoque5a44dd42014-03-12 18:11:32 -0500255 adjLsaData+="|";
akmhoque05d5fcf2014-04-15 14:58:45 -0500256 adjLsaData+=(*it).getName();
akmhoque5a44dd42014-03-12 18:11:32 -0500257 adjLsaData+="|";
258 adjLsaData+=boost::lexical_cast<std::string>((*it).getConnectingFace());
259 adjLsaData+="|";
260 adjLsaData+=boost::lexical_cast<std::string>((*it).getLinkCost());
akmhoque1fd8c1e2014-02-19 19:41:49 -0600261 }
akmhoque5a44dd42014-03-12 18:11:32 -0500262 return adjLsaData+"|";
263 }
akmhoque298385a2014-02-13 14:13:09 -0600264
akmhoque5a44dd42014-03-12 18:11:32 -0500265 bool
akmhoque05d5fcf2014-04-15 14:58:45 -0500266 AdjLsa::initializeFromContent(string content)
akmhoque5a44dd42014-03-12 18:11:32 -0500267 {
268 uint32_t numLink=0;
269 nlsrTokenizer nt(content, "|");
akmhoque05d5fcf2014-04-15 14:58:45 -0500270 m_origRouter=nt.getNextToken();
271 if(m_origRouter.empty())
akmhoque1fd8c1e2014-02-19 19:41:49 -0600272 {
akmhoque5a44dd42014-03-12 18:11:32 -0500273 return false;
akmhoque1fd8c1e2014-02-19 19:41:49 -0600274 }
akmhoque5a44dd42014-03-12 18:11:32 -0500275 try
akmhoque1fd8c1e2014-02-19 19:41:49 -0600276 {
akmhoque05d5fcf2014-04-15 14:58:45 -0500277 m_lsType=boost::lexical_cast<uint8_t>(nt.getNextToken());
278 m_lsSeqNo=boost::lexical_cast<uint32_t>(nt.getNextToken());
279 m_lifeTime=boost::lexical_cast<uint32_t>(nt.getNextToken());
akmhoque5a44dd42014-03-12 18:11:32 -0500280 numLink=boost::lexical_cast<uint32_t>(nt.getNextToken());
akmhoque1fd8c1e2014-02-19 19:41:49 -0600281 }
akmhoque5a44dd42014-03-12 18:11:32 -0500282 catch(std::exception &e)
akmhoque1fd8c1e2014-02-19 19:41:49 -0600283 {
akmhoque5a44dd42014-03-12 18:11:32 -0500284 return false;
akmhoque2bb198e2014-02-28 11:46:27 -0600285 }
akmhoque5a44dd42014-03-12 18:11:32 -0500286 for(int i=0; i< numLink; i++)
akmhoque2bb198e2014-02-28 11:46:27 -0600287 {
akmhoque5a44dd42014-03-12 18:11:32 -0500288 try
289 {
290 string adjName=nt.getNextToken();
291 int connectingFace=boost::lexical_cast<int>(nt.getNextToken());
292 double linkCost=boost::lexical_cast<double>(nt.getNextToken());
293 Adjacent adjacent(adjName, connectingFace, linkCost, 0, 0);
akmhoque05d5fcf2014-04-15 14:58:45 -0500294 addAdjacent(adjacent);
akmhoque5a44dd42014-03-12 18:11:32 -0500295 }
296 catch( std::exception &e )
297 {
298 return false;
299 }
akmhoque1fd8c1e2014-02-19 19:41:49 -0600300 }
akmhoque5a44dd42014-03-12 18:11:32 -0500301 return true;
302 }
akmhoque298385a2014-02-13 14:13:09 -0600303
304
akmhoque5a44dd42014-03-12 18:11:32 -0500305 void
akmhoque05d5fcf2014-04-15 14:58:45 -0500306 AdjLsa::addNptEntries(Nlsr& pnlsr)
akmhoque5a44dd42014-03-12 18:11:32 -0500307 {
308 if ( getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
akmhoque1fd8c1e2014-02-19 19:41:49 -0600309 {
akmhoque5a44dd42014-03-12 18:11:32 -0500310 pnlsr.getNpt().addNpteByDestName(getOrigRouter(), getOrigRouter(),pnlsr);
akmhoque1fd8c1e2014-02-19 19:41:49 -0600311 }
akmhoque5a44dd42014-03-12 18:11:32 -0500312 }
akmhoque298385a2014-02-13 14:13:09 -0600313
314
akmhoque5a44dd42014-03-12 18:11:32 -0500315 void
akmhoque05d5fcf2014-04-15 14:58:45 -0500316 AdjLsa::removeNptEntries(Nlsr& pnlsr)
akmhoque5a44dd42014-03-12 18:11:32 -0500317 {
318 if ( getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
akmhoque1fd8c1e2014-02-19 19:41:49 -0600319 {
akmhoque5a44dd42014-03-12 18:11:32 -0500320 pnlsr.getNpt().removeNpte(getOrigRouter(), getOrigRouter(),pnlsr);
akmhoque1fd8c1e2014-02-19 19:41:49 -0600321 }
akmhoque5a44dd42014-03-12 18:11:32 -0500322 }
akmhoque298385a2014-02-13 14:13:09 -0600323
324
325
akmhoque5a44dd42014-03-12 18:11:32 -0500326 std::ostream&
327 operator<<(std::ostream& os, AdjLsa& aLsa)
328 {
329 os<<"Adj Lsa: "<<endl;
330 os<<" Origination Router: "<<aLsa.getOrigRouter()<<endl;
331 os<<" Ls Type: "<<(unsigned short)aLsa.getLsType()<<endl;
332 os<<" Ls Seq No: "<<(unsigned int)aLsa.getLsSeqNo()<<endl;
333 os<<" Ls Lifetime: "<<(unsigned int)aLsa.getLifeTime()<<endl;
334 os<<" No Link: "<<(unsigned int)aLsa.getNoLink()<<endl;
335 os<<" Adjacents: "<<endl;
336 int i=1;
337 std::list<Adjacent> al=aLsa.getAdl().getAdjList();
338 for( std::list<Adjacent>::iterator it=al.begin(); it != al.end(); it++)
akmhoque1fd8c1e2014-02-19 19:41:49 -0600339 {
akmhoque5a44dd42014-03-12 18:11:32 -0500340 os<<" Adjacent "<<i<<": "<<endl;
akmhoque05d5fcf2014-04-15 14:58:45 -0500341 os<<" Adjacent Name: "<<(*it).getName()<<endl;
akmhoque5a44dd42014-03-12 18:11:32 -0500342 os<<" Connecting Face: "<<(*it).getConnectingFace()<<endl;
343 os<<" Link Cost: "<<(*it).getLinkCost()<<endl;
akmhoque1fd8c1e2014-02-19 19:41:49 -0600344 }
akmhoque5a44dd42014-03-12 18:11:32 -0500345 return os;
346 }
akmhoqueb1710aa2014-02-19 17:13:36 -0600347
348}//namespace nlsr